Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate the smallest float/double that preserves the binary representation #2132

Open
pixelflinger opened this issue Mar 31, 2023 · 2 comments
Labels
enhancement New feature to SPIRV-Cross is desired. maintenance Non-functional issue / code cleanliness

Comments

@pixelflinger
Copy link

Currently spirv-cross uses %.32g by default to format floats, this can be overridden with SPIRV_CROSS_FLT_FMT at compile time. When embedding shaders with binaries, reducing their binary footprint can be important.

What really matters is to preserve the binary representation of the float in the SPIRV file. 32 digits is overkill for floats and doubles. We could use respectively 9 and 17 digits, which is always enough, however, this would still generate strings larger than needed.

Ideally, we'd want to use the smallest string that preserves the binary representation.

For instance, I have tested the following implementation for floats only:

static inline std::string convert_to_smallest_string(float f, char locale_radix_point) {
    char buf[16]; // e.g.: -0.12345678e-12, 16 bytes needed
    float r;
    for (int i = 1; i < 9; i++) {
        sprintf(buf, "%.*g", i, f);
        sscanf(buf, "%f", &r);
        if (r == f) {
            break;
        }
    }
    fixup_radix_point(buf, locale_radix_point);

    // Ensure that the literal is float.
    if (!strchr(buf, '.') && !strchr(buf, 'e'))
        strcat(buf, ".0");

    return { buf };
}

For doubles and long doubles it might better to binary-search the right format length.

@HansKristian-Work
Copy link
Contributor

We could use respectively 9 and 17 digits, which is always enough

This approach failed in one of my tests, but maybe I did something wrong. Either way, shortening the string would be great, it's been a long standing todo that just never bubbled up as something critical, but we need to have a strategy on how we're going to verify it if we're going to implement this. For FP32 we can roundtrip every possible value in a reasonable amount of time, and we should be able to test a reasonable subset of FP64 as well.

@HansKristian-Work HansKristian-Work added enhancement New feature to SPIRV-Cross is desired. maintenance Non-functional issue / code cleanliness labels Apr 20, 2023
@pixelflinger
Copy link
Author

@HansKristian-Work there is some good information here (as to why %.9g works for floats):
https://randomascii.wordpress.com/2013/02/07/float-precision-revisited-nine-digit-float-portability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature to SPIRV-Cross is desired. maintenance Non-functional issue / code cleanliness
Projects
None yet
Development

No branches or pull requests

2 participants