ecmascript_simd icon indicating copy to clipboard operation
ecmascript_simd copied to clipboard

Unsigned types don't have "neg"

Open bnjbvr opened this issue 9 years ago • 10 comments

The spec says that all integral types (signed and unsigned) should implement neg, although the polyfill doesn't have them. Is it that the polyfill is missing them, or is it that the spec shouldn't define them for unsigned types?

As noted by Jakob Olesen in https://bugzilla.mozilla.org/show_bug.cgi?id=1233111#c17 , they can be implemented with modulo arithmetic.

bnjbvr avatar Dec 23 '15 18:12 bnjbvr

I would recommend keeping unsigned neg in the spec and adding it to the polyfill. It is the same for all integer types: neg(x) = sub(splat(0), x).

stoklund avatar Dec 23 '15 18:12 stoklund

Let's get rid of neg from unsigned types. It was a typo on my part to include them; I don't think it was anyone's intention.

littledan avatar Dec 23 '15 20:12 littledan

Currently, the signed and unsigned integer types support the same set of operations. This is a desirable property of a compilation target.

Would it make sense to remove neg from the signed integer types too? I don't think it provides any benefit. It is more important to have a floating point neg.

stoklund avatar Dec 23 '15 20:12 stoklund

I did a quick survey of programming languages that provide fixed-size unsigned integer types:

  • C/C++: unsigned int and unsigned long support the unary - operator with modulo semantics.
  • Ada: Modular integer types support the unary "-" operator. http://www.adaic.org/resources/add_content/standards/12rm/html/RM-4-5-4.html
  • D has unsigned types. The spec is not so clear about negation: http://dlang.org/spec/expression.html#UnaryExpression
  • Haskell has a number of Word types which are all supported by the negate function with modulo semantics. http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:negate
  • Nim has unsigned integer types which do not support the unary - operator.
  • Rust has unsigned types with a unary - operator that currently generate an error: https://doc.rust-lang.org/stable/reference.html#unary-operator-expressions. Looks like it will be fixed in https://github.com/rust-lang/rust/pull/30538.
  • Swift has unsigned integer types which do not support the unary - operator. They provide a binary &- operator with modulo semantics for both signed and unsigned types, but that doesn't come in a unary variant.

stoklund avatar Dec 23 '15 22:12 stoklund

ARM Neon has a hardware negate instruction for the 64-bit types int8x8_t, int16x4_t, int32x2_t and float32x2_t, and the 128-bit types int8x16_t, int16x8_t, int32x4_t and float32x4_t. I'd favor keeping the negate instruction on signed and floating point types, since that can map directly to this ARM Neon instruction (even though x86 SSE doesn't have one) and be more expressive that way.

juj avatar Dec 23 '15 22:12 juj

This is pretty much a continuation of #191: SIMD really expresses operations, some of which are signed / unsigned and some of which are sign-agnostic. The type system is expressed in terms of signed / unsigned, and it sometimes maps weirdly.

IMO in this case neg should either:

  1. Exist for both signed and unsigned. On unsigned should just do the same as neg does on the same bit-represented signed.
  2. As @stoklund suggested drop neg from signed and unsigned, keep it only for floating-point.

jfbastien avatar Dec 23 '15 23:12 jfbastien

OK, I'm convinced, let's keep neg for unsigned and fix the polyfill and tests.

littledan avatar Dec 24 '15 00:12 littledan

Rust has unsigned types with a unary - operator that currently generate an error: https://doc.rust-lang.org/stable/reference.html#unary-operator-expressions. Looks like it will be fixed in rust-lang/rust#30538.

I'm not fixing it. I'm making sure it errors always. We don't have unary negation. What we have is unary not, so we do !x + 1, which is equivalent to ~x + 1 in c/c++.

Ada's modular types are like Rust's Wrapping types, and those do support unary negation. Ada's Positive type does not support unary negation, it will raise an exception.

So if your types are wrapping (unsigned::MAX + 1 == unsigned::MIN) then it's probably correct to support them. If that's not happening, this might be very suprising in some situations that unary negation works.

oli-obk avatar Dec 25 '15 10:12 oli-obk

Seems the consensus here is to have neg for both sign/unsigned ? Polyfill/tests still need to be fixed.

nmostafa avatar Feb 09 '16 19:02 nmostafa

Yes, I believe that was the consensus on the last call where we discussed it.

littledan avatar Feb 11 '16 09:02 littledan