01-08-2016 03:09 AM - edited 01-08-2016 03:12 AM
Hi X.,
using subtraction on U32 values gives you the "distance" between those U32 values.
When you convert the U32 result to an I32 value (with "To I32") you get the correct answer (-10 in your example)!
Applying simple math (add & sub) on unsigned integer values is a very basic operation in each microprocessor and well defined.
The only problem with LabVIEWs ADD and SUB function is: you don't get a Carry/Borrow flag as you would in a µP…
On your original question: What's the point of applying Abs() on unsigned values?
(But I have to agree with Christian as the current behaviour breaks LabVIEW code when you apply Abs() on clusters.)
01-08-2016 04:06 AM
I don't see the existing behaviour as a bug- I see it as the sane choice. You can always write your own 'absolute value' function that takes anything you like- unsigned integers, strings, refnums etc.
01-08-2016 04:59 AM - edited 01-08-2016 12:06 PM
@ToeCutter wrote:
You can always write your own 'absolute value' function that takes anything you like- unsigned integers, strings, refnums etc.
You cannot easily write such a function that works properly on mixed numeric clusters. remember that "abs" even works for complex and gives you the vector lenght.
Create me a polymorphic function that accepts the following clusters (and anything similar!) with no limit on the number, type and order of the cluster elements and will perform the abs function.
Cluster 1: [DBL : CDB : I32 : I32 : U8]
Cluster 2: [I16 : I16 : I32 : U64 : DBL : DBL : CDB]
etc....
Hint: You would need an infinite amount of very complicated polymorphic subVIs (e.g. containing an IPE(unbundle/bundle) absoluting all elements that are allowed and skiping the unsigned integers.
A broken wire is simply not aceptable behavior. There is no doubt what the output should be for an unsigned input: return the input value unchanged (i.e. the same behavior it already does for 50% of all possible I32 values ;)).
There are plenty of other functions that don't do anything useful, but still don't break the VI (e.g. build array of height=1 set to concatenate, a compound node of height=1, etc.).
(The "negate function" also does not accept unsigned integers, but that makes quite a bit more sense. Even here it could accept the input and do an implicit conversion to DBL to avoid the broken wire, i.e. same as it currently does with 1/x, instead of breaking the entire VI. The coercion dot would be sufficient to alert the user that something is not quite right)
My opinion: Don't break the wire and thus the entire VI. In the worst case, create a warning.
01-08-2016 07:15 AM
@X. wrote:
@aputman wrote:
Because the values are not evaluated until runtime. The compiler doesn't know or care what values are in your constant, as long as the datatype is correct.
Right. So it is perfectly fine to obtain the value of 0 - X at runtime, where 0 and X are both U32:
which gives, for instance:
This is a perfectly valid calculation in 2's complement arithmetic, implemented in most CPUs the same and standardized by IEEE. And LabVIEW tries to maintain compatibility with IEEE for floating points and integers in every possible way.
The absolute value of an unsigned integer is an entirely different case. By definition its a NOP. Yes NI could have decided to allow it and just do a "do nothing" function call there, but all those primitives do add some execution time and since the datatype is defined at compile time it was decided that that should rather cause a compilation error than add unneccessary execution time to the runtime code.
It's definitely not a bug! And for the scalar unsigned integer a convinience and the cluster containing unsigned integers an inconvinience. So +1 - 1 = neutral. I for myself have real problems to tackle instead of getting upset about such things
01-08-2016 10:39 AM
@rolfk wrote:
but all those primitives do add some execution time and since the datatype is defined at compile time it was decided that that should rather cause a compilation error than add unneccessary execution time to the runtime code.
No, the compiler would be good enough to do the proper transform and just replace it with a wire behind the scenes. There will be no execution overhead. No need to break the VI. 😉
01-27-2016 08:14 PM
Tada!
01-27-2016 08:52 PM
Similarly:
QED: There is no good reason to prevent the abs Function to take a U32 and output the same U32...
And BTW, yes, this suggestion was a joke.
08-05-2017 12:42 PM - edited 08-05-2017 01:04 PM
Following up on this discussion now that LabVIEW 2017 is released and we have now the wonderful feature of Malleable VIs exposed to the user. It is even more inconvenient to break a VI if an unsigned integer is wired to the absolute value function. This is a real road block that now requires clumsy workarounds!
A universal algorithm that include an absolute value function should not be off-limits to unsigned integers, ever!
I'll try to write up an idea if it does not exist already! (... or maybe there is a CAR for this?)
08-05-2017 04:04 PM - edited 08-05-2017 04:18 PM
@X. wrote:
More of the same or similar arbitrariness and non-standard behavior:
Notice that it is perfectly fine to substract a U32 from another one and request a U32 result, but negating a U32 (which WILL return a I32 by construction of the function) is forbidden with the same justification as above.
Why can ask for the sign of U32 when this should be flagged as anathema by the NI guardians of positiveness?
It's not really as arbitrary as you think it to be.Subtraction of unsigned integers is fully defined with two complements overflow arithmetic. The result is still an unsigned value. The Negate would have to change the datatype to always be signed and that is something LabVIEW integer nodes usually try to avoid. LabVIEW does automatic promotion to double floating point when it makes sense but leaves integers usually alone. I think this could be probably relaxed nowadays for these things you mention but there was most likely a good reason to restrict it like that.
It'probably also a remainder of C influence. I just recently edited some C code for image filtering, which was using int everywhere to use uint32_t instead because the image can't really have negative dimensions and offsets and run into the problem that I got lots of compiler warnings that the unary negative operator could not be applied to unsigned integers and the result would be still unsigned (probably the two complements of the original value). Doing a 0 - i everywhere fixed that.
You could of course question the C standard, but there have been many very smart people debating about all these kind of things ad nauseam and there is always a reason for those decisions.