Jump to page: 1 2
Thread overview
September 22

Not 4LU.

For the billionth time while porting raylib to D, I'm having to replace n*float.sizeof with n*int(float.sizeof) because otherwise, it doesn't fit into the int I'm assigning it to.

Why isn't it just 4? 4 will convert to any width you want. It does not poison integer multiplications or additions.

The chances that T.sizeof > int.max is near zero. And even if it did, making it the same as a number literal would just work -- it would become size_t if it was too big.

-Steve

September 22
On 9/22/24 14:59, Steven Schveighoffer wrote:
> Not `4LU`.
> 
> For the billionth time while porting raylib to D, I'm having to replace `n*float.sizeof` with `n*int(float.sizeof)` because otherwise, it doesn't fit into the `int` I'm assigning it to.
> 
> Why isn't it just 4? 4 will convert to any width you want. It does not poison integer multiplications or additions.
> 
> The chances that `T.sizeof > int.max` is near zero. And even if it did, making it the same as a number literal would just work -- it would become `size_t` if it was too big.
> 
> -Steve

Well, the point of contention is not that `float.sizeof > int.max`. Rather, `n*float.sizeof` could be bigger than `int.max`.
September 22

On Sunday, 22 September 2024 at 14:59:36 UTC, Timon Gehr wrote:

>

On 9/22/24 14:59, Steven Schveighoffer wrote:

>

Not 4LU.

For the billionth time while porting raylib to D, I'm having to replace n*float.sizeof with n*int(float.sizeof) because otherwise, it doesn't fit into the int I'm assigning it to.

Why isn't it just 4? 4 will convert to any width you want. It does not poison integer multiplications or additions.

The chances that T.sizeof > int.max is near zero. And even if it did, making it the same as a number literal would just work -- it would become size_t if it was too big.

-Steve

Well, the point of contention is not that float.sizeof > int.max. Rather, n*float.sizeof could be bigger than int.max.

Is that true?
n*int(float.sizeof) could also be bigger than int.max, but Steven says it works for his case. (@Steven: best to show the full case).

-Johan

September 22

On Sunday, 22 September 2024 at 16:45:23 UTC, Johan wrote:

>

On Sunday, 22 September 2024 at 14:59:36 UTC, Timon Gehr wrote:

>

On 9/22/24 14:59, Steven Schveighoffer wrote:

>

Not 4LU.

For the billionth time while porting raylib to D, I'm having to replace n*float.sizeof with n*int(float.sizeof) because otherwise, it doesn't fit into the int I'm assigning it to.

Why isn't it just 4? 4 will convert to any width you want. It does not poison integer multiplications or additions.

The chances that T.sizeof > int.max is near zero. And even if it did, making it the same as a number literal would just work -- it would become size_t if it was too big.

Well, the point of contention is not that float.sizeof > int.max. Rather, n*float.sizeof could be bigger than int.max.

This is true for any integer calculation. Though, it is true that this would be painful if you'd have to increase the precision explicitly, and a failure to do so would be a silent error. So I have to withdraw this.

The correct solution is likely to just write a function to do this correctly. Ugh.

>

Is that true?
n*int(float.sizeof) could also be bigger than int.max, but Steven says it works for his case. (@Steven: best to show the full case).

See all the modifications here: https://github.com/schveiguy/draylib/commit/b665f75c453afa6ab8e4f8108fe1bd296f72d53e#diff-10364ecc46979709c69d6caaeb639fedf2ffa2db80d4d61a7172b7a8a374dd12

(you have to tell github to load the diff).

-Steve

September 22

On Sunday, 22 September 2024 at 12:59:04 UTC, Steven Schveighoffer wrote:

>

Not 4LU.

But it represents a size, not a number. It's fine for me it is size_t.

September 22
I agree that it seems to make sense making 4 an `int`.

I remember the bad old days, when an `int` was 16 bits. The transition to 32 bits broke an awful lot of code. Since the language does not recognize integer overflow, address calculations left and right would wrap around. Things like `malloc(n * sizeof(i))` would overflow the byte count, the malloc'd buffer would be too small, and malware would be injected.

The most effective solution is to make sizes a consistent type, which is size_t.

This does not eliminate the possibility of overflows, but dramatically reduces its incidence.
September 23
On Monday, 23 September 2024 at 05:34:51 UTC, Walter Bright wrote:
> I agree that it seems to make sense making 4 an `int`.

A number literal should always be of the smallest type that can represent it - it will be implicitly converted to larger types anyway.
So, 4 should be ubyte (as only negative literals should be of signed type and there is no smaller type in D than ubyte - else it should be of type "nibble" (4bit)).
September 23
On Monday, September 23, 2024 5:08:37 PM MDT Dom DiSc via Digitalmars-d wrote:
> On Monday, 23 September 2024 at 05:34:51 UTC, Walter Bright wrote:
> > I agree that it seems to make sense making 4 an `int`.
>
> A number literal should always be of the smallest type that can
> represent it - it will be implicitly converted to larger types
> anyway.
> So, 4 should be ubyte (as only negative literals should be of
> signed type and there is no smaller type in D than ubyte - else
> it should be of type "nibble" (4bit)).

4 will work in any context that requires a ubyte, because the compiler will know that it will fit. The issue is what it defaults to. In this case, it's size_t, because it has to do with memory size, and you really want stuff like T.sizeof * numberOfTs to result in size_t, because it represents the amount of memory being used, and if it's not size_t, it risks being truncated. It would be particularly bad if it were treated as ubyte given how little memory that would be.

So, the issue really isn't the value itself. That will convert to other sizes just fine, particularly since it's known at compile time. Rather, what matters is what you get when you do math on it, and that really needs to be size_t, because it's used for memory sizes.

- Jonathan M Davis



September 24
On Tuesday, 24 September 2024 at 03:23:31 UTC, Jonathan M Davis wrote:
> So, the issue really isn't the value itself. That will convert to other sizes just fine, particularly since it's known at compile time. Rather, what matters is what you get when you do math on it

Doing math most of the time involves at least two values, in this case sizeof (of type size_t) and 4 (a nibble).
It should be clearly defined in what type such an operation should result. Best would be: the larger type of the two operands, here size_t (but for multiplication also the next larger type would be reasonable, if you want to be sure to never get an overflow).
So if you do ubyte * 4 the result should be ubyte, because ubyte is the larger of the two types.
It doesn't matter that the calculation is done in the size of the registers of the machine, may that be 8bit, 16bit, 32bit or 64bit (or maybe any unusual odd word size), but the result should be per default restricted to the type of the larger operand (or collected from multiple registers if the type is larger than the machine word size).
If you want a different result type, you should cast at least one of the operands to the desired result type beforehand.

Of course there is also math with only one value. This should result in the same type as the operand. The unitary operators should NEVER change the type of its parameter. This is an awful behaviour of D that should be burned with fire!
September 24
On Tuesday, 24 September 2024 at 10:49:45 UTC, Dom DiSc wrote:
> The unitary operators should NEVER change the type of its parameter. This is an awful behaviour of D that should be burned with fire!

Except (of course) a cast, which is also a unitary operator :-)
« First   ‹ Prev
1 2