Floating-point math in Glulx

I’ve got Glulxe running and passing the tests on Windows, and I’m some of the way through producing a patch for Git. (On Git some tests pass, and some blow up the interpreter - damned preprocessor macro cleverness/madness). A few thoughts:

The math functions used mean that the compiler must pretty much support C99. This isn’t entirely unreasonable, but might be worth mentioning in the README, at least.

The code in exec.c presumes that the C99 math functions get all the special cases right. Unfortunately the pow() function in the GCC build I’m using doesn’t get a few special cases right, resulting in me having to do preprocessor macro nastiness to call my own pow() function first. Looking around online, I can see that this won’t be uncommon on other platforms. Is there a case for a glulx_pow() function in osdepend.c?

Which functions are C99? signbit() and any others? I’d be willing to rewrite them out, if it’s easy, and for signbit() it should be.

(I already got rid of isless() and friends for that reason – they weren’t on my Ubuntu machine. I didn’t realize there were intermediate classes of availability.)

Yeah, glulx_pow() makes sense. Send me what you have when you get it working.

Errm, well, all of them, really: signbit(), isnan(), isinf(), truncf(), roundf(), ceilf(), floorf(), sqrtf(), expf() and so on … ceil(double) and friends are C89, but the float forms like ceilf(float) are C99.

Will do.

Oh. Hm. I was (somehow) assuming that C99 was a previous standard, and we were now on some new one.

I’ll add a note.

I just noticed that one @ceil test fails on Mac OSX 10.5.8 (Intel):

ceil -0.9=0.00000 or $0 (should be -0.00000 or $80000000 FAIL)

Git has the same bug (presumably from the same implementation). I’ll get a fix out soonish.

For some reason, trying to call out from op_pow to glulx_powf(valf1, valf2) resulted in those values getting scrambled. Could be a quirk of GCC 4.5, but I could not get the correct values to come through.

I ended up having to add your conditions directly to the op_pow code:

      case op_pow:
        valf1 = decode_float(inst[0].value);
        valf2 = decode_float(inst[1].value);
        if (valf1 == 1.0f)
            value = encode_float(1.0f);
        else if ((valf2 == 0.0f) || (valf2 == -0.0f))
            value = encode_float(1.0f);
        else if ((valf1 == -1.0f) && isinf(valf2))
            value = encode_float(1.0f);
            value = encode_float(powf(valf1, valf2));
        store_operand(inst[2].desttype, inst[2].value, value);

Hmmm, I can’t see anything wrong in the glulx_powf() logic :frowning:

The same glulx_powf() code works fine if it’s defined in exec.c instead of osdepend.c.

I’ve tried to get around this a number of ways and I’ve basically given up. GCC 4.5 / MinGW seems to have trouble passing float values correctly between functions in different source files. No idea why this should be so, but there you go.

I’ve checked in David’s glulx_powf change (to the master branch).

I rearranged it a little bit – the VM now always calls glulx_powf(), and osdepend.c compiles that function differently if the FLOAT_COMPILE_SAFER_POWF symbol is defined. (This is closer to the way glulx_random() works. It shouldn’t act any differently from what David had.)

I don’t understand the Windows build problem. But then, I wouldn’t.

My only idea is this: the header is compiling the line “typedef float gfloat32;” without including math.h. Maybe float is defined to a different type when you’ve got math.h included? You could test this by throwing an #include math.h line at the top of glulxe.h.

Well, it worked with the latest Glulxe code from the Git repository. It was the extern definition of glulx_powf() in glulxe.h that did the trick. :blush:

David’s version had that extern definition too. I thought the #ifdefs around it were correct.

But, if mine version is working correctly, that’s good enough. :slight_smile:

Ah. The Windows Glulxe source package doesn’t include the core Glulxe files, so I missed his change to glulxe.h.