English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. C/C++ (https://eab.abime.net/forumdisplay.php?f=118)
-   -   Generating FFP values at compile time (https://eab.abime.net/showthread.php?t=107564)

deimos 07 July 2021 11:59

Generating FFP values at compile time
 
I'm working with FFP format floating point numbers, using C++ Bartman's GCC environment, cross compiling from Windows.

I have a type,
real
, that's really just a
LONG
with a bunch of overloaded operators to make it appear almost like an inbuilt type.

Everything works, except initialising these objects is awkward. I can't just go:

Code:

    real pi = 3.14159;
I have an a2r function that means I can go:

Code:

    real pi = a2r("3.14159");
which is ok for some things, but really not ideal, and fails in some situations, like in static initialisation of flexible array contents.

At the moment I have a bunch of #defined constants:

Code:

#define r_pi 0xC90FDB42UL
but that's turning out to be a real pain to work with.

Does anyone have any smarter ideas?

Thomas Richter 07 July 2021 18:21

Well, for Os 3.1.4, we had kinna the reverse problem, namely to let SAS/C accept IEEE single precision constants. The solution there, albeit hacky, was to have a (self-written) preprocessor (not the standard C preprocessor) which took these constants, and converted them to references (i.e. __3_14159), and then later in the build stage, C was compiled to assembler (not object code), and a second script then converted those constants by suitable immediate hex values.

It was really a sort of abuse of the SAS/C compiler chain, and an external "hack" that abused that chain.

Jobbo 07 July 2021 19:38

I've done something similar.

I wrote a wrapper class around the FFP library. Then pulled some helper functions from elsewhere for conversion from and to ieee floats. I also added some trig/math code as needed.

For my implementation you can declare an FFP with the following helper function:

ffloat value = ffloat_from_ieee(1.2345f);

It's relatively fast but it's still better to do this all upfront so it's only slow for the initial setup.

You can also create ffloat's from ints:

ffloat value = ffloat(1) / ffloat(100); // 0.01

I've shared my class over at: https://github.com/rjobling/ffloat

deimos 07 July 2021 20:09

Quote:

Originally Posted by Thomas Richter (Post 1494637)
Well, for Os 3.1.4, we had kinna the reverse problem, namely to let SAS/C accept IEEE single precision constants. The solution there, albeit hacky, was to have a (self-written) preprocessor (not the standard C preprocessor) which took these constants, and converted them to references (i.e. __3_14159), and then later in the build stage, C was compiled to assembler (not object code), and a second script then converted those constants by suitable immediate hex values.

It was really a sort of abuse of the SAS/C compiler chain, and an external "hack" that abused that chain.

Well, that kind of validates one of the ideas I have at the moment, to write a GCC preprocessor, which seems to be a supported, if underdocumented thing.

Trouble mostly is that I'd have to write a preprocessor to run under Windows, and I've never done any Windows development before.

deimos 07 July 2021 20:19

Quote:

Originally Posted by Jobbo (Post 1494652)
I've done something similar.

I wrote a wrapper class around the FFP library. Then pulled some helper functions from elsewhere for conversion from and to ieee floats. I also added some trig/math code as needed.

For my implementation you can declare an FFP with the following helper function:

ffloat value = ffloat_from_ieee(1.2345f);

It's relatively fast but it's still better to do this all upfront so it's only slow for the initial setup.

You can also create ffloat's from ints:

ffloat value = ffloat(1) / ffloat(100); // 0.01

I've shared my class over at: https://github.com/rjobling/ffloat

I've had a quick look at that, and will look deeper tomorrow. It looks like you've tried to do much the same as me, but maybe got further than I have.

One of the problems I have is the static initialisation of flexible array members with that kind of approach ( ffloat_from_ieee or a2f = ffloat from char * ). I'm not sure if it's my code to blame, or a gcc bug. Maybe it would be worthwhile me testing with your approach as well as mine.

Jobbo 07 July 2021 20:35

I don't know what you mean by "static initialization of flexible array members"?

Can you show me an example of what you're doing?

alkis 07 July 2021 22:28

You mean something like that?

http://franke.ms/cex/z/b9vqoo

Jobbo 07 July 2021 22:35

Cool! I hadn't considered trying to get it all to happen at compile time. But that's pretty awesome that it can be made to work.

Thomas Richter 07 July 2021 22:54

Quote:

Originally Posted by deimos (Post 1494655)
Trouble mostly is that I'd have to write a preprocessor to run under Windows, and I've never done any Windows development before.


First, if it's command line, it's not any different. Just use gcc, and your standard main() to collect command line arguments.


Second, you can always use vamos and write an amiga binary. This is what I did as "pre-processor", but it was supposed to operate in an all-amiga environment anyhow.

deimos 08 July 2021 10:41

Quote:

Originally Posted by Thomas Richter (Post 1494681)
First, if it's command line, it's not any different. Just use gcc, and your standard main() to collect command line arguments.


Second, you can always use vamos and write an amiga binary. This is what I did as "pre-processor", but it was supposed to operate in an all-amiga environment anyhow.

Vamos seems like a good idea to make sure I'm using the same conversion code regardless of whether I'm converting at compile or runtime.

I think I'll look for something else for the text replacement part, maybe I can make do with a sed script.

deimos 08 July 2021 10:48

Quote:

Originally Posted by Jobbo (Post 1494662)
I don't know what you mean by "static initialization of flexible array members"?

Can you show me an example of what you're doing?

This is what I'm currently doing:

Code:

#include "../real_constants.h"

    static VertexComponentData yVertexComponentData = {
        .numTouchValues = 2,
        .numTotalValues = 4,
        .values = {
            r_0_000,
            r_2_600,
            r_5_500,
            r_1_200
        }
    };

This is what didn't work:

Code:

    static VertexComponentData yVertexComponentData = {
        .numTouchValues = 2,
        .numTotalValues = 4,
        .values = {
            a2r("0.000"),
            a2r("2.600"),
            a2r("5.500"),
            a2r("1.200")
        }
    };

The calls to a2r happen during the static initialisation phase, but the return values get put in the wrong place, overwriting other data.

alkis 08 July 2021 11:30

Quote:

Originally Posted by deimos (Post 1494748)
This is what I'm currently doing:

Code:

#include "../real_constants.h"

    static VertexComponentData yVertexComponentData = {
        .numTouchValues = 2,
        .numTotalValues = 4,
        .values = {
            r_0_000,
            r_2_600,
            r_5_500,
            r_1_200
        }
    };

This is what didn't work:

Code:

    static VertexComponentData yVertexComponentData = {
        .numTouchValues = 2,
        .numTotalValues = 4,
        .values = {
            a2r("0.000"),
            a2r("2.600"),
            a2r("5.500"),
            a2r("1.200")
        }
    };

The calls to a2r happen during the static initialisation phase, but the return values get put in the wrong place, overwriting other data.

post#7?

deimos 08 July 2021 11:45

Quote:

Originally Posted by alkis (Post 1494752)
post#7?

Probably needed some explanation and context.

How will that approach work with cross compilation? I'll obviously not be able to use my existing a2r function.

alkis 08 July 2021 11:51

Quote:

Originally Posted by deimos (Post 1494755)
Probably needed some explanation and context.

How will that approach work with cross compilation? I'll obviously not be able to use my existing a2r function.

The code in the link initialises an array with FFP values. Isn't that what you wanted?

You have to call the ffpfieee() function and instead of strings supply c++ floats.

deimos 08 July 2021 12:12

Quote:

Originally Posted by alkis (Post 1494756)
The code in the link initialises an array with FFP values. Isn't that what you wanted?

You have to call the ffpfieee() function and instead of strings supply c++ floats.

It's almost what I want - I do want the source to be the text values rather than ieee floats.

But, my question was, how will that work with the cross compilation environment I outlined in

post #1.

The constexpr code needs to be executed, right? But my compiler is running on windows but generating 68000 Amiga code. How can the code be executed at compile time?

Edit:

I'm learning more about this new constexpr thing, and I'm now seeing that it's not code that is executed, it just allows for really complicated expressions to be evaluated, with a whole bunch of restrictions that change every few years. It will be interesting to see if I can parse a string with it.

alkis 08 July 2021 12:50

The site where you see the code is using a cross-compiler toolchain. So it works in cross-compiler for sure.

But why would you want strings?

Code:

int a[] = {
  foo("3.14159")
};

vs

Code:

int a[] = {
    foo(3.14159)
};

why would you choose string? Aren't floats a cleaner solution?

deimos 08 July 2021 13:13

Quote:

Originally Posted by alkis (Post 1494767)
The site where you see the code is using a cross-compiler toolchain. So it works in cross-compiler for sure.

But why would you want strings?

Code:

int a[] = {
  foo("3.14159")
};

vs

Code:

int a[] = {
    foo(3.14159)
};

why would you choose string? Aren't floats a cleaner solution?

Because ieee sp floats and ffp floats aren't exactly equivalent, they cover different ranges, plus I want to guarantee 100% consistency between the compile time behaviour and the ffp assembly code that I'm wrapping. Using floats may or may not be subjectively cleaner, but strings are what I want, if I can make it work.

alkis 08 July 2021 13:26

the function ffpfieee is "ffp from ieee"

Check the hex representation here
https://godbolt.org/z/fWbzjTbff

deimos 08 July 2021 13:46

Quote:

Originally Posted by alkis (Post 1494779)
the function ffpfieee is "ffp from ieee"

Check the hex representation here
https://godbolt.org/z/fWbzjTbff

Yes, but ieee floats and ffp floats are functionally different and I don't want to convert between them.

alkis 08 July 2021 14:03

Quote:

Originally Posted by deimos (Post 1494784)
Yes, but ieee floats and ffp floats are functionally different and I don't want to convert between them.

There shouldn't be different if your values are within FFP range. If they are not then you have other problems. If they are, then the conversion should work.


All times are GMT +2. The time now is 13:58.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.04888 seconds with 11 queries