Recognitions:
Homework Help

## Inverting function that includes modulus

 Quote by SpectraCat No, that's wrong .. I gave an example of why, and Hurkyl gave another example.
 Quote by SpectraCat Not sure what you mean .. my point was that the declaration "extern const" within a namespace has replaced the role that "static const" declarations at file scope used to play.
You won't get a linker error on a const variable.
There is no space allocated for it.
It is expanded similar to a macro (but not by the preprocessor).

Btw, I just edited my previous post, since I checked.
You do get a syntax error on a non-static const variable inside a class, but I think that's only a limitation of the syntax and not of the principle involved.

 Quote by SpectraCat I have noticed that one of our debating partners is a moderator, so as long as he is chiming in too, I guess we are fine .
True! So if the OP doesn't chime in too and if he feels it's necessary, he can move the discussion to a separate thread. ;)

Recognitions:
Gold Member
Staff Emeritus
 Quote by I like Serena You won't get a linker error on a const variable.
Have you tried it?

 There is no space allocated for it.
Just to check before I spend more effort on this discussion, are you familiar with the following?
Code:
// main.c
#include <stdlib.h>
extern const int x;
int main() {
}
Code:
// other.c
const int x = 3;

Recognitions:
Gold Member
Staff Emeritus
 Quote by I like Serena You do get a syntax error on a non-static const variable inside a class
The two options have very different semantics. Consider the two classes:

Code:
class immutable_integer
{
private:
const int data;
public:
immutable_integer(int arg):data(arg) {}
operator int() const { return data; }
};
Code:
class wrapper_around_three
{
private:
static const int data = 3;
public:
operator int() const { return data; }
};
The meaning of the data field in the two cases is very different.

Recognitions:
Homework Help
 Quote by Hurkyl Have you tried it?
Of course I have.
Just to check before I spend more effort on this discussion, have you?

To make it explicit, try this:
Code:
a.cpp:
const int i = 10;

b.cpp:
const int i = 20;
$g++ -ansi -pedantic -Wall -Wextra a.cpp b.cpp dummy_main.cpp You'll find that there are no warnings or errors! If you want I can bring out the heavy guns, and quote the standard. But I have to search for it again, and it's not easy to read. ;)  Quote by Hurkyl Just to check before I spend more effort on this discussion, are you familiar with the following? extern const int x; This is where you replace the redundant "static" with "extern", specifying that you want external linkage (I already made a note of that in an earlier post)! This is useful when you have a "const" complex object of which you do not want its implementation to be globally visible and/or that you want to initialize only once.  Quote by Hurkyl The two options have very different semantics. Consider the two classes: Yes, here you can force the const variable to have external linkage by not initializing it within the class. And if you do initialize it, the language forces you (in this case!) to put static in front of it. Cheers! Recognitions: Gold Member Science Advisor Staff Emeritus  Quote by I like Serena Of course I have. Just to check before I spend more effort on this discussion, have you? I have before -- at least I'm pretty sure this test. (I have to download a compiler if I want to test it today, otherwise I would have tested before posting) Also, IIRC it actually makes a difference between compiling each unit separately and linking them versus throwing them all on a single gcc command line. I can't remember if it matters (when testing with gcc) whether you actually use the variable for some purpose.  If you want I can bring out the heavy guns, and quote the standard. But I have to search for it again, and it's not easy to read. ;) I have a copy of the C and C++ standards at work but not at home. If you know of a link it wouldbe greatly appreciated.  This is where you replace the redundant "static" with "extern", specifying that you want external linkage! You misunderstand immutable_integer; the storage class of data is neither static nor external. Instead, it is an instance variable -- each instance of the class gets its own version of the field data, each initialized to the value passed to the constructor. const is a CV qualifier, not a storage class. Recognitions: Homework Help  Quote by Hurkyl I have before -- at least I'm pretty sure this test. (I have to download a compiler if I want to test it today, otherwise I would have tested before posting) Also, IIRC it actually makes a difference between compiling each unit separately and linking them versus throwing them all on a single gcc command line. I can't remember if it matters (when testing with gcc) whether you actually use the variable for some purpose. No, for g++ it does not matter if you put them on a single command line. And no, it does not matter whether you actually use the variable for some purpose - the compiler does not "know" whether you'd make an external reference to it. And I only made this example to prove my point - I use non-static const variables in header files at work.  Quote by Hurkyl I have a copy of the C and C++ standards at work but not at home. If you know of a link it wouldbe greatly appreciated. If you google it, you'll find a quick hit on a draft 1996 standard. I tend to use it for quick reference, especially since concepts like these have not changed since the C90 standard.  Quote by Hurkyl You misunderstand immutable_integer; the storage class of data is neither static nor external. Instead, it is an instance variable -- each instance of the class gets its own version of the field data, each initialized to the value passed to the constructor. const is a CV qualifier, not a storage class. You're right, sorry, I did not read carefully. You did not define external linkage, but only the CV qualifier. Storage duration in this case is the same as the class instance.  Recognitions: Gold Member Science Advisor Staff Emeritus I did your test -- I do get a linker error with gcc 3.4.4 as I predicted. (and you're right -- it fails whether or not I build the program all at once or whether I do it one compilation unit at a time and link) I get a linker error with g++ 3.4.4 if and only if main.cc actually references the variable x. (using an extern const int x; prototype, of course) Recognitions: Homework Help  Quote by Hurkyl I did your test -- I do get a linker error with gcc 3.4.4 as I predicted. (and you're right -- it fails whether or not I build the program all at once or whether I do it one compilation unit at a time and link) I get a linker error with g++ 3.4.4 if and only if main.cc actually references the variable x. (using an extern const int x; prototype, of course) All right, I repeated your test. And yes, I get a linker error too: undefined reference to i'. Which I predicted as well! I'm using g++ 4.4.3. Do you mean to say you get a different linker error?  Recognitions: Gold Member Science Advisor Staff Emeritus Whoops, I hadn't noticed that g++ and gcc gave me different errors. Recognitions: Homework Help  Quote by Hurkyl Whoops, I hadn't noticed that g++ and gcc gave me different errors. Just tried it with gcc, which works since the code is also C. But I get the same linker error: undefined reference, as expected. What do you get?  Recognitions: Gold Member Science Advisor Staff Emeritus (Each line is a separate file) Code: $ echo *.c f1.c f2.c main.c $cat *.c const int x = 0; const int x = 10; int main() { }$ gcc *.c /tmp/ccuq04L9.o:f2.c:(.rdata+0x0): multiple definition of _x' /tmp/ccArQr4j.o:f1.c:(.rdata+0x0): first defined here collect2: ld returned 1 exit status (try renaming your *.cpp files to *.c before running the gcc test. gcc infers to compile as C++ when seeing the extension *.cc or *.cpp, along with some others. Or use gcc -x c *.cpp. The -x c specifies to treat the files as C files)

Recognitions:
Homework Help
 Quote by Hurkyl (try renaming your *.cpp files to *.c before running the gcc test. gcc infers to compile as C++ when seeing the extension *.cc or *.cpp, along with some others. Or use gcc -x c *.cpp. The -x c specifies to treat the files as C files)

Of course, I have the same linker error now.
I didn't know that this was different for C though...
 Recognitions: Gold Member Science Advisor Staff Emeritus If it makes you feel better, I didn't know it was different for C++. I knew some things were different, but hadn't really learned what. (The few times I run into problems, it's usually quicker to guess-and-check the right way to do things than to actually look things up)

Mentor
 Quote by cepheid That could very well be it, because it is acting as though the first term on the right hand side of: phi = (enc - enc_ref)/CNTS_PER_DEG + phi_ref is evaluating to zero, and hence it thinks the current angle is always phi_ref. Perhaps that could be due to some order of operations problem. I will try that and report back!
I am reporting back to say that this fix worked. In hindsight it is obvious that what I entered before was resulting in first dividing by 72,000, and then dividing by 360. Not the intended effect at all.

Okkaaay, as for the rest of this discussion, although I am not interested in delving as deep into the vagaries of C as you guys are, I would like to know one thing: why are constants preferred to defines in this situation?

Finally, I have another question along similar lines. I need to do this again for my device's other axis of rotation (call this angle theta if you like, and call the encoder position y). Now, theta is physically restricted to lie between -10 deg and +89 deg (and I am required to use this coordinate system, since the zero point needs to be with reference to something external, namely the horizon). A range of 99 degrees corresponds to a range in encoder values of only 19,800 counts.

After some trial and error, I decided that there were three (mutually exclusive) possibilities, depending on the values of y0 and theta0 (neither of which are under my control, but depend on the system orientation and stored position at startup):

1. the encoder values would be monotonic throughout the range of motion

2. the encoder reference position y0 would be large enough and/or the reference angle theta0 would be far enough from the maximum angle that as you increased the angle, you'd eventually exceed 71,999, and wrap back around. This would cause the highest angles to evaluate to large and negative values, requiring addition of 360 degrees to them.

3. the encoder reference position y0 would be small enough and/or the reference angle theta0 would be far enough from the minimum angle that as you decreased the angle, you'd eventually go below 0, and wrap back around. This would cause the lowest angles to evaluate to large positive values, requiring subtraction by 360.

Based on these scenarios, I concluded that I could just use the same equation as before:

$$\theta(y) = \left[ (y-y_0)\left(\frac{360^\circ}{72,000}\right) + \theta_0 \right]~\textrm{mod}~360^\circ$$

Using this formula:

- the positive angles (those between 0 and 89) would always turn out right

- the negative angles would have 360 added to them, and this would have to be "undone." Since the formula would produce large positive values (between 350 and 359 -- much larger than the maximum angle) for the negative angles, I added a line that said if (theta > 89.0) theta -= 360.0;

Does anyone see any errors?

Recognitions:
Homework Help
 Quote by cepheid I am reporting back to say that this fix worked. In hindsight it is obvious that what I entered before was resulting in first dividing by 72,000, and then dividing by 360. Not the intended effect at all.
Nice!

 Quote by cepheid Okkaaay, as for the rest of this discussion, although I am not interested in delving as deep into the vagaries of C as you guys are, I would like to know one thing: why are constants preferred to defines in this situation?

As you have seen, macro's are tricky.
It's very easy for them to behave other than you expect.
What you found is just one of the many pitfalls.

In particular with constants you need to specify the type, which means additional checks are made by the compiler that everything is in order.
This is called "type safety".

 Quote by cepheid Finally, I have another question along similar lines. ... Does anyone see any errors?
I don't quite understand what you are doing (your text is too long ;)).
If I understand correctly you want to map a range of encoder values to a range of angle values.
What are those ranges exactly?
And why do you think there might be a problem?

Recognitions:
 Quote by cepheid I am reporting back to say that this fix worked. In hindsight it is obvious that what I entered before was resulting in first dividing by 72,000, and then dividing by 360. Not the intended effect at all.
Those silly #define-induced logic errors always are obvious in hindsight ...

 Okkaaay, as for the rest of this discussion, although I am not interested in delving as deep into the vagaries of C as you guys are, I would like to know one thing: why are constants preferred to defines in this situation?
As was already pointed out, type safety is one reason ... the other is what you already experienced ... the macro-preprocessor has one job .. to go through and do text-based find-and-replace of your macros throughout your code. Therefore, it is much less context sensitive than the compiler, and is prone to face-palm-worthy goof ups like the one you experienced.

 Finally, I have another question along similar lines. I need to do this again for my device's other axis of rotation (call this angle theta if you like, and call the encoder position y). Now, theta is physically restricted to lie between -10 deg and +89 deg (and I am required to use this coordinate system, since the zero point needs to be with reference to something external, namely the horizon). A range of 99 degrees corresponds to a range in encoder values of only 19,800 counts. ... depending on the values of y0 and theta0 (neither of which are under my control, but depend on the system orientation and stored position at startup)
Before answering, I need to know whether or not y0 and theta0 are truly independent, or if they are correlated ... actually this question holds for x0 and phi0 as well.In other words, when you start up, if you run the value of x0 through your formula, do you get phi0, and vice-versa? Or are the encoder and the "true" angle values unrelated at startup?

The reason I ask is that the formula I came up with before assumes that they are uncorrelated. It should be possible to use a much simpler formula if the values are correlated.

A similar question has to do with the encoder ... is it a physical entity, or is it just a theoretical construct to help you control your device (telescope?) with a computer?

Mentor
 Quote by SpectraCat Before answering, I need to know whether or not y0 and theta0 are truly independent, or if they are correlated ... actually this question holds for x0 and phi0 as well.In other words, when you start up, if you run the value of x0 through your formula, do you get phi0, and vice-versa? Or are the encoder and the "true" angle values unrelated at startup?
Phi0 and x0 are independent. Same for y0 and theta0. At the startup of my program, I have to enter the reference angles. I can choose whatever phi0 I want, because I can choose whatever coordinate system I want for that direction (azimuth). In contrast, I have to measure the starting theta0 relative to a fixed coordinate system (for elevation) and enter it in. The encoder positions x0 and y0 at startup are outside of my control, because the last known positions are "remembered" by the readout electronics from previous runs of the program (unless if I power cycle everything). So I don't get to choose which values of x0 and y0 map to my chosen/measured phi0 and theta0.

 Quote by SpectraCat The reason I ask is that the formula I came up with before assumes that they are uncorrelated. It should be possible to use a much simpler formula if the values are correlated.
I'm pretty happy with the formula I stated in post #31. It seems to hold up under testing so far. In fact, I'm convinced that if the reasoning that I outlined in those three enumerated points in that post is correct, then the formula (with the correction for negative angles) is also correct. So it was mostly just that reasoning on which I wanted feedback.

 Quote by SpectraCat A similar question has to do with the encoder ... is it a physical entity, or is it just a theoretical construct to help you control your device (telescope?) with a computer?
The encoders are real devices. As I stated before, they are incremental encoders with a resolution of 72,000 counts per revolution. And yes, my device is a scanning mount for a cryostat that houses a microwave telescope.

 Similar discussions for: Inverting function that includes modulus Thread Forum Replies General Math 3 Advanced Physics Homework 3 Precalculus Mathematics Homework 1 General Math 4 General Math 3