Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ehnus
Apr 16, 2003

Now you're thinking with portals!

Zombywuf posted:

Your compilers guess as to whether it should inline is probably as good as yours. It's a bit of a black art.

Actually, no. Really lovely compilers like Metrowerks pretty much force you to forego inline functions and use macros to avoid function calls. VC++ and GCC which are far better in this area can still inject unwanted function calls, even when using stronger inline hints like __forceinline.

Adbot
ADBOT LOVES YOU

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

ehnus posted:

Actually, no. Really lovely compilers like Metrowerks pretty much force you to forego inline functions and use macros to avoid function calls. VC++ and GCC which are far better in this area can still inject unwanted function calls, even when using stronger inline hints like __forceinline.

I'd really like to see some kind of evidence to that effect, since I can't imagine GCC or MSVC would fail to inline functions that you request to inline (assuming they can be inlined and all that), unless you're loving around with compiler settings.

ehnus
Apr 16, 2003

Now you're thinking with portals!
I've fought the compilers may times on these fronts, off the top of my head the last time this was specifically an issue was for vectorized trigonometry routines. The only way I could get them inline consistently was to turn them into a macro

Mr VacBob
Aug 27, 2003
Was yea ra chs hymmnos mea
gcc completely or mostly ignores 'inline' if you have optimizations on. Recent (4.3 or after) versions have decent inlining detection, but it was completely messed up before that. You really have to use __attribute__((always_inline)) sometimes.

Regalia
Jun 11, 2007
Sorry if this has been asked before.

How can you get VS2005 to build a project that contains multiple 16-bit asm files and C++ files? I can get each individual file to compile separately; giving me obj files for each, but I can't build the project.

I know it's because I'm using 16-bit assembly because I can build projects with 32-bit assembly just fine. Maybe if there was a way to use the 16-bit linker when building the project?

Any help would be appreciated. Thanks.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Can you set it to target a 16-bit machine in the project properties? It's under Linker -> Advanced.

Regalia
Jun 11, 2007

Avenging Dentist posted:

Can you set it to target a 16-bit machine in the project properties? It's under Linker -> Advanced.

I'm afraid there's no option for a 16-bit machine; only different processor types. E.G. x86, AM33, etc.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

Regalia posted:

Sorry if this has been asked before.

How can you get VS2005 to build a project that contains multiple 16-bit asm files and C++ files? I can get each individual file to compile separately; giving me obj files for each, but I can't build the project.

I know it's because I'm using 16-bit assembly because I can build projects with 32-bit assembly just fine. Maybe if there was a way to use the 16-bit linker when building the project?

Any help would be appreciated. Thanks.

As far as I know know, you actually need to use an old linker, I'm pretty sure there is no switch.

MASM 5.1 has one.

POKEMAN SAM
Jul 8, 2004

Avenging Dentist posted:

Macros are evil, and unless you absolutely have to, it's preferable to use an inline function to enforce type safety and all that good stuff.

The 'macros are evil' is pretty lame, but I understand the type safety argument.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Ugg boots posted:

The 'macros are evil' is pretty lame, but I understand the type safety argument.

I use macros plenty often, but only when I can't use anything else. Sometimes you have to do evil things to get the results you want, but it's something you should be cautious of. That said, you can get the best of both worlds if you're willing to write a few extra lines of code:

code:
#include <iostream>
#include <cassert>
using namespace std;

#define SQUARE_REAL(x) (x)*(x)

#ifdef _DEBUG
	double square_test(double x,double result)
	{
		assert(result == SQUARE_REAL(x));
		return result;
	}
#	define SQUARE(x) square_test(x,(x)*(x))
#else
#	define SQUARE SQUARE_REAL
#endif


int main()
{
	int x=2;
	cout << "SQUARE(x) = " << SQUARE(x++) << endl; // "Works" in release builds, fails on assertion in debug builds
	return 0;
}
Hell, you could probably turn all that into a generic macro if you were so inclined.

bcrules82
Mar 27, 2003

sarehu posted:

Here's an algorithm that scales better with respect to integer size. I don't think it's a good idea to use a macro.

code:
uint32_t evenbits(uint64_t x) {
  x = (x & 0x1111111111111111LL) | ((x & 0x4444444444444444LL) >> 1);
  x = (x & 0x0303030303030303LL) | ((x & 0x3030303030303030LL) >> 2);
  x = (x & 0x000f000f000f000fLL) | ((x & 0x0f000f000f000f00LL) >> 4);
  x = (x & 0x000000ff000000ffLL) | ((x & 0x00ff000000ff0000LL) >> 8);
  x = (x & 0x000000000000ffffLL) | ((x & 0x0000ffff00000000LL) >> 16);
  return (uint32_t) x;
}

sarehu: do you have a reference/document for this? i think i saw that back in school, but i forgot about it. it was part of a lesson on how moving complex bitwise operations from functions to macros can speed up execution dramatically, due to having lots of constant expressions that can be optimized by the preprocessor.

i'm using this for some asic dv code.
my quick and dirty solution was this (32-bit version):
code:
#define BIT(data,bit) (((data) >> (bit)) & 0x1)
#define EVEN_BITS_W(data) ( \
(BIT(data, 0)<< 0) | \
(BIT(data, 2)<< 1) | \
(BIT(data, 4)<< 2) | \
(BIT(data, 6)<< 3) | \
(BIT(data, 8)<< 4) | \
(BIT(data,10)<< 5) | \
(BIT(data,12)<< 6) | \
(BIT(data,14)<< 7) | \
(BIT(data,16)<< 8) | \
(BIT(data,18)<< 9) | \
(BIT(data,20)<<10) | \
(BIT(data,22)<<11) | \
(BIT(data,24)<<12) | \
(BIT(data,26)<<13) | \
(BIT(data,28)<<14) | \
(BIT(data,30)<<15))

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
That macro re-evalutates its first argument 15 times.

Entheogen
Aug 30, 2004

by Fragmaster

Mustach posted:

That macro re-evalutates its first argument 15 times.

doesn't this get done at compile-time, so by the time it compiles its super fast code since it doesn't have to do an extra function call?

vanjalolz
Oct 31, 2006

Ha Ha Ha HaHa Ha
I think the & 0x01 might screw up optimisations.

sarehu
Apr 20, 2007

(call/cc call/cc)

bcrules82 posted:

sarehu: do you have a reference/document for this?

No.. I just made it up on the spot.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

Entheogen posted:

doesn't this get done at compile-time, so by the time it compiles its super fast code since it doesn't have to do an extra function call?
Only if the argument is a constant expression. There still won't be an "extra" function call since the macro just expands to a single statement, but EVEN_BITS_W(f()); expands to
code:
( \
((((f()) >> (0)) & 0x1)<< 0) | \
((((f()) >> (2)) & 0x1)<< 1) | \
((((f()) >> (4)) & 0x1)<< 2) | \
((((f()) >> (6)) & 0x1)<< 3) | \
((((f()) >> (8)) & 0x1)<< 4) | \
((((f()) >> (10)) & 0x1)<< 5) | \
((((f()) >> (12)) & 0x1)<< 6) | \
((((f()) >> (14)) & 0x1)<< 7) | \
((((f()) >> (16)) & 0x1)<< 8) | \
((((f()) >> (18)) & 0x1)<< 9) | \
((((f()) >> (20)) & 0x1)<<10) | \
((((f()) >> (22)) & 0x1)<<11) | \
((((f()) >> (24)) & 0x1)<<12) | \
((((f()) >> (26)) & 0x1)<<13) | \
((((f()) >> (28)) & 0x1)<<14) | \
((((f()) >> (30)) & 0x1)<<15));
which is a lot of calls in a single statement.

Mustach fucked around with this message at 14:44 on Jul 7, 2008

Entheogen
Aug 30, 2004

by Fragmaster

Mustach posted:

Only if the argument is a constant expression. There stil won't be an "extra" function call since the macro just expands to a single statement, but EVEN_BITS_W(f()); expands to
code:
( \
((((f()) >> (0)) & 0x1)<< 0) | \
((((f()) >> (2)) & 0x1)<< 1) | \
((((f()) >> (4)) & 0x1)<< 2) | \
((((f()) >> (6)) & 0x1)<< 3) | \
((((f()) >> (8)) & 0x1)<< 4) | \
((((f()) >> (10)) & 0x1)<< 5) | \
((((f()) >> (12)) & 0x1)<< 6) | \
((((f()) >> (14)) & 0x1)<< 7) | \
((((f()) >> (16)) & 0x1)<< 8) | \
((((f()) >> (18)) & 0x1)<< 9) | \
((((f()) >> (20)) & 0x1)<<10) | \
((((f()) >> (22)) & 0x1)<<11) | \
((((f()) >> (24)) & 0x1)<<12) | \
((((f()) >> (26)) & 0x1)<<13) | \
((((f()) >> (28)) & 0x1)<<14) | \
((((f()) >> (30)) & 0x1)<<15));

oh ok, i see what you are saying. even though macro is replaced by pre-compiler with whatever it is defined to, if data is a function call it will be evaluated 15 times.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

Entheogen posted:

oh ok, i see what you are saying. even though macro is replaced by pre-compiler with whatever it is defined to, if data is a function call it will be evaluated 15 times.

Yes, and what's worse, if that function call has any side-effects, those side-effects will be repeated 15 times.

Imagine what would happen if f() were instead randomGenerator.nextNumber().

more falafel please
Feb 26, 2005

forums poster

Entheogen posted:

oh ok, i see what you are saying. even though macro is replaced by pre-compiler with whatever it is defined to, if data is a function call it will be evaluated 15 times.

Yes, the preprocessor does text substitution only. It's not compiling or optimizing anything.

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Question for the peanut gallery. How do you select a random integer from 0 to something higher than RAND_MAX? (Which I'm assuming is static) I'm guessing we're getting into algorithm territory...

I come from a world where random numbers are floating in (0,1).

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

Triple Tech posted:

Question for the peanut gallery. How do you select a random integer from 0 to something higher than RAND_MAX? (Which I'm assuming is static) I'm guessing we're getting into algorithm territory...

I come from a world where random numbers are floating in (0,1).

If RAND_MAX is a power of two minus one (which it usually is), you can generate two random integers, and consider them to be two halves of an integer with twice the number of bits set in RAND_MAX. This can be done with n random integers representing a number with n times the number of bits in RAND_MAX.

For example, in the GNU C library where RAND_MAX is the largest representable int32_t (231-1, so 31 bits set), you generate two ints with rand(), and then OR them together to build a 62-bit integer which is equally random. (...assuming of course that you have or can create a datatype that can hold a 62-bit integer)

If RAND_MAX is not 2x-1, then this isn't uniform, but there's probably a way around that if you're really interested in that corner case.

Edit: It seems like you know this, but for lurkers in this thread, things that definitely do not work include...

1. Generate two numbers and add them together. Nope, the distribution will be biased in favor of numbers towards the middle of the range. In order to hit the extremes, both numbers must be either large or small simultaneously, which is less likely than other combinations.

2. Generate two numbers and multiply them together. Nope, (among other problems) the distribution will be biased towards even numbers. The result number will be even if either of the original numbers were, making the result three times more likely to be even than odd.

The reason that the OR'ing method works is that if the original PRNG is any good, every bit in the original 31-bit numbers is just as random as every other bit, so if we generate 62 totally random bits, they're still totally random no matter what order we put them in, as long as we don't change them in any way (like by doing math with them).

Smackbilly fucked around with this message at 18:37 on Jul 7, 2008

bcrules82
Mar 27, 2003

Smackbilly posted:

Yes, and what's worse, if that function call has any side-effects, those side-effects will be repeated 15 times.

Imagine what would happen if f() were instead randomGenerator.nextNumber().

luckily i'm only using this with a const function, so hopefully the compiler optimizes to call it only once.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

bcrules82 posted:

luckily i'm only using this with a const function, so hopefully the compiler optimizes to call it only once.
No guarantee there, e.g.: const int f(){ return rand(); }

bcrules82
Mar 27, 2003

Mustach posted:

No guarantee there, e.g.: const int f(){ return rand(); }

can rand() be called within a const method? anyways, i'm just returning a private variable.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

bcrules82 posted:

can rand() be called within a const method? anyways, i'm just returning a private variable.

Of course it can. The only constraint that const places on a method is that you can't change non-mutable member variables. Besides, if you're using C++, for the love of god just use an inline function.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

bcrules82 posted:

can rand() be called within a const method? anyways, i'm just returning a private variable.

A const member method only guarantees that the internal state of the object will not change (and even then there are legitimate reasons that the method might internally cast away constness for some operation). It does not at all preclude stateful library calls.

In your case, yes, there is no logic-related problem with calling the accessor 15 times. There might be a performance hit if you are using this macro in a loop that runs many times because your compiler may choose not to inline the accessor for some reason.

However the main thing we're pointing out is that one reason to avoid macros generally is because they are prone to bugs like this where the behavior of a poorly written "function macro" is different than the behavior of an equivalent function. Ideally, you shouldn't have to care if EVEN_BITS_W is a macro or a function call, because it should work the same way. In the case of the particular EVEN_BITS_W macro that was posted, this assumption is violated because the macro version re-evaluates the argument 15 times, whereas if it were written as a function, the argument would be guaranteed to only evaluate once. This means that if you ever later decide to re-use EVEN_BITS_W with an argument that is not a simple accessor, you do have to stop and carefully think about whether the argument can handle being evaluated 15 times with no ill effects.

Scaevolus
Apr 16, 2007

Avenging Dentist posted:

code:
#define SQUARE_REAL(x) (x)*(x)

code:
#define SQUARE_REAL(x) ((x)*(x))
:eng101:

Macros are annoying.

sarehu
Apr 20, 2007

(call/cc call/cc)

Smackbilly posted:

If RAND_MAX is a power of two minus one (which it usually is), you can generate two random integers, and consider them to be two halves of an integer with twice the number of bits set in RAND_MAX.

More generally, generate two numbers x and y, and return (x * (RAND_MAX + 1)) + y. It is like writing a two digit number in the base RAND_MAX+1.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Back again, with another beginner question.

I'm having a bit of trouble with class-based states for a program.
What I'm trying to achieve is to have a state manager class, that contains a vector of state classes, all of which are derived from a base class. Then I can push new states onto the end of the vector (i.e., to go into a submenu) or pop them off again (to go back up to the root menu).

code:
stateManager sm;
mainGame mg;
mainMenu mm;
	
int menu = sm.storeReference(&mm);
int game = sm.storeReference(&mg);
	
sm.ChangeState(&mm);
sm.Execute();
This is my 'Main.cpp'. This sets up the states, and adds them to the state manager. The Execute() then starts up the main loop.

The problem comes when I try to change the current state from within a state.

code:
bool mainMenu::OnInit(baseState* state)
{
	Running = true;
	mainSurface = new SDL_Surface;
	
	managerLink = state;

	return true;
}

void mainMenu::OnEvent(SDL_Event *Event)
{
	if (Event->key.keysym.sym == SDLK_SPACE)
		ChangeState(managerLink->getReference(1));
}


void mainMenu::ChangeState(baseState *state, baseState *manager)
{
	if (manager==0)
		managerLink->ChangeState(state);
	else
		manager->ChangeState(state);
	
}
This is some of 'MainMenu.cpp'. The ChangeState() here is generating a pointer error: further testing shows that the pointer to the state manager class isn't beeing changed from the default of '0'. In other words, OnInit() isn't being called.

code:
void stateManager::ChangeState(baseState *state)
{

	if (stateList.size()==0)
	{
		stateList.push_back(state);
		stateList.back()->OnInit(this);
		
	}
	else
	{
		if (stateList.back() == state)
		{
			return;
		}
		else if (state == stateList[stateList.size()-1])
		{
			stateList.back()->OnCleanup();
			stateList.pop_back();
			stateList.back()->Resume();
		}
		else
		{
			stateList.back()->Pause();
			stateList.push_back(state);
			stateList.back()->OnInit(this);
			
		}
	}
	stateList.back()->OnInit(this);
}
This is the 'Change State' function from 'StateManager.cpp'. It works in a sense; new states are definitely added, and when called from within the state manager class, it definitely changes correctly. But it doesn't seem to call the OnInit() of the new state, even after I added that last call to
code:
stateList.back()->OnInit(this);
Sorry for the massive post, but does anyone have nay idea what I'm doing wrong / overlooking?

TSDK
Nov 24, 2003

I got a wooden uploading this one
It sounds a bit like you've just not declared the OnInit function in your base state class as virtual. You'll need to post more code to help pinpoint what's going wrong.

Have you tried putting a breakpoint in the stateManager::ChangeState function and tracing into the OnInit function call to see where it ends up?

Finally, I'm not 100% sure what you're trying to do with the logic in the changeState function, but it's almost certainly much more complicated than it needs to be. Split it into three functions: SetState, PushState and PopState.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


TSDK posted:

It sounds a bit like you've just not declared the OnInit function in your base state class as virtual. You'll need to post more code to help pinpoint what's going wrong.

Have you tried putting a breakpoint in the stateManager::ChangeState function and tracing into the OnInit function call to see where it ends up?

Finally, I'm not 100% sure what you're trying to do with the logic in the changeState function, but it's almost certainly much more complicated than it needs to be. Split it into three functions: SetState, PushState and PopState.

That was the problem, thanks. I had a few more issues after I fixed that, but I realised that you're advice still applied. It looks like forgetting to set functions to virtual is something I need to get over.

As for the breakpoint, I didn't (at the time) know what they were or how to do so. Since then I've figured out a rough idea; enough to use them, anyway.

The ChangeState function was supposed to be work out how to switch state. So if the stack were empty, it'd just shove it in and run it. If the new state is identical to the current state, it does nothing, if the new state is identical to the next state back, it gets rid of the current state and resumes the next one. Then if none of those apply, it pauses the current state and shoves on the new one.

I figured that this way, all you had to do was shove in the address of the state, and the function would work out the rest. Is this a bad way of going about things?

TSDK
Nov 24, 2003

I got a wooden uploading this one

Staggy posted:

I figured that this way, all you had to do was shove in the address of the state, and the function would work out the rest. Is this a bad way of going about things?
The main reason why it's bad is that the function can end up doing one of several things. It's more of a PushOrPopOrDoNothingOrPossiblySomethingElse() function. It's generally good programming practice for functions to do just one simple job, so that it's easy to use and easy to get right.

So if you have a PushState function, then it's always going to do exactly what you expect it to do: push a state on the stack - nothing more, nothing less.

Adhemar
Jan 21, 2004

Kellner, da ist ein scheussliches Biest in meiner Suppe.

Staggy posted:

State stuff.

I'm a little confused about your program logic. Have you looked at the State Pattern? I recommend it highly.

Your derived State classes should be handling events (each in their own way, relevant to that state) and simply notifying state transitions to the containing Manager class, effectively replacing themselves. The (abstract) base class (which should just be called "State", not "BaseState") defines a set of events for each state to respond to.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Adhemar posted:

I'm a little confused about your program logic. Have you looked at the State Pattern? I recommend it highly.

Your derived State classes should be handling events (each in their own way, relevant to that state) and simply notifying state transitions to the containing Manager class, effectively replacing themselves. The (abstract) base class (which should just be called "State", not "BaseState") defines a set of events for each state to respond to.

That's what I'm trying to achieve, I think I just explained things badly. Each state - be it a menu, the game, etc. - is derived from a base class. The manager class keeps track of which state is active at the moment, as well as the ones before it. Each state can then tell the manager to change state.

The base class defines various functions: OnInit(), OnRender(), OnLoop(), etc. Then the specific states expand on them, whilst the the state manager (mostly) simply calls the right function of the active state at the right time. However, like with most projects I start, I think I need to go back and start over now that I have a clearer vision of what it entails. Perhaps not 'expand' both the states and the manger class from the same base class.

Insurrectum
Nov 1, 2005

What's a way to determine the runtime of a program for something like a Project Euler problem?

Plastic Jesus
Aug 26, 2006

I'm cranky most of the time.

Insurrectum posted:

What's a way to determine the runtime of a program for something like a Project Euler problem?

man time

sarehu
Apr 20, 2007

(call/cc call/cc)

Insurrectum posted:

What's a way to determine the runtime of a program for something like a Project Euler problem?

The way you always do. How is it any different?

Insurrectum
Nov 1, 2005

Plastic Jesus posted:

man time
Thanks for this.

sarehu posted:

The way you always do. How is it any different?

The way you always do? Explain to me how I have always determined how long it took a program to run.

(But don't, because I just figured out to use GetTickCount() and subtract)

That Turkey Story
Mar 30, 2003

I usually just run it and then count aloud to myself.

Adbot
ADBOT LOVES YOU

Insurrectum
Nov 1, 2005

That Turkey Story posted:

I usually just run it and then count aloud to myself.

I'm talking about time differences in the 10 to 100s of milliseconds

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply