Floatmode confusion

Where do we set @setFloatMode to be global?
How can I get the default floatmode? Where can I find it?

1 Like

As per the docs, it sets the float mode for the current scope, so I guess set it in your main and leave it be if you want it to be global? The default value is documented to be Strict.

1 Like

The floating point mode is inherited by child scopes, and can be overridden in any scope.

It’s not clear to me that an @import is considered a child scope, I would actually find that strange. I’ve wondered the same thing about @setRuntimeSafety actually.

Treating imports as child scope could lead to invisible code duplication if various qualities differ between two imports, that would be weird, and you’d end up with extreme oddities like a type which has different float behavior, but the same @TypeOf, and how would the compiler keep track of that? Now I’m hoping it doesn’t work that way…

So @setFloatMode should probably be included in each file where you care about the float mode; I don’t know if this is necessary (perhaps someone who does will chime in), but I don’t see a downside either.

I didn’t find a way to configure this with build options and flags, either. That was unexpected, it seems like a good candidate for that.

1 Like

Yes that is confusing for me.

I don’t think this is possible. @setFloatMode is only allowed on function scope, you can’t write it at top level and have it work everywhere. I guess you could write it at the beginning of each function, but that would be inconvenient.
Zig’s compilation starts at main and follows each function that you call. @import doesn’t matter for this. When you call a function, it doesn’t matter if it’s from this file or another, then that function will inherit whatever float mode is active. Intil you call it, it won’t be compiled, so it won’t care about the float mode.
With that said, I don’t know what happens if you call the same function with two different float modes. Presumably, the most correct way of handling this would be for the compiler to generate two versions of the function, one for each mode. That’s not hard at all for a compiler to do, though I don’t know if Zig actually does this.
To add to the confusion, which mode is used when exporting a function?

fwiw, it’s potentially on the chopping block: https://github.com/ziglang/zig/issues/23173

1 Like

I stumbled upon it, not knowing if its existance. In my chess program I have quite some f32 calculations and wanted to check if some speed-boost is possible. Also contemplating using f16, which - I read somewhere - are quite fast.
My confusion is complete now :slight_smile:

I suppose I could have been clearer about that:

You can set the floating point mode in a struct or module scope by using a comptime block.

So

comptime {
    @setFloatMode(.strict);
}

Like that, in each file.

Are we sure this is how that works? Compilation does, yes, I mean inheritance of these kinds of builtin attribute settings.

That’s dynamic scope, sure, but Zig is a lexically scoped language. I took “child scopes” to mean what it would mean in a lexically scoped language: any blocks nested inside the one with the declaration, not everything down-stack from the call which has it, as in a dynamically scoped one.

I actually think dynamic scope is a great fit for @setRuntimeSafety in particular, but I don’t think it uses it, or @setFloatMode either.

But this has never been clear to me, I’m just relaying what I’ve pieced together, which could easily be wrong.

I’m sorry this is crazy-pants. At least the voice of reason has spoken. If the intention is to reify fast-float as a separate type, ok that’s great, but.

Whatever it’s off topic. But here’s a choice quote from the Voice of Reason:

Please do study the published literature–people have been trying this for two decades and failing.

Indeed.

Well, now I don’t know. I’ve always assumed that’s how all the “state” functions worked, including @setRuntimeSafety and @setEvalBranchQuota. I guess I’ve been using all of that wrong, which would explain some weird behavior I’ve seen over the years. :thinking:

According to Sema, float mode and runtime safety is per lexical scope, while eval quota is just a bump:

https://codeberg.org/ziglang/zig/src/commit/52141fe85f1b7719cecb868520f40431fcfff2a1/src/Sema.zig#L375-L379

https://codeberg.org/ziglang/zig/src/commit/52141fe85f1b7719cecb868520f40431fcfff2a1/src/Sema.zig#L5479

3 Likes

I was afraid of that. This makes it difficult to turn off bounds checking for dynamically scoped slice processing, for example, but I can understand why dynamic scoping would be quite difficult or even impossible.

In any case, good to know! Thanks.