Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Workaday Wizard
Oct 23, 2009

by Pragmatica

Bruegels Fuckbooks posted:

It's explicitly defined in the c standard section defining for loops.
6.5.3/2 has:

But why?

Adbot
ADBOT LOVES YOU

Eela6
May 25, 2007
Shredded Hen

The Cavern of COBOL > Coding Horrors: But why?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Because they happened to implement it that way in the 70s.

sarehu
Apr 20, 2007

(call/cc call/cc)
Having to put a 1 in there would be a pain in the rear end.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

sarehu posted:

Having to put a 1 in there would be a pain in the rear end.

And if there's one thing that absolutely will not be tolerated in The C Programming Language, it's annoying and error-prone corner cases.

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:


Someone has to try stuff so we can find out it was a bad idea.

Zaxxon
Feb 14, 2004

Wir Tanzen Mekanik

cause they let you do it in C

return0
Apr 11, 2007

TheBlackVegetable posted:

Of course, but it looks nicer in F#

Sounds like java vs scala

idiotmeat
Apr 3, 2010

If I were to venture a guess it would be to allow for trivial initialization and iteration semantics while allowing for nontrivial ways of exiting the loop.

qsvui
Aug 23, 2003
some crazy thing
I think it just looks better.

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"
Choosing the empty statement as false would mean
C code:
for (int i = 0;; i++) {
  // ...
}
is the same as
C code:
:v:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The idea behind allowing it to be omitted was probably symmetry, since it's frequently useful to omit either or both of the other two clauses.

Absurd Alhazred
Mar 27, 2010

by Athanatos

rjmccall posted:

The idea behind allowing it to be omitted was probably symmetry, since it's frequently useful to omit either or both of the other two clauses.

Coder! Coder! Typing bright!
On the keyboard of the night!
What immortal hand or eye/
Could parse thy fearful symmetry?

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

NihilCredo posted:

And if there's one thing that absolutely will not be tolerated in The C Programming Language, it's annoying and error-prone corner cases.

:golfclap:

Jaded Burnout
Jul 10, 2004


Absurd Alhazred posted:

Coder! Coder! Typing bright!
On the keyboard of the night!
What immortal hand or eye/
Could parse thy fearful symmetry?

Lovely. Air kisses all round.

QuarkJets
Sep 8, 2008

This thread seems like it would appreciate a review of Solidity, the programming language that Ethereum uses for its "smart contracts" and the technical capabilities of which presumably gives the cryptocurrency its $20B market cap (I lied, it's all based on speculation). From yospos

quote:

Solidity has far worse problems than not being an advanced research language. Just being a sanely designed normal language would be a big step up. Solidity is so riddled with bizarre design errors it makes PHP 4 look like a work of genius.

A small sampling of the issues:

Everything is 256 bits wide, including the "byte" type. This means that whilst byte[] is valid syntax, it will take up 32x more space than you expect. Storage space is extremely limited in Solidity programs. You should use "bytes" instead which is an actual byte array. The native 256-bit wide primitive type is called "bytes32" but the actual 8-bit wide byte type is called "int8".

Strings. What can we say about this. There is a string type. It is useless. There is no support for string manipulation at all. String concatenation must be done by hand after casting to a byte array. Basics like indexOf() must also be written by hand or implementations copied into your program. To even learn the length of a string you must cast it to a byte array, but see above. In some versions of the Solidity compiler passing an empty string to a function would cause all arguments after that string to be silently corrupted.

There is no garbage collector. Dead allocations are never reclaimed, despite the scarcity of available memory space. There is also no manual memory management.

Solidity looks superficially like an object oriented language. There is a "this" keyword. However there are actually security-critical differences between "this.setX()" and "setX()" that can cause wrong results: https://github.com/ethereum/solidity/issues/583

Numbers. Despite being intended for financial applications like insurance, floating point is not supported. Integer operations can overflow, despite the underlying operation being interpreted and not implemented in hardware. There is no way to do overflow-checked operations: you need constructs like "require((balanceOf[_to] + _value) >= balanceOf[_to]);"

You can return statically sized arrays from functions, but not variably sized arrays.

For loops are completely broken. Solidity is meant to look like JavaScript but the literal 0 type-infers to byte, not int. Therefore "for (var i = 0; i < a.length; i ++) { a[i] = i; }" will enter an infinite loop if a[] is longer than 255 elements, because it will wrap around back to zero. This is despite the underlying VM using 256 bits to store this byte. You are just supposed to know this and write "uint" instead of "var".

Arrays. Array access syntax looks like C or Java, but array declaration syntax is written backwards: int8[][5] creates 5 dynamic arrays of bytes. Dynamically sized arrays work, in theory, but you cannot create multi-dimensional dynamic arrays. Because "string" is a byte array, that means "string[]" does not work.

The compiler is riddled with mis-compilation bugs, many of them security critical. The documentation helpfully includes a list of these bugs .... in JSON. The actual contents of the JSON is of course just strings meant to be read by humans. Here are some summaries of miscompile bugs:

In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers

Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes. For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.

Dynamic allocation of an empty memory array caused an infinite loop and thus an exception

Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.

As you can see the decision to build a virtual machine with that is natively 256-bit wide led to a huge number of bugs whereby reads or writes randomly corrupt memory.

Solidity/EVM is by far the worst programming environment I have ever encountered. It would be impossible to write even toy programs correctly in this language, yet it is literally called "Solidity" and used to program a financial system that manages hundreds of millions of dollars.

Not having a floating point type actually seems reasonable for a financial transaction engine but it's not like it has a BCD type, either. The compiler just randomly corrupting your data though seems awesome

Workaday Wizard
Oct 23, 2009

by Pragmatica
You need floating point to multiply percentages etc. though.

Spatial
Nov 15, 2007

Fixed point can handle percentages just fine. For currency fixed point is always better because the precision doesn't change with the size of the operands.

It's unfortunate that most languages have poor support for fixed point. It really should be a standard type especially in systems programming languages.

Athas
Aug 6, 2007

fuck that joker

Spatial posted:

Fixed point can handle percentages just fine. For currency fixed point is always better because the precision doesn't change with the size of the operands.

It's unfortunate that most languages have poor support for fixed point. It really should be a standard type especially in systems programming languages.

What kind of language support do you envision for fixed point? Just use integers and a printing routine based on the unit you want.

Fixed point is indeed nice, but it has serious problems for handling intermediate calculations. For example, computing the distance between two points of magnitude O(n) requires an intermediate result of magnitude O(n*n) if you use the usual Pythagoras formula. This means you might get an overflow in the intermediate result, even if the final result would fit nicely. Floating point is useful in exactly such cases.

QuarkJets
Sep 8, 2008

Spatial posted:

Fixed point can handle percentages just fine. For currency fixed point is always better because the precision doesn't change with the size of the operands.

It's unfortunate that most languages have poor support for fixed point. It really should be a standard type especially in systems programming languages.

Except this language doesn't have fixed point, either

john donne
Apr 10, 2016

All suitors of all sorts themselves enthral;

So on his back lies this whale wantoning,

And in his gulf-like throat, sucks everything

That passeth near.

QuarkJets posted:

Except this language doesn't have fixed point, either

Then what's the point?

Mr Shiny Pants
Nov 12, 2012

john donne posted:

Then what's the point?

There isn't one.

nielsm
Jun 1, 2009



Athas posted:

What kind of language support do you envision for fixed point? Just use integers and a printing routine based on the unit you want.

Just something that handles scaling in multiplication and division correctly and implicitly.

Kilson
Jan 16, 2003

I EAT LITTLE CHILDREN FOR BREAKFAST !!11!!1!!!!111!

quote:

In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers

:allears:

Pixelboy
Sep 13, 2005

Now, I know what you're thinking...

QuarkJets posted:

Except this language doesn't have fixed point, either

No ints or bit shifts?

Dylan16807
May 12, 2010

Athas posted:

What kind of language support do you envision for fixed point? Just use integers and a printing routine based on the unit you want.

Fixed point is indeed nice, but it has serious problems for handling intermediate calculations. For example, computing the distance between two points of magnitude O(n) requires an intermediate result of magnitude O(n*n) if you use the usual Pythagoras formula. This means you might get an overflow in the intermediate result, even if the final result would fit nicely. Floating point is useful in exactly such cases.

You answered your own question. It can be tricky to avoid intermediate overflow, so language support would take care of those mechanisms while you write straightforward code.

Athas
Aug 6, 2007

fuck that joker

Dylan16807 posted:

You answered your own question. It can be tricky to avoid intermediate overflow, so language support would take care of those mechanisms while you write straightforward code.

What would that language support do, short of just switching to floating point?

nielsm
Jun 1, 2009



Athas posted:

What would that language support do, short of just switching to floating point?

I don't know about other archs, but on x86 the integer MUL and DIV instructions respectively store the result in a register pair, and take the numerator as a register pair. Which means that for a 32 x 32 bit multiplication, the result is in fact 64 bit, and you don't have 32 / 32 bit division, but actually 64 / 32 bit division.
So if the compiler knows it's working with fixed-point numbers it can generate correct MUL-DIV sequences that have a 64 bit intermediate without any additional cost.

Eela6
May 25, 2007
Shredded Hen

Athas posted:

What would that language support do, short of just switching to floating point?

Well, you could use arbitrary-precision arithmetic internally, I suppose. I can see a case for a financial language that uses bigInts and extreme-precision Decimals as the default types for internal numeric calculations. You could even throw an exception on busting the bounds of your decimal precision, forcing the user to deliberately round or expand the precision.

"Solidity" is not it, though.

Ed: I answered a question no one asked. I am dumb.

Spatial
Nov 15, 2007

When I suggested fixed point as a fundamental type, I meant in the context of a language like C. The rules would be the same as for integer arithmetic. If you use fixed point you probably know the limitations plenty well.

Athas
Aug 6, 2007

fuck that joker

nielsm posted:

I don't know about other archs, but on x86 the integer MUL and DIV instructions respectively store the result in a register pair, and take the numerator as a register pair. Which means that for a 32 x 32 bit multiplication, the result is in fact 64 bit, and you don't have 32 / 32 bit division, but actually 64 / 32 bit division.
So if the compiler knows it's working with fixed-point numbers it can generate correct MUL-DIV sequences that have a 64 bit intermediate without any additional cost.

In this case, the code would be something like:

code:
fixed32 res = sqrt((x2-x1)**2 + (y2-y1)**2)
And sure, even if the type 'fixed32' involved is specified to only be 32 bits or whatever, the power operator could give the result as a 'fixed64', followed by rounding/truncation when assigning to the result variable. However, I have a hard time seeing that working if the code is factored to store the intermediate results in variables:

code:
fixed32 u = (x2-x1)**2
fixed32 v = (y2-y1)**2
fixed32 res = sqrt(u + v)
Unless the compiler does something real funky (I'm not even sure how that behaviour should be specified precisely), these two programs would not have the same semantics.

Also, it cannot even be known at compile-time how much precision you need for the intermediate result. Yes, for multiplication you just need to double the number of bits, but what about exponents? The only way to make this scheme work is with arbitrary size numbers (which has its owns problems), which I think you are free to use in most high-level languages.

Numerics are not easy, and there is no quick fix. In general, floating point turns out to have the least warts.

nielsm
Jun 1, 2009



I'll try.

code:
  ; ecx:ebx := (x2-x1)**2
  mov eax, [x2]
  sub eax, [x1]
  mov edx, eax
  mul edx        ; edx:eax := eax * edx
  mov ebx, eax
  mov ecx, edx
  ; edx:eax := (y2-y1)**2
  mov eax, [y2]
  sub eax, [y1]
  mov edx, eax
  mul edx
  ; edx:eax := edx:eax + ecx:ebx
  add eax, ebx   ; sets carry bit if signed addition overflows
  adc edx, ecx   ; includes carry bit in signed addition
  ; sqrt
  call sqrt_int64 ; gently caress no i'm not doing this part
May have mistakes, I'm not very trained in assembly. But this code should run on a 386, working with 64 bit intermediates.

nielsm fucked around with this message at 21:34 on Jul 20, 2017

boo_radley
Dec 30, 2005

Politeness costs nothing

Eela6 posted:

I answered a question no one asked.

Hey, this is the coding horrors thread, Jack. The enterprise architecture thread is over that-a-way.

boo_radley fucked around with this message at 01:53 on Jul 21, 2017

Eela6
May 25, 2007
Shredded Hen

boo_radley posted:

Hey, this is the coding horrors thread, Jack. The enterprise architecture thread is over that-a-way.

:golfclap:

Athas
Aug 6, 2007

fuck that joker

nielsm posted:

I'll try.

code:
  ; ecx:ebx := (x2-x1)**2
  mov eax, [x2]
  sub eax, [x1]
  mov edx, eax
  mul edx        ; edx:eax := eax * edx
  mov ebx, eax
  mov ecx, edx
  ; edx:eax := (y2-y1)**2
  mov eax, [y2]
  sub eax, [y1]
  mov edx, eax
  mul edx
  ; edx:eax := edx:eax + ecx:ebx
  add eax, ebx   ; sets carry bit if signed addition overflows
  adc edx, ecx   ; includes carry bit in signed addition
  ; sqrt
  call sqrt_int64 ; gently caress no i'm not doing this part
May have mistakes, I'm not very trained in assembly. But this code should run on a 386, working with 64 bit intermediates.

This only works for a special case. My argument is that there is no way to do this automatically in a compiler, because the right solution is always algorithm-dependent.

Also, there is no guarantee that the sum of the two squares will fit in 64 bits (consider if all of x1,x2,y1,y2 have the maximum size), so your code is not even correct for that case.

nielsm
Jun 1, 2009



If you need arbitrary precision and magnitude, you use an arbitrary precision library. You would have the same problem with plain integer math, and even floating point has a magnitude limit to numbers, after which the result may just clamp to Inf.

However if you actually checked, you'd see that (0x7FFFFFFF**2)*2 does not overflow 64 bits, you simply get 0x7FFFFFFE'00000002. I'm not sure what 32 bit signed values you imagined could sub in for x1, x2, y1, y2 to generate a 64 bit overflow.
A compiler would also be able to determine if an expression would need a bigger intermediate and automatically extend the data type, so I do believe this code could have been generated without any special casing.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.
The guy who invented Solidity also wrote a buggy Ethereum smart contract that got millions of dollars stolen.

There's a very nice (and extremely weaselly) article about it. It explains why it's actually *good* that this happened.

From a legal perspective you can even argue that nothing was stolen, since due to the programming error the "contract" specified that arbitrary people could take the money.

Sagacity fucked around with this message at 07:52 on Jul 21, 2017

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

quote:

The developer here was Gavin Wood, one of the co-creators of Ethereum, and the inventor of Solidity, the smart contract programming language. The code was also reviewed by other Parity contributors. This is basically the highest standard of programming that exists in the Ethereum ecosystem.

I thought he was supposed to be downplaying the impact of this.

Athas
Aug 6, 2007

fuck that joker

nielsm posted:

If you need arbitrary precision and magnitude, you use an arbitrary precision library. You would have the same problem with plain integer math, and even floating point has a magnitude limit to numbers, after which the result may just clamp to Inf.

However if you actually checked, you'd see that (0x7FFFFFFF**2)*2 does not overflow 64 bits, you simply get 0x7FFFFFFE'00000002. I'm not sure what 32 bit signed values you imagined could sub in for x1, x2, y1, y2 to generate a 64 bit overflow.
A compiler would also be able to determine if an expression would need a bigger intermediate and automatically extend the data type, so I do believe this code could have been generated without any special casing.

You're right that this won't happen in the two-dimensional case (sorry, should have checked), but you do get that it's not actually possible in general for a compiler to determine an appropriate fixed size for intermediaries, right?. Let's consider an arbitrary n-dimensional space (this also requires the compiler to work a little harder):

code:
fixed res = 0;
for i in n:
  res += (xs[i]-ys[i])**2
res = sqrt(res)
It is not possible (at compile-time) to determine a fixed size for 'res' that will work in all (or even most) cases. You'll (potentially) get problems as soon as n>2. This issue crops up quickly for fairly basic computations, like computing the variance of some samples. You're right that floating point will also break down after a while, but the limit is far harder to reach. There is no replacement for understanding numerics issues, but I'll argue that floating point is more practical when you actually want to do non-trivial computation (but please don't modify my bank account with floating point operations).

Adbot
ADBOT LOVES YOU

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Athas posted:

What kind of language support do you envision for fixed point? Just use integers and a printing routine based on the unit you want.

Jesus, what kind of question is this. Full support of course, the same support enjoyed by floating point numbers: printing, parsing, math routines, the whole thing

Athas posted:

Fixed point is indeed nice, but it has serious problems for handling intermediate calculations. For example, computing the distance between two points of magnitude O(n) requires an intermediate result of magnitude O(n*n) if you use the usual Pythagoras formula. This means you might get an overflow in the intermediate result, even if the final result would fit nicely. Floating point is useful in exactly such cases.

Native language support would handle and hide the overflow. It's not like we couldn't multiply 64 bit integers on 32 bit machines, there just wasn't a neat single CPU instruction to do it (there was a neat single built-in function instead)

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply