Question on "if" statements...

D

David Cleaver

Hello all,

I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself? Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there. I could use more in the
future, and for the purposes of my program, I don't want to use less. I
know that do_stuff should be executed because I have run test cases
where it should have been run. But it just keeps goin to the "else"
statement. I'm probably way off base thinking C is the problem. If you
want to know about my setup here it is:
WinXP, P4 1.8, Compiler: DJGPP using gcc v3.0.3

So, am I expecting too much out of the if statement? Am I using the if
statement incorrectly up there? Any advice or help in this regard is
greatly appreciated.

-David C.
 
A

Arthur J. O'Dwyer

I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself?

There is some limitation given by the official standard in that
it specifies a "minimal limit" for the depth of expressions (if I
recall correctly). That is, the Standard says how many "ands" an
'if' statement *must* be able to hold; but any decent implementation
will be able to handle as many as you can throw at it (up to the
available memory on your machine).
Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed.

Have you considered the possibility that the body of the 'if' is
never executed because the big complicated condition is, in fact,
*false*? Have you tried running the 'if' statement in a program
in which "table001..030" and "b" are entirely filled with 0x1f
values? What values are stored in those tables during the run of
your current program?

[OT: And why do you need so many tables anyway, and why not use
a "for" loop to check all of them, rather than hard-code the
number of tables into your program?]

-Arthur
 
R

Ralf Damaschke

David said:
Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
[...]

The formatting is a bit misleading. This is parsed as:

if (table001[n[0]][x[0]>>5] & (b[x[0]&0x1f] != 0) &&
....

Ralf
 
W

William L. Bahn

David Cleaver said:
if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the decision
for you. This is frequently not a good idea.
 
S

Stephen Sprunk

David Cleaver said:
I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself? Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

First, the order of operations isn't clear in your expression. As a rule of
thumb, if the reader needs to look up the rules to figure out what an
expression does, you should add parens to make it clear what you intended.
Second, judicious use of spaces makes complex expressions more readable.
Third, the test against zero is unnecessary since that's implied with
logical operators.

if ( ( table001[n[0]][x[0]>>5] & b[x[0]&0x1f] ) &&
( table002[n[1]][x[1]>>5] & b[x[1]&0x1f] ) &&
( table003[n[2]][x[2]>>5] & b[x[2]&0x1f] ) &&
... &&
( table030[n[29]][x[29]>>5] & b[x[29]&0x1f] ) )
{
do_stuff();
}//end if
else do_other_stuff();

I don't know if this code is any more correct, but it's a lot easier to read
and debug, which others (and you, later on) will appreciate.

S
 
C

Chris Dollin

William said:
David Cleaver said:
if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the
decision for you.

The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.

On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y". [Well, actually,
I wouldn't write a monster expression with 30 lines in it embedded in
an if-expression at all, but that's a separate issue.]

[1] defined implicitly by the grammar in the Standard, but expressible
as precedence order.

[2] certain.
 
R

Richard Bos

Chris Dollin said:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".

No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...

Richard
 
C

Chris Dollin

Richard said:
Chris Dollin said:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".

No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...

That's the point - I believe that the OP wrote "X & Y != 0" and *meant*
"(X & Y) != 0", which can be written as "X & Y" in conditional context
with the same effect, where it avoids all questions of the relative
precedence of & and !=. Hence "in this case".
 
C

Chris Dollin

Chris said:
The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.

Erm, in my haste I did not make it clear that one should still
write expressions for clarity - there's a difference between knowing
the C precedence levels, assuming the reader will know them, and
writing for the IOCC.
 
D

David Cleaver

Chris said:
David said:
if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the
decision for you.

The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.

On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y". [Well, actually,
I wouldn't write a monster expression with 30 lines in it embedded in
an if-expression at all, but that's a separate issue.]

Thank you very much. I never thought about there being a precedence
issue. I've fixed my code to better reflect what I was doing. [And I
was wanting (x & y), not x & (y != 0), I've changed it all to be of the
form (x & y) && ...]

May I ask, without making those tables 3-dimensional, how could I make
that code segment look better? Someone earlier in this thread mentioned
putting it into a for loop, but I can't see how that'd be possible with
30 different tables.

Anyway, I wanted to thank everyone for their suggestions so far. I'm
really glad a place like this exists where people can come for help.
Thanks again.

-David C.
[1] defined implicitly by the grammar in the Standard, but expressible
as precedence order.

[2] certain.
 
W

William L. Bahn

Chris Dollin said:
William said:
David Cleaver said:
if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the
decision for you.

The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1].

The compiler is the one that is making the decision as the compiler is the
one that is compiling the code. I'm not saying that the compiler has any
choice in the decision it makes - and I understand the point you are making.
Please recognize that just saying something like "the compiler is making the
decision" is anthropomorphisizing (sp?) to begin with and the main point is
not who (or what) is making the decision but rather that the OP is NOT
making the decision.
Having lots of conditions separated
by && should be no problem at all.

Really? So something like

if( a || b && c || d )

should present no difficulties and compile the way that it was most likely
meant?
 
W

William L. Bahn

Richard Bos said:
Chris Dollin said:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".

No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...

I think he is saying that

"X & Y"

would produce the same results that were almost certainly intended by

"X & Y !=0"

had the OP used parens to make it explicit

"(X & Y) != 0"
 
O

Old Wolf

David Cleaver said:
I'm writing a program which needs to check a bunch of
conditions all at the same time (basically).

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there.

Others have pointed out the reason this code doesn't work. But I cannot
think of a reason why you do not go:

int i;
for (i = 0; i < 30; ++i)
if (table[n][x>>5] & b[x&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}

In case you didn't like this for runtime-speed reasons, note that
this is at least as fast as your version
(your version unoptimised is slow because there are 5 array index
lookups on each line, whereas even the worst compiler will optimise
the loop to be incrementing 1 or 2 pointers, with fixed offsets
from that pointer. This will work even better if n, x, and b, are
all the same size of object).

If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).

Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).
 
D

David Cleaver

Old said:
David said:
I'm writing a program which needs to check a bunch of
conditions all at the same time (basically).

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there.

Others have pointed out the reason this code doesn't work. But I cannot
think of a reason why you do not go:

int i;
for (i = 0; i < 30; ++i)
if (table[n][x>>5] & b[x&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}


Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right? Anyway, I understand what you are saying, but please read on.
In case you didn't like this for runtime-speed reasons, note that
this is at least as fast as your version
(your version unoptimised is slow because there are 5 array index
lookups on each line, whereas even the worst compiler will optimise
the loop to be incrementing 1 or 2 pointers, with fixed offsets
from that pointer. This will work even better if n, x, and b, are
all the same size of object).

Yes, right now n, x, and b are all arrays of ints. I want this to be as
fast as possible because I'm using it for math applications.

For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants? And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x&0x1f) - 1))?
instead of:
table[][] & b[x&0x1f]
I don't know which would be faster/better.

Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better? If its ok, then read on below.
If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).

Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size? And all my tables are
of different sizes. Would the array of pointers look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
....
Or would you do it a different way? I've never set up an array of
pointers to other arrays before. At least, not where all the other 2D
arrays are of differing sizes. Now that I think about it, since its an
array of pointers to 2D arrays, does it have to be int ***table? Or was
I right above?
Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).

Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.

-David C.
 
A

Arthur J. O'Dwyer

Old said:
int i;
for (i = 0; i < 30; ++i)
if (table[n][x>>5] & b[x&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}


Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right?


Nope. Old Wolf's code checks to make sure all the tests are passed;
if they are, then 'i == 30' will be true, and 'do_stuff' will get
executed. Otherwise (if one of the tests failed), it will print the
error message and then 'do_other_stuff'.
For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants?

If you define 'n' as an array of const int, your compiler will be
able to determine the best way to generate code for it. Your writing
#define n_0 42
#define n_1 23
#define n_2 11
is definitely *NOT* the right approach.
And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x&0x1f) - 1))?


You realize that 32-1 is 31, right? :)

table[ ][ ] & (1<<(31 - (x & 31)))?
instead of:
table[][] & b[x&0x1f]
I don't know which would be faster/better.


It depends. Run a profile if you care so much, but I'd bet you
a large amount that the difference will *not* be significant in the
long run. Micro-optimization is usually Not A Good Idea, *even*
in math programs, and *certainly* not until you have a working
program.
Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better?

comp.programming is a more general group that can answer surprisingly
in-depth questions about individual architectures, because it's frequented
by a number of working programmers. (Not that c.l.c isn't; but
processors aren't on topic here.) And then of course there are the
compiler-specific groups like gnu.gcc.help.

If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).

Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size?

That doesn't make sense to me. Arrays are just arrays. Do you
mean you thought that once you had declared one 30-element array in
your program, all the other arrays had to have 30 elements too? That
would just be masochistic!
And all my tables are of different sizes. Would the array of pointers
look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
...

Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
...

Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).

Definitely. Unsigned for bitwise operations, always!
Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.

I still haven't understood why you need to have those thirty
tables. Are you legally prevented from telling us what you're
trying to do, or what?

-Arthur
 
D

David Cleaver

Arthur J. O'Dwyer said:
Old said:
int i;
for (i = 0; i < 30; ++i)
if (table[n][x>>5] & b[x&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}


Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right?


Nope. Old Wolf's code checks to make sure all the tests are passed;
if they are, then 'i == 30' will be true, and 'do_stuff' will get
executed. Otherwise (if one of the tests failed), it will print the
error message and then 'do_other_stuff'.


But I thought that "break" would break out of current loop that it is
in, not that it would break out of the if statement. The way I see it:
for (i = 0; i < 30; ++i)
if (table[n][x>>5] & b[x&0x1f])
break;

when it gets to "if (...)", if the "..." evaluates to true, then the
"break" instruction is executed which breaks it out of the for loop,
right? So, if at i=0 it were true, none of the other conditions would
be tested. I wanted it to be:
for (i = 0; i < 30; i++)
{
if (table[n][x>>5] & b[x&0x1f])
continue; //if true, make sure the next one is true...
else
break; //else, it was false and we need to stop checking...
}//end for
For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants?

If you define 'n' as an array of const int, your compiler will be
able to determine the best way to generate code for it. Your writing
#define n_0 42
#define n_1 23
#define n_2 11
is definitely *NOT* the right approach.

I'm sorry, I didn't exactly mean that kind of constant. I was thinking
of declaring 30 integers where I would just store each of the n[k]
values. Hoping that just using the int would be faster than an "array
lookup".
And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x&0x1f) - 1))?


You realize that 32-1 is 31, right? :)

table[ ][ ] & (1<<(31 - (x & 31)))?


Heh, yes, I do realize 32-1 is 31. I was trying to show what was going
on better, but it looks better your way.
instead of:
table[][] & b[x&0x1f]
I don't know which would be faster/better.


It depends. Run a profile if you care so much, but I'd bet you
a large amount that the difference will *not* be significant in the
long run. Micro-optimization is usually Not A Good Idea, *even*
in math programs, and *certainly* not until you have a working
program.


Ah, well, thanks to the earlier suggestions my program is now up and
running perfectly. Now I'm trying to tweak as much as possible to run
it as fast as possible.
Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better?

comp.programming is a more general group that can answer surprisingly
in-depth questions about individual architectures, because it's frequented
by a number of working programmers. (Not that c.l.c isn't; but
processors aren't on topic here.) And then of course there are the
compiler-specific groups like gnu.gcc.help.
If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).

Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size?

That doesn't make sense to me. Arrays are just arrays. Do you
mean you thought that once you had declared one 30-element array in
your program, all the other arrays had to have 30 elements too? That
would just be masochistic!

No, I thought that if you had a 3D array, like arr[x][y][z], that y and
z had to be the same for all the different values of x. I thought of it
as a 3D array because its an array of pointers to 2D arrays.
And all my tables are of different sizes. Would the array of pointers
look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
...

Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

Thank you for the clarification.
would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
...

I don't think I want to go down the dynamic route, it won't be too
difficult to do it the other way.
Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).

Definitely. Unsigned for bitwise operations, always!
Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.

I still haven't understood why you need to have those thirty
tables. Are you legally prevented from telling us what you're
trying to do, or what?

-Arthur

Lol, ok, no I'm not prevented from telling you what this is because I am
programming this for myself. Its a math program that attempts to factor
a number N using the difference of squares method. I want to solve N =
x^2 - y^2. I do this by looking at values of (x^2 - N)%p [p a prime]
and then see if that is a possible perfect square mod p. (ie, I'm
looking at S = x^2 - N, to see if S is a possible perfect square mod p.
Then I do this for lots of values of p, each of which reduces the number
of candidates in half. So, looking at 30 different primes reduces the
number of candidates by about 1/(2^30), so this is why I might use more
tables in the future.)

I edited the code a little so it would look better in this newsgroup and
because originally I didn't want to give too much away. Anyway, heres
what my actual (and working thanks to you all) code looks like:
while (1)
{
if ((table003[nmodp[0]][0] & b[xmodp[0]]) &&
(table005[nmodp[1]][0] & b[xmodp[1]]) &&
(table007[nmodp[2]][0] & b[xmodp[2]]) &&
(table011[nmodp[3]][0] & b[xmodp[3]]) &&
...
(table113[nmodp[28]][xmodp[28]>>5] & b[xmodp[28]&0x1f]) &&
(table127[nmodp[29]][xmodp[29]>>5] & b[xmodp[29]&0x1f]))
{
multiply(x, x, x_squared);
subtract(x_squared, test_num, x2_minus_n);

if (nroot(x2_minus_n, 2, y))
{ we_have_a_factor();}//end if
//if true we're done and we break out...
}//end if

incr(x, 1, x);
for (loop_var = 0; loop_var < num_primes; loop_var++)
xmodp[loop_var] = (xmodp[loop_var] + 1)%i_primes[loop_var];
}//end while

I've precomputed those tables. Originally those tables were filled with
int's that held either 0 or 1. Then I rewrote it to pack those 0's and
1's into 32 bit ints (I know its not that portable, but so far its only
running on my system) For a while the if statements looked like:
if ((table003[nmodp[0]][xmodp[0]/32] & b[xmodp[0]%32]) && ...
However, I know from experience that / and % are very slow operations,
so I did a few calculations and found that >>5 and &0x1f would give the
same resutls only lots faster. So, thats why you see a bunch of that in
the above if statements. Also, when p < 32 I don't have to do /32 or
%32 because it just return the same number. (in case you were wondering)

I haven't rewritten it yet to reflect the table[][][] nomenclature, but
I will very soon. Thanks again everyone for all your help.

-David C.
 
S

Stephen Sprunk

David Cleaver said:
For a while the if statements looked like:
if ((table003[nmodp[0]][xmodp[0]/32] & b[xmodp[0]%32]) && ...
However, I know from experience that / and % are very slow operations,
so I did a few calculations and found that >>5 and &0x1f would give the
same resutls only lots faster. So, thats why you see a bunch of that in
the above if statements. Also, when p < 32 I don't have to do /32 or
%32 because it just return the same number. (in case you were wondering)

A decent compiler should do those optimizations (aka strength reduction) for
you, and using /32 and %32 in your source better explains to other readers
what you're trying to do.

S
 
D

David Cleaver

Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
...

Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type
blah.c:71: warning: assignment from incompatible pointer type
blah.c:72: warning: assignment from incompatible pointer type
....
blah.c:99: warning: assignment from incompatible pointer type
blah.c:172: subscripted value is neither array nor pointer

here is line 172:
if (table[nmodp][xmodp/32] & b[xmodp%32])

What does that mean? What have I done wrong? I'm not seeing it. Can
someone else tell me if I have programmed something wrong or if this
code is just confusing the compiler? Thanks for any help.

-David C.
 
A

Arthur J. O'Dwyer

Arthur J. O'Dwyer said:
int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO

Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type

This tells us that '&table003' is not a pointer to int. I suppose
I wasn't thinking quite clearly when I wrote the code above; obviously,
if 'table001' etc. are arrays[foo] of int, then '&table001' is a
pointer to array[foo] of int, not a pointer to int as we want. So,
drop the '&'s. Done and done.
blah.c:172: subscripted value is neither array nor pointer

here is line 172:
if (table[nmodp][xmodp/32] & b[xmodp%32])


Let's see... You're taking 'table', an array of pointers to int,
and subscripting it with '' to yield a single pointer to int.
Then you're subscripting that with '[nmodp]' to yield a single
int. Then you're trying to subscript *that* with '[xmodp/32]'!
That's the error: your code doesn't make any sense. You can't
use an 'int' as if it were a pointer. Why did you change the code
you had? --- this new code seems to do something different!
What does that mean? What have I done wrong? I'm not seeing it. Can
someone else tell me if I have programmed something wrong or if this
code is just confusing the compiler? Thanks for any help.

At this point, all I can tell you is to post a minimal complete,
compilable example that demonstrates your problem, and let the
regulars critique it. You're doling things out in bits and pieces,
and that simply won't fix your errors. There's no need to be so
secretive about things; if you're having problems working with the
type system in C, then you'll need to explain what types you're using
to define your variables. If you're having trouble with control
structures, you'll need to explain the structure of your program.
As you seem to be having trouble with all of this, you'd better
post it all.

(And by "all" I mean a program of maybe 20 to 60 lines with
commentary that tells what the problem is. With the global
variables, #includes and everything. You'll be glad you did.)

HTH,
-Arthur
 
D

David Cleaver

Arthur J. O'Dwyer said:
At this point, all I can tell you is to post a minimal complete,
compilable example that demonstrates your problem, and let the
regulars critique it. You're doling things out in bits and pieces,
and that simply won't fix your errors. There's no need to be so
secretive about things; if you're having problems working with the
type system in C, then you'll need to explain what types you're using
to define your variables. If you're having trouble with control
structures, you'll need to explain the structure of your program.
As you seem to be having trouble with all of this, you'd better
post it all.

(And by "all" I mean a program of maybe 20 to 60 lines with
commentary that tells what the problem is. With the global
variables, #includes and everything. You'll be glad you did.)

HTH,
-Arthur

OK, this code is compilable, but it requires the miracl
arbitrary-size-number library to run. If you want me to comment out all
the miracl code, I can do that and then repost. Right now it is
compiling except for the error I mentioned earlier. Actually, I fixed
the last error and now it is just giving all of the warnings. This file
has a #include "arrays.h", if you want to see that I can post it later.
In the code I give an example of what the beginning of arrays.h looks
like.

Should I "inline" the code or "attach" it to this message? If I inline
it, it will definitely not look pretty when it gets through to the other
side. If I attach it, some NG's remove attachments. Please let me know
which way is better.

-David C.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Lexical Analysis on C++ 1
For loop with if statement 3
Need an if statement 8
First time question 1
Minimum Total Difficulty 0
It doesn't see my 'if' statements 7
Pythen question 0
Function is not worked in C 2

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top