From 13df9529fdec0f52ecf18960a6ff21d198f282cf Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 14 Mar 2025 06:22:42 -0700 Subject: [PATCH] Add documentation, tests and better parameter names to Float32x4. The same should happen for `Int32x4` and `Float64x2`, but this is a start. The existing class was basically uncommented and you had to guess or explore to find out what, fx, the returned values for the relational operators means. I've tried to discover and document the current behavior, but I had to fall back on "it's implementation specific" in some places where platforms behave differently. (For example it seems VM on Mac treats `.reciprocalSqrt()` as doing `.sqrt().reciprocal()` where the other platforms do `.reciprocal().sqrt()`, which makes a difference for exactly one value.) CoreLibraryReviewExempt: Doc and parameter name changes only. Tested: Added more tests to float32x4_test.dart. Change-Id: I3f8804f842d8a5d95e1d378a7edb9438a2f3ed2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/415000 Commit-Queue: Lasse Nielsen Reviewed-by: Alexander Markov --- .../patch/typed_data_patch.dart | 6 +- .../private/native_typed_data.dart | 28 +- .../js_runtime/lib/native_typed_data.dart | 422 +++-- .../js_runtime/lib/typed_data_patch.dart | 6 +- .../_internal/vm/lib/typed_data_patch.dart | 45 +- sdk/lib/_internal/wasm/lib/simd.dart | 26 +- sdk/lib/_internal/wasm/lib/simd_patch.dart | 7 +- sdk/lib/typed_data/typed_data.dart | 1409 ++++++++++++++++- tests/lib/typed_data/float32x4_test.dart | 917 ++++++----- tests/lib/typed_data/int32x4_test.dart | 88 + 10 files changed, 2296 insertions(+), 658 deletions(-) diff --git a/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart index 958d44eb3be..2c11a9db3d8 100644 --- a/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart +++ b/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart @@ -156,14 +156,14 @@ class Float32x4 { @patch factory Float32x4(double x, double y, double z, double w) = NativeFloat32x4; @patch - factory Float32x4.splat(double v) = NativeFloat32x4.splat; + factory Float32x4.splat(double value) = NativeFloat32x4.splat; @patch factory Float32x4.zero() = NativeFloat32x4.zero; @patch - factory Float32x4.fromInt32x4Bits(Int32x4 x) = + factory Float32x4.fromInt32x4Bits(Int32x4 bits) = NativeFloat32x4.fromInt32x4Bits; @patch - factory Float32x4.fromFloat64x2(Float64x2 v) = NativeFloat32x4.fromFloat64x2; + factory Float32x4.fromFloat64x2(Float64x2 xy) = NativeFloat32x4.fromFloat64x2; } @patch diff --git a/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart b/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart index 40d26491abb..7e6d89901d8 100644 --- a/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart +++ b/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart @@ -1219,20 +1219,20 @@ final class NativeFloat32x4 implements Float32x4 { if (w is! num) throw ArgumentError(w); } - NativeFloat32x4.splat(double v) : this(v, v, v, v); + NativeFloat32x4.splat(double value) : this(value, value, value, value); NativeFloat32x4.zero() : this._truncated(0.0, 0.0, 0.0, 0.0); - /// Returns a bit-wise copy of [i] as a Float32x4. - factory NativeFloat32x4.fromInt32x4Bits(Int32x4 i) { - _uint32view[0] = i.x; - _uint32view[1] = i.y; - _uint32view[2] = i.z; - _uint32view[3] = i.w; + /// Returns a bit-wise copy of [bits] as a Float32x4. + factory NativeFloat32x4.fromInt32x4Bits(Int32x4 bits) { + _uint32view[0] = bits.x; + _uint32view[1] = bits.y; + _uint32view[2] = bits.z; + _uint32view[3] = bits.w; return NativeFloat32x4._truncated(_list[0], _list[1], _list[2], _list[3]); } - NativeFloat32x4.fromFloat64x2(Float64x2 v) - : this._truncated(_truncate(v.x), _truncate(v.y), 0.0, 0.0); + NativeFloat32x4.fromFloat64x2(Float64x2 xy) + : this._truncated(_truncate(xy.x), _truncate(xy.y), 0.0, 0.0); /// Creates a new NativeFloat32x4. /// @@ -1380,11 +1380,11 @@ final class NativeFloat32x4 implements Float32x4 { } /// Returns a copy of this [Float32x4] each lane being scaled by [s]. - Float32x4 scale(double s) { - double _x = s * x; - double _y = s * y; - double _z = s * z; - double _w = s * w; + Float32x4 scale(double scale) { + double _x = scale * x; + double _y = scale * y; + double _z = scale * z; + double _w = scale * w; return NativeFloat32x4._doubles(_x, _y, _z, _w); } diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart index dd3f0160641..c1f820daf3b 100644 --- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart +++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart @@ -46,8 +46,10 @@ final class NativeByteBuffer extends JavaScriptObject return NativeInt8List.view(this, offsetInBytes, length); } - NativeUint8ClampedList asUint8ClampedList( - [int offsetInBytes = 0, int? length]) { + NativeUint8ClampedList asUint8ClampedList([ + int offsetInBytes = 0, + int? length, + ]) { return NativeUint8ClampedList.view(this, offsetInBytes, length); } @@ -121,7 +123,7 @@ final class NativeFloat32x4List extends Object NativeFloat32x4List._externalStorage(this._storage); NativeFloat32x4List._slowFromList(List list) - : _storage = NativeFloat32List(list.length * 4) { + : _storage = NativeFloat32List(list.length * 4) { for (int i = 0; i < list.length; i++) { var e = list[i]; _storage[(i * 4) + 0] = e.x; @@ -138,7 +140,8 @@ final class NativeFloat32x4List extends Object factory NativeFloat32x4List.fromList(List list) { if (list is NativeFloat32x4List) { return NativeFloat32x4List._externalStorage( - NativeFloat32List.fromList(list._storage)); + NativeFloat32List.fromList(list._storage), + ); } else { return NativeFloat32x4List._slowFromList(list); } @@ -177,7 +180,8 @@ final class NativeFloat32x4List extends Object Float32x4List sublist(int start, [int? end]) { var stop = _checkValidRange(start, end, this.length); return NativeFloat32x4List._externalStorage( - _storage.sublist(start * 4, stop * 4)); + _storage.sublist(start * 4, stop * 4), + ); } } @@ -207,7 +211,7 @@ final class NativeInt32x4List extends Object NativeInt32x4List._externalStorage(this._storage); NativeInt32x4List._slowFromList(List list) - : _storage = NativeInt32List(list.length * 4) { + : _storage = NativeInt32List(list.length * 4) { for (int i = 0; i < list.length; i++) { var e = list[i]; _storage[(i * 4) + 0] = e.x; @@ -224,7 +228,8 @@ final class NativeInt32x4List extends Object factory NativeInt32x4List.fromList(List list) { if (list is NativeInt32x4List) { return NativeInt32x4List._externalStorage( - NativeInt32List.fromList(list._storage)); + NativeInt32List.fromList(list._storage), + ); } else { return NativeInt32x4List._slowFromList(list); } @@ -262,7 +267,8 @@ final class NativeInt32x4List extends Object Int32x4List sublist(int start, [int? end]) { var stop = _checkValidRange(start, end, this.length); return NativeInt32x4List._externalStorage( - _storage.sublist(start * 4, stop * 4)); + _storage.sublist(start * 4, stop * 4), + ); } } @@ -292,7 +298,7 @@ final class NativeFloat64x2List extends Object NativeFloat64x2List._externalStorage(this._storage); NativeFloat64x2List._slowFromList(List list) - : _storage = NativeFloat64List(list.length * 2) { + : _storage = NativeFloat64List(list.length * 2) { for (int i = 0; i < list.length; i++) { var e = list[i]; _storage[(i * 2) + 0] = e.x; @@ -305,7 +311,8 @@ final class NativeFloat64x2List extends Object factory NativeFloat64x2List.fromList(List list) { if (list is NativeFloat64x2List) { return NativeFloat64x2List._externalStorage( - NativeFloat64List.fromList(list._storage)); + NativeFloat64List.fromList(list._storage), + ); } else { return NativeFloat64x2List._slowFromList(list); } @@ -342,7 +349,8 @@ final class NativeFloat64x2List extends Object Float64x2List sublist(int start, [int? end]) { var stop = _checkValidRange(start, end, this.length); return NativeFloat64x2List._externalStorage( - _storage.sublist(start * 2, stop * 2)); + _storage.sublist(start * 2, stop * 2), + ); } } @@ -412,7 +420,11 @@ final class NativeTypedData extends JavaScriptObject implements TypedData { @pragma('dart2js:prefer-inline') void _checkMutable(String operation) { HArrayFlagsCheck( - this, HArrayFlagsGet(this), ArrayFlags.unmodifiableCheck, operation); + this, + HArrayFlagsGet(this), + ArrayFlags.unmodifiableCheck, + operation, + ); } } @@ -552,7 +564,10 @@ final class NativeByteData extends NativeTypedData /// [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or /// equal to the length of [buffer]. factory NativeByteData.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); return length == null ? _create2(buffer, offsetInBytes) @@ -565,8 +580,10 @@ final class NativeByteData extends NativeTypedData ByteData asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, lengthInBytes), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, lengthInBytes), + ArrayFlags.unmodifiable, + ); } /// Returns the floating point number represented by the four bytes at @@ -864,9 +881,10 @@ final class NativeByteData extends NativeTypedData void _setUint8(int byteOffset, int value) native; static NativeByteData _create1(arg) => JS( - 'returns:NativeByteData;effects:none;depends:none;new:true', - 'new DataView(new ArrayBuffer(#))', - arg); + 'returns:NativeByteData;effects:none;depends:none;new:true', + 'new DataView(new ArrayBuffer(#))', + arg, + ); static NativeByteData _create2(arg1, arg2) => JS('NativeByteData', 'new DataView(#, #)', arg1, arg2); @@ -880,7 +898,11 @@ abstract final class NativeTypedArray extends NativeTypedData int get length => JS('JSUInt32', '#.length', this); void _setRangeFast( - int start, int end, NativeTypedArray source, int skipCount) { + int start, + int end, + NativeTypedArray source, + int skipCount, + ) { int targetLength = this.length; _checkPosition(start, targetLength, 'start'); _checkPosition(end, targetLength, 'end'); @@ -915,8 +937,12 @@ abstract final class NativeTypedArrayOfDouble extends NativeTypedArray JS('void', '#[#] = #', this, index, value); } - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { + void setRange( + int start, + int end, + Iterable iterable, [ + int skipCount = 0, + ]) { _checkMutable('setRange'); if (iterable is NativeTypedArrayOfDouble) { _setRangeFast(start, end, iterable, skipCount); @@ -938,8 +964,12 @@ abstract final class NativeTypedArrayOfInt extends NativeTypedArray JS('void', '#[#] = #', this, index, value); } - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { + void setRange( + int start, + int end, + Iterable iterable, [ + int skipCount = 0, + ]) { _checkMutable('setRange'); if (iterable is NativeTypedArrayOfInt) { _setRangeFast(start, end, iterable, skipCount); @@ -958,7 +988,10 @@ final class NativeFloat32List extends NativeTypedArrayOfDouble _create1(_ensureNativeList(elements)); factory NativeFloat32List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement; @@ -969,8 +1002,10 @@ final class NativeFloat32List extends NativeTypedArrayOfDouble Float32List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeFloat32List sublist(int start, [int? end]) { @@ -980,9 +1015,10 @@ final class NativeFloat32List extends NativeTypedArrayOfDouble } static NativeFloat32List _createLength(int arg) => JS( - 'returns:NativeFloat32List;effects:none;depends:none;new:true', - 'new Float32Array(#)', - arg); + 'returns:NativeFloat32List;effects:none;depends:none;new:true', + 'new Float32Array(#)', + arg, + ); static NativeFloat32List _create1(arg) => JS('NativeFloat32List', 'new Float32Array(#)', arg); @@ -1000,7 +1036,10 @@ final class NativeFloat64List extends NativeTypedArrayOfDouble _create1(_ensureNativeList(elements)); factory NativeFloat64List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement; @@ -1011,8 +1050,10 @@ final class NativeFloat64List extends NativeTypedArrayOfDouble Float64List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeFloat64List sublist(int start, [int? end]) { @@ -1022,9 +1063,10 @@ final class NativeFloat64List extends NativeTypedArrayOfDouble } static NativeFloat64List _createLength(int arg) => JS( - 'returns:NativeFloat64List;effects:none;depends:none;new:true', - 'new Float64Array(#)', - arg); + 'returns:NativeFloat64List;effects:none;depends:none;new:true', + 'new Float64Array(#)', + arg, + ); static NativeFloat64List _create1(arg) => JS('NativeFloat64List', 'new Float64Array(#)', arg); @@ -1042,7 +1084,10 @@ final class NativeInt16List extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeInt16List.view( - NativeByteBuffer buffer, int offsetInBytes, int? length) { + NativeByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement; @@ -1058,8 +1103,10 @@ final class NativeInt16List extends NativeTypedArrayOfInt Int16List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeInt16List sublist(int start, [int? end]) { @@ -1069,9 +1116,10 @@ final class NativeInt16List extends NativeTypedArrayOfInt } static NativeInt16List _createLength(int arg) => JS( - 'returns:NativeInt16List;effects:none;depends:none;new:true', - 'new Int16Array(#)', - arg); + 'returns:NativeInt16List;effects:none;depends:none;new:true', + 'new Int16Array(#)', + arg, + ); static NativeInt16List _create1(arg) => JS('NativeInt16List', 'new Int16Array(#)', arg); @@ -1089,7 +1137,10 @@ final class NativeInt32List extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeInt32List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement; @@ -1105,8 +1156,10 @@ final class NativeInt32List extends NativeTypedArrayOfInt Int32List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeInt32List sublist(int start, [int? end]) { @@ -1116,9 +1169,10 @@ final class NativeInt32List extends NativeTypedArrayOfInt } static NativeInt32List _createLength(int arg) => JS( - 'returns:NativeInt32List;effects:none;depends:none;new:true', - 'new Int32Array(#)', - arg); + 'returns:NativeInt32List;effects:none;depends:none;new:true', + 'new Int32Array(#)', + arg, + ); static NativeInt32List _create1(arg) => JS('NativeInt32List', 'new Int32Array(#)', arg); @@ -1136,7 +1190,10 @@ final class NativeInt8List extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeInt8List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); return length == null ? _create2(buffer, offsetInBytes) @@ -1152,8 +1209,10 @@ final class NativeInt8List extends NativeTypedArrayOfInt Int8List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeInt8List sublist(int start, [int? end]) { @@ -1163,9 +1222,10 @@ final class NativeInt8List extends NativeTypedArrayOfInt } static NativeInt8List _createLength(int arg) => JS( - 'returns:NativeInt8List;effects:none;depends:none;new:true', - 'new Int8Array(#)', - arg); + 'returns:NativeInt8List;effects:none;depends:none;new:true', + 'new Int8Array(#)', + arg, + ); static NativeInt8List _create1(arg) => JS('NativeInt8List', 'new Int8Array(#)', arg); @@ -1186,7 +1246,10 @@ final class NativeUint16List extends NativeTypedArrayOfInt _create1(_ensureNativeList(list)); factory NativeUint16List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement; @@ -1202,8 +1265,10 @@ final class NativeUint16List extends NativeTypedArrayOfInt Uint16List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeUint16List sublist(int start, [int? end]) { @@ -1213,9 +1278,10 @@ final class NativeUint16List extends NativeTypedArrayOfInt } static NativeUint16List _createLength(int arg) => JS( - 'returns:NativeUint16List;effects:none;depends:none;new:true', - 'new Uint16Array(#)', - arg); + 'returns:NativeUint16List;effects:none;depends:none;new:true', + 'new Uint16Array(#)', + arg, + ); static NativeUint16List _create1(arg) => JS('NativeUint16List', 'new Uint16Array(#)', arg); @@ -1233,7 +1299,10 @@ final class NativeUint32List extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeUint32List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); length ??= (buffer.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement; @@ -1249,8 +1318,10 @@ final class NativeUint32List extends NativeTypedArrayOfInt Uint32List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeUint32List sublist(int start, [int? end]) { @@ -1260,9 +1331,10 @@ final class NativeUint32List extends NativeTypedArrayOfInt } static NativeUint32List _createLength(int arg) => JS( - 'returns:NativeUint32List;effects:none;depends:none;new:true', - 'new Uint32Array(#)', - arg); + 'returns:NativeUint32List;effects:none;depends:none;new:true', + 'new Uint32Array(#)', + arg, + ); static NativeUint32List _create1(arg) => JS('NativeUint32List', 'new Uint32Array(#)', arg); @@ -1281,7 +1353,10 @@ final class NativeUint8ClampedList extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeUint8ClampedList.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); return length == null ? _create2(buffer, offsetInBytes) @@ -1299,21 +1374,29 @@ final class NativeUint8ClampedList extends NativeTypedArrayOfInt Uint8ClampedList asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeUint8ClampedList sublist(int start, [int? end]) { var stop = _checkValidRange(start, end, this.length); - var source = - JS('NativeUint8ClampedList', '#.subarray(#, #)', this, start, stop); + var source = JS( + 'NativeUint8ClampedList', + '#.subarray(#, #)', + this, + start, + stop, + ); return _create1(source); } static NativeUint8ClampedList _createLength(int arg) => JS( - 'returns:NativeUint8ClampedList;effects:none;depends:none;new:true', - 'new Uint8ClampedArray(#)', - arg); + 'returns:NativeUint8ClampedList;effects:none;depends:none;new:true', + 'new Uint8ClampedArray(#)', + arg, + ); static NativeUint8ClampedList _create1(arg) => JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#)', arg); @@ -1322,11 +1405,12 @@ final class NativeUint8ClampedList extends NativeTypedArrayOfInt JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2); static NativeUint8ClampedList _create3(arg1, arg2, arg3) => JS( - 'NativeUint8ClampedList', - 'new Uint8ClampedArray(#, #, #)', - arg1, - arg2, - arg3); + 'NativeUint8ClampedList', + 'new Uint8ClampedArray(#, #, #)', + arg1, + arg2, + arg3, + ); } // On some browsers Uint8ClampedArray is a subtype of Uint8Array. Marking @@ -1342,7 +1426,10 @@ final class NativeUint8List extends NativeTypedArrayOfInt _create1(_ensureNativeList(elements)); factory NativeUint8List.view( - ByteBuffer buffer, int offsetInBytes, int? length) { + ByteBuffer buffer, + int offsetInBytes, + int? length, + ) { _checkViewArguments(buffer, offsetInBytes, length); return length == null ? _create2(buffer, offsetInBytes) @@ -1360,8 +1447,10 @@ final class NativeUint8List extends NativeTypedArrayOfInt Uint8List asUnmodifiableView() { if (_isUnmodifiable()) return this; - return HArrayFlagsSet(_create3(_nativeBuffer, offsetInBytes, length), - ArrayFlags.unmodifiable); + return HArrayFlagsSet( + _create3(_nativeBuffer, offsetInBytes, length), + ArrayFlags.unmodifiable, + ); } NativeUint8List sublist(int start, [int? end]) { @@ -1371,9 +1460,10 @@ final class NativeUint8List extends NativeTypedArrayOfInt } static NativeUint8List _createLength(int arg) => JS( - 'returns:NativeUint8List;effects:none;depends:none;new:true', - 'new Uint8Array(#)', - arg); + 'returns:NativeUint8List;effects:none;depends:none;new:true', + 'new Uint8Array(#)', + arg, + ); static NativeUint8List _create1(arg) => JS('NativeUint8List', 'new Uint8Array(#)', arg); @@ -1403,10 +1493,10 @@ final class NativeFloat32x4 implements Float32x4 { } NativeFloat32x4(double x, double y, double z, double w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w) { + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w) { // We would prefer to check for `double` but in dart2js we can't see the // difference anyway. if (x is! num) throw ArgumentError(x); @@ -1415,29 +1505,29 @@ final class NativeFloat32x4 implements Float32x4 { if (w is! num) throw ArgumentError(w); } - NativeFloat32x4.splat(double v) : this(v, v, v, v); + NativeFloat32x4.splat(double value) : this(value, value, value, value); NativeFloat32x4.zero() : this._truncated(0.0, 0.0, 0.0, 0.0); - /// Returns a bit-wise copy of [i] as a Float32x4. - factory NativeFloat32x4.fromInt32x4Bits(Int32x4 i) { - _uint32view[0] = i.x; - _uint32view[1] = i.y; - _uint32view[2] = i.z; - _uint32view[3] = i.w; + /// Returns a bit-wise copy of [bits] as a Float32x4. + factory NativeFloat32x4.fromInt32x4Bits(Int32x4 bits) { + _uint32view[0] = bits.x; + _uint32view[1] = bits.y; + _uint32view[2] = bits.z; + _uint32view[3] = bits.w; return NativeFloat32x4._truncated(_list[0], _list[1], _list[2], _list[3]); } - NativeFloat32x4.fromFloat64x2(Float64x2 v) - : this._truncated(_truncate(v.x), _truncate(v.y), 0.0, 0.0); + NativeFloat32x4.fromFloat64x2(Float64x2 xy) + : this._truncated(_truncate(xy.x), _truncate(xy.y), 0.0, 0.0); /// Creates a new NativeFloat32x4. /// /// Does not verify if the given arguments are non-null. NativeFloat32x4._doubles(double x, double y, double z, double w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w); + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w); /// Creates a new NativeFloat32x4. /// @@ -1498,7 +1588,11 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z < other.z; bool _cw = w < other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Relational less than or equal. @@ -1508,7 +1602,11 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z <= other.z; bool _cw = w <= other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Relational greater than. @@ -1518,7 +1616,11 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z > other.z; bool _cw = w > other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Relational greater than or equal. @@ -1528,7 +1630,11 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z >= other.z; bool _cw = w >= other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Relational equal. @@ -1538,7 +1644,11 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z == other.z; bool _cw = w == other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Relational not-equal. @@ -1548,15 +1658,19 @@ final class NativeFloat32x4 implements Float32x4 { bool _cz = z != other.z; bool _cw = w != other.w; return NativeInt32x4._truncated( - _cx ? -1 : 0, _cy ? -1 : 0, _cz ? -1 : 0, _cw ? -1 : 0); + _cx ? -1 : 0, + _cy ? -1 : 0, + _cz ? -1 : 0, + _cw ? -1 : 0, + ); } /// Returns a copy of this [Float32x4] each lane being scaled by [s]. - Float32x4 scale(double s) { - double _x = s * x; - double _y = s * y; - double _z = s * z; - double _w = s * w; + Float32x4 scale(double scale) { + double _x = scale * x; + double _y = scale * y; + double _z = scale * z; + double _w = scale * w; return NativeFloat32x4._doubles(_x, _y, _z, _w); } @@ -1738,10 +1852,10 @@ final class NativeInt32x4 implements Int32x4 { } NativeInt32x4(int x, int y, int z, int w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w) { + : this.x = _truncate(x), + this.y = _truncate(y), + this.z = _truncate(z), + this.w = _truncate(w) { if (x != this.x && x is! int) throw ArgumentError(x); if (y != this.y && y is! int) throw ArgumentError(y); if (z != this.z && z is! int) throw ArgumentError(z); @@ -1749,10 +1863,10 @@ final class NativeInt32x4 implements Int32x4 { } NativeInt32x4.bool(bool x, bool y, bool z, bool w) - : this.x = x ? -1 : 0, - this.y = y ? -1 : 0, - this.z = z ? -1 : 0, - this.w = w ? -1 : 0; + : this.x = x ? -1 : 0, + this.y = y ? -1 : 0, + this.z = z ? -1 : 0, + this.w = w ? -1 : 0; /// Returns a bit-wise copy of [f] as a Int32x4. factory NativeInt32x4.fromFloat32x4Bits(Float32x4 f) { @@ -1774,10 +1888,11 @@ final class NativeInt32x4 implements Int32x4 { // Dart2js uses unsigned results for bit-operations. // We use "JS" to fall back to the signed versions. return NativeInt32x4._truncated( - JS('int', '# | #', x, other.x), - JS('int', '# | #', y, other.y), - JS('int', '# | #', z, other.z), - JS('int', '# | #', w, other.w)); + JS('int', '# | #', x, other.x), + JS('int', '# | #', y, other.y), + JS('int', '# | #', z, other.z), + JS('int', '# | #', w, other.w), + ); } /// The bit-wise and operator. @@ -1785,10 +1900,11 @@ final class NativeInt32x4 implements Int32x4 { // Dart2js uses unsigned results for bit-operations. // We use "JS" to fall back to the signed versions. return NativeInt32x4._truncated( - JS('int', '# & #', x, other.x), - JS('int', '# & #', y, other.y), - JS('int', '# & #', z, other.z), - JS('int', '# & #', w, other.w)); + JS('int', '# & #', x, other.x), + JS('int', '# & #', y, other.y), + JS('int', '# & #', z, other.z), + JS('int', '# & #', w, other.w), + ); } /// The bit-wise xor operator. @@ -1796,37 +1912,41 @@ final class NativeInt32x4 implements Int32x4 { // Dart2js uses unsigned results for bit-operations. // We use "JS" to fall back to the signed versions. return NativeInt32x4._truncated( - JS('int', '# ^ #', x, other.x), - JS('int', '# ^ #', y, other.y), - JS('int', '# ^ #', z, other.z), - JS('int', '# ^ #', w, other.w)); + JS('int', '# ^ #', x, other.x), + JS('int', '# ^ #', y, other.y), + JS('int', '# ^ #', z, other.z), + JS('int', '# ^ #', w, other.w), + ); } Int32x4 operator +(Int32x4 other) { // Avoid going through the typed array by "| 0" the result. return NativeInt32x4._truncated( - JS('int', '(# + #) | 0', x, other.x), - JS('int', '(# + #) | 0', y, other.y), - JS('int', '(# + #) | 0', z, other.z), - JS('int', '(# + #) | 0', w, other.w)); + JS('int', '(# + #) | 0', x, other.x), + JS('int', '(# + #) | 0', y, other.y), + JS('int', '(# + #) | 0', z, other.z), + JS('int', '(# + #) | 0', w, other.w), + ); } Int32x4 operator -(Int32x4 other) { // Avoid going through the typed array by "| 0" the result. return NativeInt32x4._truncated( - JS('int', '(# - #) | 0', x, other.x), - JS('int', '(# - #) | 0', y, other.y), - JS('int', '(# - #) | 0', z, other.z), - JS('int', '(# - #) | 0', w, other.w)); + JS('int', '(# - #) | 0', x, other.x), + JS('int', '(# - #) | 0', y, other.y), + JS('int', '(# - #) | 0', z, other.z), + JS('int', '(# - #) | 0', w, other.w), + ); } Int32x4 operator -() { // Avoid going through the typed array by "| 0" the result. return NativeInt32x4._truncated( - JS('int', '(-#) | 0', x), - JS('int', '(-#) | 0', y), - JS('int', '(-#) | 0', z), - JS('int', '(-#) | 0', w)); + JS('int', '(-#) | 0', x), + JS('int', '(-#) | 0', y), + JS('int', '(-#) | 0', z), + JS('int', '(-#) | 0', w), + ); } /// Extract the top bit from each lane return them in the first 4 bits. @@ -1970,7 +2090,11 @@ final class NativeInt32x4 implements Int32x4 { intView[2] = _z; intView[3] = _w; return NativeFloat32x4._truncated( - floatList[0], floatList[1], floatList[2], floatList[3]); + floatList[0], + floatList[1], + floatList[2], + floatList[3], + ); } } @@ -2075,13 +2199,17 @@ final class NativeFloat64x2 implements Float64x2 { /// Returns the lane-wise minimum value in this [Float64x2] or [other]. Float64x2 min(Float64x2 other) { return NativeFloat64x2._doubles( - x < other.x ? x : other.x, y < other.y ? y : other.y); + x < other.x ? x : other.x, + y < other.y ? y : other.y, + ); } /// Returns the lane-wise maximum value in this [Float64x2] or [other]. Float64x2 max(Float64x2 other) { return NativeFloat64x2._doubles( - x > other.x ? x : other.x, y > other.y ? y : other.y); + x > other.x ? x : other.x, + y > other.y ? y : other.y, + ); } /// Returns the lane-wise square root of this [Float64x2]. diff --git a/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart b/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart index c211cbb6361..9eafe75d469 100644 --- a/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart @@ -157,14 +157,14 @@ class Float32x4 { @patch factory Float32x4(double x, double y, double z, double w) = NativeFloat32x4; @patch - factory Float32x4.splat(double v) = NativeFloat32x4.splat; + factory Float32x4.splat(double value) = NativeFloat32x4.splat; @patch factory Float32x4.zero() = NativeFloat32x4.zero; @patch - factory Float32x4.fromInt32x4Bits(Int32x4 x) = + factory Float32x4.fromInt32x4Bits(Int32x4 bits) = NativeFloat32x4.fromInt32x4Bits; @patch - factory Float32x4.fromFloat64x2(Float64x2 v) = NativeFloat32x4.fromFloat64x2; + factory Float32x4.fromFloat64x2(Float64x2 xy) = NativeFloat32x4.fromFloat64x2; } @patch diff --git a/sdk/lib/_internal/vm/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart index 8b54344ffd0..02d83ce3ff4 100644 --- a/sdk/lib/_internal/vm/lib/typed_data_patch.dart +++ b/sdk/lib/_internal/vm/lib/typed_data_patch.dart @@ -3777,10 +3777,6 @@ class Float32x4 { @patch @pragma("vm:prefer-inline") factory Float32x4(double x, double y, double z, double w) { - _throwIfNull(x, 'x'); - _throwIfNull(y, 'y'); - _throwIfNull(z, 'z'); - _throwIfNull(w, 'w'); return _Float32x4FromDoubles(x, y, z, w); } @@ -3796,10 +3792,7 @@ class Float32x4 { @patch @pragma("vm:prefer-inline") - factory Float32x4.splat(double v) { - _throwIfNull(v, 'v'); - return _Float32x4Splat(v); - } + factory Float32x4.splat(double value) => _Float32x4Splat(value); @pragma("vm:recognized", "other") @pragma("vm:exact-result-type", _Float32x4) @@ -3822,7 +3815,7 @@ class Float32x4 { @pragma("vm:recognized", "other") @pragma("vm:exact-result-type", _Float32x4) @pragma("vm:external-name", "Float32x4_fromFloat64x2") - external factory Float32x4.fromFloat64x2(Float64x2 v); + external factory Float32x4.fromFloat64x2(Float64x2 xy); } @pragma('vm:deeply-immutable') @@ -3874,7 +3867,7 @@ final class _Float32x4 implements Float32x4 { @pragma("vm:recognized", "other") @pragma("vm:exact-result-type", _Float32x4) @pragma("vm:external-name", "Float32x4_scale") - external Float32x4 scale(double s); + external Float32x4 scale(double scale); @pragma("vm:recognized", "other") @pragma("vm:exact-result-type", _Float32x4) @pragma("vm:external-name", "Float32x4_abs") @@ -3914,7 +3907,6 @@ final class _Float32x4 implements Float32x4 { @pragma("vm:prefer-inline") Float32x4 withX(double x) { - _throwIfNull(x, 'x'); return _withX(x); } @@ -3925,7 +3917,6 @@ final class _Float32x4 implements Float32x4 { @pragma("vm:prefer-inline") Float32x4 withY(double y) { - _throwIfNull(y, 'y'); return _withY(y); } @@ -3936,7 +3927,6 @@ final class _Float32x4 implements Float32x4 { @pragma("vm:prefer-inline") Float32x4 withZ(double z) { - _throwIfNull(z, 'z'); return _withZ(z); } @@ -3947,7 +3937,6 @@ final class _Float32x4 implements Float32x4 { @pragma("vm:prefer-inline") Float32x4 withW(double w) { - _throwIfNull(w, 'w'); return _withW(w); } @@ -3984,10 +3973,6 @@ class Int32x4 { @patch @pragma("vm:prefer-inline") factory Int32x4(int x, int y, int z, int w) { - _throwIfNull(x, 'x'); - _throwIfNull(y, 'y'); - _throwIfNull(z, 'z'); - _throwIfNull(w, 'w'); return _Int32x4FromInts(x, y, z, w); } @@ -3999,10 +3984,6 @@ class Int32x4 { @patch @pragma("vm:prefer-inline") factory Int32x4.bool(bool x, bool y, bool z, bool w) { - _throwIfNull(x, 'x'); - _throwIfNull(y, 'y'); - _throwIfNull(z, 'z'); - _throwIfNull(w, 'w'); return _Int32x4FromBools(x, y, z, w); } @@ -4053,7 +4034,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline") Int32x4 withX(int x) { - _throwIfNull(x, 'x'); return _withX(x); } @@ -4063,7 +4043,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline") Int32x4 withY(int y) { - _throwIfNull(y, 'y'); return _withY(y); } @@ -4073,7 +4052,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline") Int32x4 withZ(int z) { - _throwIfNull(z, 'z'); return _withZ(z); } @@ -4083,7 +4061,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline") Int32x4 withW(int w) { - _throwIfNull(w, 'w'); return _withW(w); } @@ -4110,7 +4087,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline", _Int32x4) Int32x4 withFlagX(bool x) { - _throwIfNull(x, 'x'); return _withFlagX(x); } @@ -4121,7 +4097,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline", _Int32x4) Int32x4 withFlagY(bool y) { - _throwIfNull(y, 'y'); return _withFlagY(y); } @@ -4132,7 +4107,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline", _Int32x4) Int32x4 withFlagZ(bool z) { - _throwIfNull(z, 'z'); return _withFlagZ(z); } @@ -4143,7 +4117,6 @@ final class _Int32x4 implements Int32x4 { @pragma("vm:prefer-inline", _Int32x4) Int32x4 withFlagW(bool w) { - _throwIfNull(w, 'w'); return _withFlagW(w); } @@ -4164,8 +4137,6 @@ class Float64x2 { @patch @pragma("vm:prefer-inline") factory Float64x2(double x, double y) { - _throwIfNull(x, 'x'); - _throwIfNull(y, 'y'); return _Float64x2FromDoubles(x, y); } @@ -4177,7 +4148,6 @@ class Float64x2 { @patch @pragma("vm:prefer-inline") factory Float64x2.splat(double v) { - _throwIfNull(v, 'v'); return _Float64x2Splat(v); } @@ -4244,7 +4214,6 @@ final class _Float64x2 implements Float64x2 { @pragma("vm:prefer-inline") Float64x2 withX(double x) { - _throwIfNull(x, 'x'); return _withX(x); } @@ -4255,7 +4224,6 @@ final class _Float64x2 implements Float64x2 { @pragma("vm:prefer-inline") Float64x2 withY(double y) { - _throwIfNull(y, 'y'); return _withY(y); } @@ -5435,13 +5403,6 @@ int _toClampedUint8(int value) { return value; } -@pragma("vm:prefer-inline") -void _throwIfNull(val, String name) { - if (val == null) { - throw ArgumentError.notNull(name); - } -} - // Length should be non-negative. @pragma("vm:recognized", "other") @pragma("vm:prefer-inline") diff --git a/sdk/lib/_internal/wasm/lib/simd.dart b/sdk/lib/_internal/wasm/lib/simd.dart index 6b6c9254115..b5debe10698 100644 --- a/sdk/lib/_internal/wasm/lib/simd.dart +++ b/sdk/lib/_internal/wasm/lib/simd.dart @@ -343,19 +343,19 @@ final class NaiveFloat32x4 extends WasmTypedDataBase implements Float32x4 { this.z = _truncate(z), this.w = _truncate(w); - NaiveFloat32x4.splat(double v) : this(v, v, v, v); + NaiveFloat32x4.splat(double value) : this(value, value, value, value); NaiveFloat32x4.zero() : this._truncated(0.0, 0.0, 0.0, 0.0); - factory NaiveFloat32x4.fromInt32x4Bits(Int32x4 i) { - _uint32view[0] = i.x; - _uint32view[1] = i.y; - _uint32view[2] = i.z; - _uint32view[3] = i.w; + factory NaiveFloat32x4.fromInt32x4Bits(Int32x4 bits) { + _uint32view[0] = bits.x; + _uint32view[1] = bits.y; + _uint32view[2] = bits.z; + _uint32view[3] = bits.w; return NaiveFloat32x4._truncated(_list[0], _list[1], _list[2], _list[3]); } - NaiveFloat32x4.fromFloat64x2(Float64x2 v) - : this._truncated(_truncate(v.x), _truncate(v.y), 0.0, 0.0); + NaiveFloat32x4.fromFloat64x2(Float64x2 xy) + : this._truncated(_truncate(xy.x), _truncate(xy.y), 0.0, 0.0); NaiveFloat32x4._doubles(double x, double y, double z, double w) : this.x = _truncate(x), @@ -487,11 +487,11 @@ final class NaiveFloat32x4 extends WasmTypedDataBase implements Float32x4 { ); } - Float32x4 scale(double s) { - double _x = s * x; - double _y = s * y; - double _z = s * z; - double _w = s * w; + Float32x4 scale(double scale) { + double _x = scale * x; + double _y = scale * y; + double _z = scale * z; + double _w = scale * w; return NaiveFloat32x4._doubles(_x, _y, _z, _w); } diff --git a/sdk/lib/_internal/wasm/lib/simd_patch.dart b/sdk/lib/_internal/wasm/lib/simd_patch.dart index 883f29d24c3..497159800a5 100644 --- a/sdk/lib/_internal/wasm/lib/simd_patch.dart +++ b/sdk/lib/_internal/wasm/lib/simd_patch.dart @@ -28,16 +28,17 @@ class Float32x4 { factory Float32x4(double x, double y, double z, double w) = NaiveFloat32x4; @patch - factory Float32x4.splat(double v) = NaiveFloat32x4.splat; + factory Float32x4.splat(double value) = NaiveFloat32x4.splat; @patch factory Float32x4.zero() = NaiveFloat32x4.zero; @patch - factory Float32x4.fromInt32x4Bits(Int32x4 x) = NaiveFloat32x4.fromInt32x4Bits; + factory Float32x4.fromInt32x4Bits(Int32x4 bits) = + NaiveFloat32x4.fromInt32x4Bits; @patch - factory Float32x4.fromFloat64x2(Float64x2 v) = NaiveFloat32x4.fromFloat64x2; + factory Float32x4.fromFloat64x2(Float64x2 xy) = NaiveFloat32x4.fromFloat64x2; } @patch diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart index 08b3b44fac5..219fe3dca6b 100644 --- a/sdk/lib/typed_data/typed_data.dart +++ b/sdk/lib/typed_data/typed_data.dart @@ -2645,381 +2645,1682 @@ abstract final class Float64x2List static const int bytesPerElement = 16; } -/// Float32x4 immutable value type and operations. +/// Four 32-bit floating point values. /// -/// Float32x4 stores 4 32-bit floating point values in "lanes". -/// The lanes are "x", "y", "z", and "w" respectively. +/// Float32x4 stores four 32-bit floating point values in "lanes". +/// The lanes are named [x], [y], [z], and [w] respectively. /// -/// It is a compile-time error for a class to attempt to extend or implement -/// `Float32x4`. +/// Single operations can be performed on the multiple values of one or +/// more `Float32x4`s, which will perform the corresponding operation +/// for each lane of the operands, and provide a new `Float32x4` (or similar +/// multi-value) result with the results from each lane. +/// +/// The `Float32x4` class cannot be extended or implemented. abstract final class Float32x4 { + /// Creates a `Float32x4` containing the 32-bit float values of the arguments. + /// + /// The created value has [Float32x4.x], [Float32x4.y], [Float32x4.z] + /// and [Float32x4.w] values that are the 32-bit floating point values + /// created from the [x], [y], [z] and [w] arguments by conversion + /// from 64-bit floating point to 32-bit floating point values. + /// + /// The conversion from 64-bit float to 32-bit float loses significant + /// precision, and may become zero or infinite even if the original 64-bit + /// floating point value was non-zero and finite. external factory Float32x4(double x, double y, double z, double w); - external factory Float32x4.splat(double v); + + /// Creates a `Float32x4` with the same 32-bit float value four times. + /// + /// The created value has the same [Float32x4.x], [Float32x4.y], [Float32x4.z] + /// and [Float32x4.w] value, which is the 32-bit floating point value + /// created by converting the 64-bit floating point [value] to a + /// 32-bit floating point value. + /// + /// The conversion from 64-bit float to 32-bit float loses significant + /// precision, and may become zero or infinite even if the original 64-bit + /// floating point value was non-zero and finite. + external factory Float32x4.splat(double value); + + /// Creates a `Float32x4` with all values being zero. + /// + /// The created value has the same [Float32x4.x], [Float32x4.y], [Float32x4.z] + /// and [Float32x4.w] value, which is the 32-bit floating point zero value. external factory Float32x4.zero(); - external factory Float32x4.fromInt32x4Bits(Int32x4 x); - /// Sets the x and y lanes to their respective values in [v] and sets the z - /// and w lanes to 0.0. - external factory Float32x4.fromFloat64x2(Float64x2 v); + /// Creates a `Float32x4` with 32-bit float values from the provided bits. + /// + /// The created value has [Float32x4.x], [Float32x4.y], [Float32x4.z] + /// and [Float32x4.w] values, which are the 32-bit floating point values + /// of the bit-representations of the corresponding lanes of [bits]. + /// + /// The conversion is performed using the *platform endianness* for both + /// 32-bit integers and 32-bit floating point numbers. + external factory Float32x4.fromInt32x4Bits(Int32x4 bits); - /// Addition operator. + /// Creates a `Float32x4` with its [x] and [y] lanes set to values from [xy]. + /// + /// The created value has [Float32x4.x] and [Float32x4.y] values + /// which are the conversions of the [Float64x2.x] and [Float64x2.y] lanes + /// of [xy] to 32-bit floating point values. + /// The [Float32x4.z] and [Float32x4.w] lanes are set to the zero value. + external factory Float32x4.fromFloat64x2(Float64x2 xy); + + /// Lane-wise addition. + /// + /// Adds the value of each lane of this value + /// to the value of the corresponding lane of [other]. + /// + /// Returns the result for each lane. Float32x4 operator +(Float32x4 other); - /// Negate operator. + /// Lane-wise negation. + /// + /// Returns a result where each lane is the negation of the corresponding + /// lane of this value. Float32x4 operator -(); - /// Subtraction operator. + /// Lane-wise subtraction. + /// + /// Subtracts the value of each lane of [other] + /// from the value of the corresponding lane of this value. + /// + /// Returns the result for each lane. Float32x4 operator -(Float32x4 other); - /// Multiplication operator. + /// Lane-wise multiplication. + /// + /// Multiplies the value of each lane of this value + /// with the value of the corresponding lane of [other]. + /// + /// Returns the result for each lane. Float32x4 operator *(Float32x4 other); - /// Division operator. + /// Lane-wise division. + /// + /// Divides the value of each lane of this value + /// with the value of the corresponding lane of [other]. + /// + /// Returns the result for each lane. Float32x4 operator /(Float32x4 other); - /// Relational less than. + /// Lane-wise less-than comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *less than* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 lessThan(Float32x4 other); - /// Relational less than or equal. + /// Lane-wise less-than-or-equal comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *less than or equal to* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 lessThanOrEqual(Float32x4 other); - /// Relational greater than. + /// Lane-wise greater-than comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *greater than* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 greaterThan(Float32x4 other); - /// Relational greater than or equal. + /// Lane-wise greater-than-or-equal comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *greater than or equal to* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 greaterThanOrEqual(Float32x4 other); - /// Relational equal. + /// Lane-wise equals comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *equal to* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 equal(Float32x4 other); - /// Relational not-equal. + /// Lane-wise not-equals comparison. + /// + /// Compares the 32-bit floating point value of each lane of this + /// to the value of the corresponding lane of [other], + /// using 32-bit floating point comparison. + /// _For floating point comparisons, a comparison with a NaN value is + /// always false, and -0.0 (negative zero) is considered equal to 0.0 + /// (positive zero), and not less strictly than it._ + /// The result for a lane is a 32-bit signed integer which is -1 + /// (all bits set) if the value from this object is *not equal to* + /// the value from [other], and the result is 0 (all bits cleared) if not, + /// including if either value is a NaN value. + /// + /// Returns four values that are always either 0 or -1. Int32x4 notEqual(Float32x4 other); - /// Returns a copy of this [Float32x4] each lane being scaled by [s]. - /// Equivalent to this * new Float32x4.splat(s) - Float32x4 scale(double s); + /// Lane-wise multiplication by [scale]. + /// + /// Returns a result where each lane is the result of multiplying the + /// corresponding lane of this value with [scale]. + /// This can happen either by converting the lane value to a 64-bit + /// floating point value, multiplying it with [scale] and converting + /// the result back to a 32-bit floating point value, + /// or by converting [scale] to a 32-bit floating point value + /// and performing a 32-bit floating point multiplication. + /// + /// In the latter case it is equivalent to `thisValue * Float32x4.splat(s)`. + Float32x4 scale(double scale); - /// The lane-wise absolute value of this [Float32x4]. + /// Lane-wise conversion to absolute value. + /// + /// Converts each lane's value to a non-negative value + /// by negating the value if it is negative, + /// and keeping the original value if it is not negative. + /// + /// Returns the result for each lane. Float32x4 abs(); - /// Lane-wise clamp this [Float32x4] to be in the range - /// [lowerLimit]-[upperLimit]. + /// Lane-wise clamp to a range. + /// + /// Clamps the value of each lane to a minimum value + /// of the corresponding lane of [lowerLimit] + /// and a maximum value of the corresponding lane of [upperLimit]. + /// If the original value is lower than the minimum value, the result is + /// the minimum value, and if original value is greater than the maximum + /// value, the result is the maximum value. + /// The result is unspecified if the maximum value is lower than the minimum + /// value, or if any of the three values is a NaN value, other than that + /// the result will be one of those three values, or possibly a different + /// NaN value if any value is a NaN value. + /// + /// Returns the result for each lane. Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit); - /// Extracted x value. + /// The value of the "x" lane. double get x; - /// Extracted y value. + /// The value of the "y" lane. double get y; - /// Extracted z value. + /// The value of the "z" lane. double get z; - /// Extracted w value. + /// The value of the "w" lane. double get w; - /// Extract the sign bits from each lane return them in the first 4 bits. - /// "x" lane is bit 0. - /// "y" lane is bit 1. - /// "z" lane is bit 2. - /// "w" lane is bit 3. + /// The sign bits of each lane as single bits. + /// + /// The sign bits of each lane's 32-bit floating point value + /// are stored in the low four bits of this value: + /// - The [x] lane in bit 0. + /// - The [y] lane in bit 1. + /// - The [z] lane in bit 2. + /// - The [w] lane in bit 3. int get signMask; - /// Mask passed to [shuffle] or [shuffleMix]. + // Masks passed to [shuffle] or [shuffleMix]. + + /// Shuffle mask "xxxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxxx = 0x00; + + /// Shuffle mask "xxxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxxy = 0x40; + + /// Shuffle mask "xxxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxxz = 0x80; + + /// Shuffle mask "xxxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxxw = 0xC0; + + /// Shuffle mask "xxyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxyx = 0x10; + + /// Shuffle mask "xxyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxyy = 0x50; + + /// Shuffle mask "xxyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxyz = 0x90; + + /// Shuffle mask "xxyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxyw = 0xD0; + + /// Shuffle mask "xxzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxzx = 0x20; + + /// Shuffle mask "xxzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxzy = 0x60; + + /// Shuffle mask "xxzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxzz = 0xA0; + + /// Shuffle mask "xxzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxzw = 0xE0; + + /// Shuffle mask "xxwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxwx = 0x30; + + /// Shuffle mask "xxwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxwy = 0x70; + + /// Shuffle mask "xxwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxwz = 0xB0; + + /// Shuffle mask "xxww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xxww = 0xF0; + + /// Shuffle mask "xyxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyxx = 0x04; + + /// Shuffle mask "xyxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyxy = 0x44; + + /// Shuffle mask "xyxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyxz = 0x84; + + /// Shuffle mask "xyxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyxw = 0xC4; + + /// Shuffle mask "xyyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyyx = 0x14; + + /// Shuffle mask "xyyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyyy = 0x54; + + /// Shuffle mask "xyyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyyz = 0x94; + + /// Shuffle mask "xyyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyyw = 0xD4; + + /// Shuffle mask "xyzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyzx = 0x24; + + /// Shuffle mask "xyzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyzy = 0x64; + + /// Shuffle mask "xyzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyzz = 0xA4; + + /// Shuffle mask "xyzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyzw = 0xE4; + + /// Shuffle mask "xywx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xywx = 0x34; + + /// Shuffle mask "xywy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xywy = 0x74; + + /// Shuffle mask "xywz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xywz = 0xB4; + + /// Shuffle mask "xyww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xyww = 0xF4; + + /// Shuffle mask "xzxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzxx = 0x08; + + /// Shuffle mask "xzxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzxy = 0x48; + + /// Shuffle mask "xzxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzxz = 0x88; + + /// Shuffle mask "xzxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzxw = 0xC8; + + /// Shuffle mask "xzyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzyx = 0x18; + + /// Shuffle mask "xzyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzyy = 0x58; + + /// Shuffle mask "xzyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzyz = 0x98; + + /// Shuffle mask "xzyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzyw = 0xD8; + + /// Shuffle mask "xzzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzzx = 0x28; + + /// Shuffle mask "xzzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzzy = 0x68; + + /// Shuffle mask "xzzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzzz = 0xA8; + + /// Shuffle mask "xzzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzzw = 0xE8; + + /// Shuffle mask "xzwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzwx = 0x38; + + /// Shuffle mask "xzwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzwy = 0x78; + + /// Shuffle mask "xzwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzwz = 0xB8; + + /// Shuffle mask "xzww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xzww = 0xF8; + + /// Shuffle mask "xwxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwxx = 0x0C; + + /// Shuffle mask "xwxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwxy = 0x4C; + + /// Shuffle mask "xwxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwxz = 0x8C; + + /// Shuffle mask "xwxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwxw = 0xCC; + + /// Shuffle mask "xwyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwyx = 0x1C; + + /// Shuffle mask "xwyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwyy = 0x5C; + + /// Shuffle mask "xwyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwyz = 0x9C; + + /// Shuffle mask "xwyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwyw = 0xDC; + + /// Shuffle mask "xwzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwzx = 0x2C; + + /// Shuffle mask "xwzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwzy = 0x6C; + + /// Shuffle mask "xwzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwzz = 0xAC; + + /// Shuffle mask "xwzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwzw = 0xEC; + + /// Shuffle mask "xwwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwwx = 0x3C; + + /// Shuffle mask "xwwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwwy = 0x7C; + + /// Shuffle mask "xwwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwwz = 0xBC; + + /// Shuffle mask "xwww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int xwww = 0xFC; + + /// Shuffle mask "yxxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxxx = 0x01; + + /// Shuffle mask "yxxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxxy = 0x41; + + /// Shuffle mask "yxxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxxz = 0x81; + + /// Shuffle mask "yxxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxxw = 0xC1; + + /// Shuffle mask "yxyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxyx = 0x11; + + /// Shuffle mask "yxyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxyy = 0x51; + + /// Shuffle mask "yxyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxyz = 0x91; + + /// Shuffle mask "yxyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxyw = 0xD1; + + /// Shuffle mask "yxzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxzx = 0x21; + + /// Shuffle mask "yxzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxzy = 0x61; + + /// Shuffle mask "yxzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxzz = 0xA1; + + /// Shuffle mask "yxzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxzw = 0xE1; + + /// Shuffle mask "yxwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxwx = 0x31; + + /// Shuffle mask "yxwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxwy = 0x71; + + /// Shuffle mask "yxwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxwz = 0xB1; + + /// Shuffle mask "yxww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yxww = 0xF1; + + /// Shuffle mask "yyxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyxx = 0x05; + + /// Shuffle mask "yyxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyxy = 0x45; + + /// Shuffle mask "yyxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyxz = 0x85; + + /// Shuffle mask "yyxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyxw = 0xC5; + + /// Shuffle mask "yyyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyyx = 0x15; + + /// Shuffle mask "yyyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyyy = 0x55; + + /// Shuffle mask "yyyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyyz = 0x95; + + /// Shuffle mask "yyyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyyw = 0xD5; + + /// Shuffle mask "yyzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyzx = 0x25; + + /// Shuffle mask "yyzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyzy = 0x65; + + /// Shuffle mask "yyzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyzz = 0xA5; + + /// Shuffle mask "yyzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyzw = 0xE5; + + /// Shuffle mask "yywx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yywx = 0x35; + + /// Shuffle mask "yywy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yywy = 0x75; + + /// Shuffle mask "yywz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yywz = 0xB5; + + /// Shuffle mask "yyww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yyww = 0xF5; + + /// Shuffle mask "yzxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzxx = 0x09; + + /// Shuffle mask "yzxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzxy = 0x49; + + /// Shuffle mask "yzxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzxz = 0x89; + + /// Shuffle mask "yzxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzxw = 0xC9; + + /// Shuffle mask "yzyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzyx = 0x19; + + /// Shuffle mask "yzyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzyy = 0x59; + + /// Shuffle mask "yzyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzyz = 0x99; + + /// Shuffle mask "yzyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzyw = 0xD9; + + /// Shuffle mask "yzzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzzx = 0x29; + + /// Shuffle mask "yzzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzzy = 0x69; + + /// Shuffle mask "yzzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzzz = 0xA9; + + /// Shuffle mask "yzzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzzw = 0xE9; + + /// Shuffle mask "yzwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzwx = 0x39; + + /// Shuffle mask "yzwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzwy = 0x79; + + /// Shuffle mask "yzwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzwz = 0xB9; + + /// Shuffle mask "yzww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int yzww = 0xF9; + + /// Shuffle mask "ywxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywxx = 0x0D; + + /// Shuffle mask "ywxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywxy = 0x4D; + + /// Shuffle mask "ywxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywxz = 0x8D; + + /// Shuffle mask "ywxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywxw = 0xCD; + + /// Shuffle mask "ywyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywyx = 0x1D; + + /// Shuffle mask "ywyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywyy = 0x5D; + + /// Shuffle mask "ywyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywyz = 0x9D; + + /// Shuffle mask "ywyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywyw = 0xDD; + + /// Shuffle mask "ywzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywzx = 0x2D; + + /// Shuffle mask "ywzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywzy = 0x6D; + + /// Shuffle mask "ywzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywzz = 0xAD; + + /// Shuffle mask "ywzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywzw = 0xED; + + /// Shuffle mask "ywwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywwx = 0x3D; + + /// Shuffle mask "ywwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywwy = 0x7D; + + /// Shuffle mask "ywwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywwz = 0xBD; + + /// Shuffle mask "ywww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int ywww = 0xFD; + + /// Shuffle mask "zxxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxxx = 0x02; + + /// Shuffle mask "zxxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxxy = 0x42; + + /// Shuffle mask "zxxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxxz = 0x82; + + /// Shuffle mask "zxxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxxw = 0xC2; + + /// Shuffle mask "zxyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxyx = 0x12; + + /// Shuffle mask "zxyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxyy = 0x52; + + /// Shuffle mask "zxyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxyz = 0x92; + + /// Shuffle mask "zxyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxyw = 0xD2; + + /// Shuffle mask "zxzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxzx = 0x22; + + /// Shuffle mask "zxzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxzy = 0x62; + + /// Shuffle mask "zxzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxzz = 0xA2; + + /// Shuffle mask "zxzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxzw = 0xE2; + + /// Shuffle mask "zxwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxwx = 0x32; + + /// Shuffle mask "zxwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxwy = 0x72; + + /// Shuffle mask "zxwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxwz = 0xB2; + + /// Shuffle mask "zxww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zxww = 0xF2; + + /// Shuffle mask "zyxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyxx = 0x06; + + /// Shuffle mask "zyxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyxy = 0x46; + + /// Shuffle mask "zyxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyxz = 0x86; + + /// Shuffle mask "zyxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyxw = 0xC6; + + /// Shuffle mask "zyyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyyx = 0x16; + + /// Shuffle mask "zyyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyyy = 0x56; + + /// Shuffle mask "zyyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyyz = 0x96; + + /// Shuffle mask "zyyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyyw = 0xD6; + + /// Shuffle mask "zyzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyzx = 0x26; + + /// Shuffle mask "zyzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyzy = 0x66; + + /// Shuffle mask "zyzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyzz = 0xA6; + + /// Shuffle mask "zyzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyzw = 0xE6; + + /// Shuffle mask "zywx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zywx = 0x36; + + /// Shuffle mask "zywy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zywy = 0x76; + + /// Shuffle mask "zywz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zywz = 0xB6; + + /// Shuffle mask "zyww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zyww = 0xF6; + + /// Shuffle mask "zzxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzxx = 0x0A; + + /// Shuffle mask "zzxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzxy = 0x4A; + + /// Shuffle mask "zzxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzxz = 0x8A; + + /// Shuffle mask "zzxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzxw = 0xCA; + + /// Shuffle mask "zzyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzyx = 0x1A; + + /// Shuffle mask "zzyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzyy = 0x5A; + + /// Shuffle mask "zzyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzyz = 0x9A; + + /// Shuffle mask "zzyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzyw = 0xDA; + + /// Shuffle mask "zzzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzzx = 0x2A; + + /// Shuffle mask "zzzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzzy = 0x6A; + + /// Shuffle mask "zzzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzzz = 0xAA; + + /// Shuffle mask "zzzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzzw = 0xEA; + + /// Shuffle mask "zzwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzwx = 0x3A; + + /// Shuffle mask "zzwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzwy = 0x7A; + + /// Shuffle mask "zzwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzwz = 0xBA; + + /// Shuffle mask "zzww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zzww = 0xFA; + + /// Shuffle mask "zwxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwxx = 0x0E; + + /// Shuffle mask "zwxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwxy = 0x4E; + + /// Shuffle mask "zwxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwxz = 0x8E; + + /// Shuffle mask "zwxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwxw = 0xCE; + + /// Shuffle mask "zwyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwyx = 0x1E; + + /// Shuffle mask "zwyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwyy = 0x5E; + + /// Shuffle mask "zwyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwyz = 0x9E; + + /// Shuffle mask "zwyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwyw = 0xDE; + + /// Shuffle mask "zwzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwzx = 0x2E; + + /// Shuffle mask "zwzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwzy = 0x6E; + + /// Shuffle mask "zwzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwzz = 0xAE; + + /// Shuffle mask "zwzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwzw = 0xEE; + + /// Shuffle mask "zwwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwwx = 0x3E; + + /// Shuffle mask "zwwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwwy = 0x7E; + + /// Shuffle mask "zwwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwwz = 0xBE; + + /// Shuffle mask "zwww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int zwww = 0xFE; + + /// Shuffle mask "wxxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxxx = 0x03; + + /// Shuffle mask "wxxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxxy = 0x43; + + /// Shuffle mask "wxxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxxz = 0x83; + + /// Shuffle mask "wxxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxxw = 0xC3; + + /// Shuffle mask "wxyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxyx = 0x13; + + /// Shuffle mask "wxyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxyy = 0x53; + + /// Shuffle mask "wxyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxyz = 0x93; + + /// Shuffle mask "wxyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxyw = 0xD3; + + /// Shuffle mask "wxzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxzx = 0x23; + + /// Shuffle mask "wxzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxzy = 0x63; + + /// Shuffle mask "wxzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxzz = 0xA3; + + /// Shuffle mask "wxzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxzw = 0xE3; + + /// Shuffle mask "wxwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxwx = 0x33; + + /// Shuffle mask "wxwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxwy = 0x73; + + /// Shuffle mask "wxwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxwz = 0xB3; + + /// Shuffle mask "wxww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wxww = 0xF3; + + /// Shuffle mask "wyxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyxx = 0x07; + + /// Shuffle mask "wyxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyxy = 0x47; + + /// Shuffle mask "wyxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyxz = 0x87; + + /// Shuffle mask "wyxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyxw = 0xC7; + + /// Shuffle mask "wyyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyyx = 0x17; + + /// Shuffle mask "wyyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyyy = 0x57; + + /// Shuffle mask "wyyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyyz = 0x97; + + /// Shuffle mask "wyyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyyw = 0xD7; + + /// Shuffle mask "wyzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyzx = 0x27; + + /// Shuffle mask "wyzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyzy = 0x67; + + /// Shuffle mask "wyzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyzz = 0xA7; + + /// Shuffle mask "wyzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyzw = 0xE7; + + /// Shuffle mask "wywx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wywx = 0x37; + + /// Shuffle mask "wywy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wywy = 0x77; + + /// Shuffle mask "wywz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wywz = 0xB7; + + /// Shuffle mask "wyww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wyww = 0xF7; + + /// Shuffle mask "wzxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzxx = 0x0B; + + /// Shuffle mask "wzxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzxy = 0x4B; + + /// Shuffle mask "wzxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzxz = 0x8B; + + /// Shuffle mask "wzxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzxw = 0xCB; + + /// Shuffle mask "wzyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzyx = 0x1B; + + /// Shuffle mask "wzyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzyy = 0x5B; + + /// Shuffle mask "wzyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzyz = 0x9B; + + /// Shuffle mask "wzyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzyw = 0xDB; + + /// Shuffle mask "wzzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzzx = 0x2B; + + /// Shuffle mask "wzzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzzy = 0x6B; + + /// Shuffle mask "wzzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzzz = 0xAB; + + /// Shuffle mask "wzzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzzw = 0xEB; + + /// Shuffle mask "wzwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzwx = 0x3B; + + /// Shuffle mask "wzwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzwy = 0x7B; + + /// Shuffle mask "wzwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzwz = 0xBB; + + /// Shuffle mask "wzww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wzww = 0xFB; + + /// Shuffle mask "wwxx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwxx = 0x0F; + + /// Shuffle mask "wwxy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwxy = 0x4F; + + /// Shuffle mask "wwxz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwxz = 0x8F; + + /// Shuffle mask "wwxw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwxw = 0xCF; + + /// Shuffle mask "wwyx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwyx = 0x1F; + + /// Shuffle mask "wwyy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwyy = 0x5F; + + /// Shuffle mask "wwyz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwyz = 0x9F; + + /// Shuffle mask "wwyw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwyw = 0xDF; + + /// Shuffle mask "wwzx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwzx = 0x2F; + + /// Shuffle mask "wwzy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwzy = 0x6F; + + /// Shuffle mask "wwzz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwzz = 0xAF; + + /// Shuffle mask "wwzw". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwzw = 0xEF; + + /// Shuffle mask "wwwx". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwwx = 0x3F; + + /// Shuffle mask "wwwy". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwwy = 0x7F; + + /// Shuffle mask "wwwz". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwwz = 0xBF; + + /// Shuffle mask "wwww". + /// + /// Used by [shuffle] and [shuffleMix]. static const int wwww = 0xFF; - /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. + /// Shuffle the lane values based on the [mask]. + /// + /// The [mask] must be one of the 256 shuffle masks from [xxxx] to [wwww]. + /// + /// Creates a new [Float32x4] whose lane values are taken from the + /// lanes of this value based on the lanes of the shuffle mask, + /// with the result's [x] lane being taken from the lane of the first + /// letter of the shuffle mask's name, the [y] lane from the second letter, + /// [z] lane from the third letter and [w] lane from the fourth letter. + /// + /// For example, the shuffle mask [wxyz] creates a new `Float32x4` + /// whose [x] lane is the [w] lane of this value, because the first letter + /// of the shuffle mask's name, `wxyz` is "w". Then the `y`, `z` and `w` + /// lanes of the result are the values of the `x`, `y` and `z` lanes + /// of this value. + /// + /// The [xyzw] "identity shuffle" mask gives a result with the same lanes + /// as the original. + /// + /// Some masks preserve the values of all lanes, but may permute them. + /// Other masks duplicates some lanes and discards the values of others. + /// + /// For example, doing `v1.shuffle(yyyy)` is equivalent to + /// `Float32x4.splat(v1.y)`. Float32x4 shuffle(int mask); - /// Shuffle the lane values in this [Float32x4] and [other]. The returned - /// Float32x4 will have XY lanes from this [Float32x4] and ZW lanes from - /// [other]. Uses the same [mask] as [shuffle]. + /// Mixes lanes chosen from two [Float32x4] values using a [mask]. + /// + /// Creates a new [Float32x4] where the [x] and [y] lanes are chosen + /// from the lanes of this value selected by the first two letters of the + /// [mask]'s name, and the [z] and [w] lanes are the lanes of [other] + /// selected by the last two letters of the `mask`'s name. + /// + /// For example, `v1.shuffleMix(v2, Float32x4.xyzw)` is equivalent + /// to `Float32x4(v1.x, v1.y, v2.z, v2.w)`. + /// + /// If [other] is the same value as this `Float32x4`, this function + /// is the same as [shuffle]. That is, doing + /// `v1.shuffleMix(v1, mask)` is equivalent to `v1.shuffle(mask)`. Float32x4 shuffleMix(Float32x4 other, int mask); - /// Returns a new [Float32x4] copied from this [Float32x4] with a new x - /// value. + /// This value, but with the value of the [Float32x4.x] lane set to [x]. + /// + /// Returns a new [Float32x4] with the same values for the [y], [z] + /// and [w] lanes as this value, and with a [Float32x4.x] lane + /// having the value [x] converted to a 32-bit floating point number. Float32x4 withX(double x); - /// Returns a new [Float32x4] copied from this [Float32x4] with a new y - /// value. + /// This value, but with the value of the [Float32x4.y] lane set to [y]. + /// + /// Returns a new [Float32x4] with the same values for the [x], [z] + /// and [w] lanes as this value, and with a [Float32x4.y] lane + /// having the value [y] converted to a 32-bit floating point number. Float32x4 withY(double y); - /// Returns a new [Float32x4] copied from this [Float32x4] with a new z - /// value. + /// This value, but with the value of the [Float32x4.z] lane set to [z]. + /// + /// Returns a new [Float32x4] with the same values for the [x], [y] + /// and [w] lanes as this value, and with a [Float32x4.z] lane + /// having the value [z] converted to a 32-bit floating point number. Float32x4 withZ(double z); - /// Returns a new [Float32x4] copied from this [Float32x4] with a new w - /// value. + /// This value, but with the value of the [Float32x4.w] lane set to [w]. + /// + /// Returns a new [Float32x4] with the same values for the [x], [y] + /// and [z] lanes as this value, and with a [Float32x4.w] lane + /// having the value [w] converted to a 32-bit floating point number. Float32x4 withW(double w); - /// The lane-wise minimum value in this [Float32x4] or [other]. + /// Lane-wise minimum. + /// + /// For each lane select the lesser of the lane value of this and [other]. + /// + /// The result is the lesser of the two lane values if either is lesser. + /// The result is unspecified if either lane contains a NaN value or + /// if the values are -0.0 and 0.0, so that neither value is smaller + /// or greater than the other. + /// Different platforms may give different results in those cases, + /// but always one of the lane values. + /// + /// Returns the result for each lane. Float32x4 min(Float32x4 other); - /// The lane-wise maximum value in this [Float32x4] or [other]. + /// Lane-wise maximum. + /// + /// For each lane select the greater of the lane value of this and [other]. + /// + /// The result is the greater of the two lane values if either is greater. + /// The result is unspecified if either lane contains a NaN value or + /// if the values are -0.0 and 0.0, so that neither value is smaller + /// or greater than the other. + /// Different platforms may give different results in those cases, + /// but always one of the lane values. + /// + /// Returns the result for each lane. Float32x4 max(Float32x4 other); - /// The square root of this [Float32x4]. + /// Lane-wise square root. + /// + /// For each lane compute the 32-bit floating point square root of the + /// lane's value. + /// + /// The result for a lane is a NaN value if the original value + /// is less than zero or if it is a NaN value. + /// The result for a negative zero, -0.0, is the same value again. + /// The result for positive infinity is positive infinity. + /// Otherwise the result is a positive value which approximates + /// the mathematical square root of the original value. + /// + /// Returns the result for each lane. Float32x4 sqrt(); - /// The reciprocal of this [Float32x4]. + /// Lane-wise reciprocal. + /// + /// For each lane compute the result of dividing 1.0 by the lane's value. + /// + /// If the value is a NaN value, so is the result. + /// If the value is infinite, the result is a zero value with the same sign. + /// If the value is zero, the result is infinite with the same sign. + /// Otherwise the result is an approximation of the mathematical result + /// of dividing 1 by the (finite, non-zero) value of the lane. + /// + /// Returns the result for each lane. Float32x4 reciprocal(); - /// The square root of the reciprocal of this [Float32x4]. + /// Lane-wise approximation of reciprocal square root. + /// + /// Approximates the same result as [reciprocal] followed by [sqrt], + /// or [sqrt] followed by [reciprocal], + /// but may be more precise and/or efficient due to computing the result + /// directly, rather than not creating a an intermediate result, + /// and possibly by working entirely at a reduced precision. + /// + /// The result can differ between platforms due to differences in + /// approximation and precision, and for values where the order of [sqrt] and + /// [reciprocal] makes a difference. + /// The latter applies specifically to `-0.0` + /// where `sqrt(-0.0)` is defined to be -0.0, + /// and `reciprocal` of that is -Infinity. + /// In the opposite order it computes `sqrt` of -Infinity which is NaN. Float32x4 reciprocalSqrt(); } diff --git a/tests/lib/typed_data/float32x4_test.dart b/tests/lib/typed_data/float32x4_test.dart index 80600ff316b..bd1b1ef1f1e 100644 --- a/tests/lib/typed_data/float32x4_test.dart +++ b/tests/lib/typed_data/float32x4_test.dart @@ -1,511 +1,646 @@ // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. + // VMOptions=--max_deoptimization_counter_threshold=1000 --optimization-counter-threshold=10 --no-background-compilation // VMOptions=--no-intrinsify -// Requirements=nnbd-strong - -// Library tag to be able to run in html test framework. -library float32x4_test; - import 'dart:typed_data'; import "package:expect/expect.dart"; -testAdd() { - var m = new Float32x4(-1.0, -2.0, -3.0, -4.0); - var n = new Float32x4(1.0, 2.0, 3.0, 4.0); +const nan = double.nan; +const inf = double.infinity; + +/// Minimal positive 32-bit float value. +const min = 1.401298464324817e-45; + +/// Maximal finite 32-bit float value. +const max = 3.4028234663852886e+38; + +void testAdd() { + var m = Float32x4(-1.0, -2.0, -3.0, -4.0); + var n = Float32x4(1.0, 2.0, 3.0, 4.0); var o = m + n; - Expect.equals(0.0, o.x); - Expect.equals(0.0, o.y); - Expect.equals(0.0, o.z); - Expect.equals(0.0, o.w); + checkEquals(0.0, o.x); + checkEquals(0.0, o.y); + checkEquals(0.0, o.z); + checkEquals(0.0, o.w); + + var p = Float32x4(-0.0, inf, max, nan); + var q = Float32x4(-0.0, -inf, max, 3.14); + var r = p + q; + checkEquals(-0.0, r.x); + checkEquals(nan, r.y); + checkEquals(inf, r.z); + checkEquals(nan, r.w); } -testNegate() { - var m = new Float32x4(1.0, 2.0, -3.0, -4.0); +void testNegate() { + var m = Float32x4(1.0, 2.0, -3.0, -4.0); m = -m; - Expect.equals(-1.0, m.x); - Expect.equals(-2.0, m.y); - Expect.equals(3.0, m.z); - Expect.equals(4.0, m.w); + checkEquals(-1.0, m.x); + checkEquals(-2.0, m.y); + checkEquals(3.0, m.z); + checkEquals(4.0, m.w); + + var n = Float32x4(0.0, -0.0, inf, nan); + n = -n; + checkEquals(-0.0, n.x); + checkEquals(0.0, n.y); + checkEquals(-inf, n.z); + checkEquals(nan, n.w); } -testSub() { - var m = new Float32x4(-1.0, -2.0, -3.0, -4.0); - var n = new Float32x4(1.0, 2.0, 3.0, 4.0); +void testSub() { + var m = Float32x4(-1.0, -2.0, -3.0, -4.0); + var n = Float32x4(1.0, 2.0, 3.0, 4.0); var o = m - n; - Expect.equals(-2.0, o.x); - Expect.equals(-4.0, o.y); - Expect.equals(-6.0, o.z); - Expect.equals(-8.0, o.w); + checkEquals(-2.0, o.x); + checkEquals(-4.0, o.y); + checkEquals(-6.0, o.z); + checkEquals(-8.0, o.w); + + var p = Float32x4(-0.0, inf, max, nan); + var q = Float32x4(0.0, inf, -max, 3.14); + var r = p - q; + checkEquals(-0.0, r.x); + checkEquals(nan, r.y); + checkEquals(inf, r.z); + checkEquals(nan, r.w); } -testMul() { - var m = new Float32x4(-1.0, -2.0, -3.0, -4.0); - var n = new Float32x4(1.0, 2.0, 3.0, 4.0); +void testMul() { + var m = Float32x4(-1.0, -2.0, -3.0, -4.0); + var n = Float32x4(1.0, 2.0, 3.0, 4.0); var o = m * n; - Expect.equals(-1.0, o.x); - Expect.equals(-4.0, o.y); - Expect.equals(-9.0, o.z); - Expect.equals(-16.0, o.w); + checkEquals(-1.0, o.x); + checkEquals(-4.0, o.y); + checkEquals(-9.0, o.z); + checkEquals(-16.0, o.w); + + var p = Float32x4(-0.0, inf, max, nan); + var q = Float32x4(0.0, 0.0, 2.0, 3.14); + var r = p * q; + checkEquals(-0.0, r.x); + checkEquals(nan, r.y); + checkEquals(inf, r.z); + checkEquals(nan, r.w); } -testDiv() { - var m = new Float32x4(-1.0, -2.0, -3.0, -4.0); - var n = new Float32x4(1.0, 2.0, 3.0, 4.0); +void testDiv() { + var m = Float32x4(-1.0, -2.0, -3.0, -4.0); + var n = Float32x4(1.0, 2.0, 3.0, 4.0); var o = m / n; - Expect.equals(-1.0, o.x); - Expect.equals(-1.0, o.y); - Expect.equals(-1.0, o.z); - Expect.equals(-1.0, o.w); + checkEquals(-1.0, o.x); + checkEquals(-1.0, o.y); + checkEquals(-1.0, o.z); + checkEquals(-1.0, o.w); + + var p = Float32x4(0.0, inf, max, nan); + var q = Float32x4(-1.0, inf, 0.5, 3.14); + var r = p / q; + checkEquals(-0.0, r.x); + checkEquals(nan, r.y); + checkEquals(inf, r.z); + checkEquals(nan, r.w); } -testComparison() { - var m = new Float32x4(1.0, 2.0, 0.1, 0.001); - var n = new Float32x4(2.0, 2.0, 0.001, 0.1); +void testComparison() { + var m = Float32x4(1.0, 2.0, 0.1, 0.001); + var n = Float32x4(2.0, 2.0, 0.001, 0.1); var cmp; cmp = m.lessThan(n); Expect.equals(-1, cmp.x); - Expect.equals(0x0, cmp.y); - Expect.equals(0x0, cmp.z); + Expect.equals(0, cmp.y); + Expect.equals(0, cmp.z); Expect.equals(-1, cmp.w); cmp = m.lessThanOrEqual(n); Expect.equals(-1, cmp.x); Expect.equals(-1, cmp.y); - Expect.equals(0x0, cmp.z); + Expect.equals(0, cmp.z); Expect.equals(-1, cmp.w); cmp = m.equal(n); - Expect.equals(0x0, cmp.x); + Expect.equals(0, cmp.x); Expect.equals(-1, cmp.y); - Expect.equals(0x0, cmp.z); - Expect.equals(0x0, cmp.w); + Expect.equals(0, cmp.z); + Expect.equals(0, cmp.w); cmp = m.notEqual(n); Expect.equals(-1, cmp.x); - Expect.equals(0x0, cmp.y); + Expect.equals(0, cmp.y); Expect.equals(-1, cmp.z); Expect.equals(-1, cmp.w); cmp = m.greaterThanOrEqual(n); - Expect.equals(0x0, cmp.x); + Expect.equals(0, cmp.x); Expect.equals(-1, cmp.y); Expect.equals(-1, cmp.z); - Expect.equals(0x0, cmp.w); + Expect.equals(0, cmp.w); cmp = m.greaterThan(n); - Expect.equals(0x0, cmp.x); - Expect.equals(0x0, cmp.y); + Expect.equals(0, cmp.x); + Expect.equals(0, cmp.y); Expect.equals(-1, cmp.z); - Expect.equals(0x0, cmp.w); + Expect.equals(0, cmp.w); + + var p = Float32x4(0.0, nan, min, nan); + var q = Float32x4(-0.0, nan, 0.0, 3.14); + + cmp = p.lessThan(q); + Expect.equals(0, cmp.x); + Expect.equals(0, cmp.y); + Expect.equals(0, cmp.z); + Expect.equals(0, cmp.w); + + cmp = p.lessThanOrEqual(q); + Expect.equals(-1, cmp.x); + Expect.equals(0, cmp.y); + Expect.equals(0, cmp.z); + Expect.equals(0, cmp.w); + + cmp = p.equal(q); + Expect.equals(-1, cmp.x); + Expect.equals(0, cmp.y); + Expect.equals(0, cmp.z); + Expect.equals(0, cmp.w); + + cmp = p.notEqual(q); + Expect.equals(0, cmp.x); + Expect.equals(-1, cmp.y); + Expect.equals(-1, cmp.z); + Expect.equals(-1, cmp.w); + + cmp = p.greaterThanOrEqual(q); + Expect.equals(-1, cmp.x); + Expect.equals(0, cmp.y); + Expect.equals(-1, cmp.z); + Expect.equals(0, cmp.w); + + cmp = p.greaterThan(q); + Expect.equals(0, cmp.x); + Expect.equals(0, cmp.y); + Expect.equals(-1, cmp.z); + Expect.equals(0, cmp.w); } -testAbs() { - var m = new Float32x4(1.0, -2.0, 3.0, -4.0); +void testAbs() { + var m = Float32x4(1.0, -2.0, 3.0, -4.0); m = m.abs(); - Expect.equals(1.0, m.x); - Expect.equals(2.0, m.y); - Expect.equals(3.0, m.z); - Expect.equals(4.0, m.w); + checkEquals(1.0, m.x); + checkEquals(2.0, m.y); + checkEquals(3.0, m.z); + checkEquals(4.0, m.w); + + var n = Float32x4(-0.0, 0.0, -inf, nan); + n = n.abs(); + checkEquals(0.0, n.x); + checkEquals(0.0, n.y); + checkEquals(inf, n.z); + checkEquals(nan, n.w); } -testScale() { - var m = new Float32x4(1.0, -2.0, 3.0, -4.0); +void testScale() { + var m = Float32x4(1.0, -2.0, 3.0, -4.0); m = m.scale(20.0); - Expect.equals(20.0, m.x); - Expect.equals(-40.0, m.y); - Expect.equals(60.0, m.z); - Expect.equals(-80.0, m.w); + checkEquals(20.0, m.x); + checkEquals(-40.0, m.y); + checkEquals(60.0, m.z); + checkEquals(-80.0, m.w); + + var n = Float32x4(0.0, max, min, nan); + var o = n.scale(-2.0); + checkEquals(-0.0, o.x); + checkEquals(-inf, o.y); + checkEquals(-min * 2.0, o.z); + checkEquals(nan, o.w); + o = n.scale(-0.5); + checkEquals(-0.0, o.x); + checkEquals(-max / 2.0, o.y); + checkEquals(-0.0, o.z); + checkEquals(nan, o.w); + o = n.scale(nan); + checkEquals(nan, o.x); + checkEquals(nan, o.y); + checkEquals(nan, o.z); + checkEquals(nan, o.w); + o = n.scale(-0.0); + checkEquals(-0.0, o.x); + checkEquals(-0.0, o.y); + checkEquals(-0.0, o.z); + checkEquals(nan, o.w); } -testClamp() { - var m = new Float32x4(1.0, -2.0, 3.0, -4.0); - var lo = new Float32x4(0.0, 0.0, 0.0, 0.0); - var hi = new Float32x4(2.0, 2.0, 2.0, 2.0); +void testClamp() { + var m = Float32x4(1.0, -2.0, 3.0, -4.0); + var lo = Float32x4(0.0, 0.0, 0.0, 0.0); + var hi = Float32x4(2.0, 2.0, 2.0, 2.0); m = m.clamp(lo, hi); - Expect.equals(1.0, m.x); - Expect.equals(0.0, m.y); - Expect.equals(2.0, m.z); - Expect.equals(0.0, m.w); + checkEquals(1.0, m.x); + checkEquals(0.0, m.y); + checkEquals(2.0, m.z); + checkEquals(0.0, m.w); + + // No guarantees if one value is `nan` or max < min. + m = Float32x4(nan, 3.0, -3.0, -4.0); + lo = Float32x4(0.0, nan, 0.0, 2.0); + hi = Float32x4(2.0, 2.0, nan, 0.0); + var r = m.clamp(lo, hi); + checkOneOf([m.x, lo.x, hi.x], r.x); + checkOneOf([m.y, lo.y, hi.y], r.y); + checkOneOf([m.z, lo.z, hi.z], r.z); + checkOneOf([m.w, lo.w, hi.w], r.w); } -testShuffle() { - var m = new Float32x4(1.0, 2.0, 3.0, 4.0); +void testShuffle() { + var m = Float32x4(1.0, 2.0, 3.0, 4.0); var xxxx = m.shuffle(Float32x4.xxxx); - Expect.equals(1.0, xxxx.x); - Expect.equals(1.0, xxxx.y); - Expect.equals(1.0, xxxx.z); - Expect.equals(1.0, xxxx.w); + checkEquals(m.x, xxxx.x); + checkEquals(m.x, xxxx.y); + checkEquals(m.x, xxxx.z); + checkEquals(m.x, xxxx.w); var yyyy = m.shuffle(Float32x4.yyyy); - Expect.equals(2.0, yyyy.x); - Expect.equals(2.0, yyyy.y); - Expect.equals(2.0, yyyy.z); - Expect.equals(2.0, yyyy.w); + checkEquals(m.y, yyyy.x); + checkEquals(m.y, yyyy.y); + checkEquals(m.y, yyyy.z); + checkEquals(m.y, yyyy.w); var zzzz = m.shuffle(Float32x4.zzzz); - Expect.equals(3.0, zzzz.x); - Expect.equals(3.0, zzzz.y); - Expect.equals(3.0, zzzz.z); - Expect.equals(3.0, zzzz.w); + checkEquals(m.z, zzzz.x); + checkEquals(m.z, zzzz.y); + checkEquals(m.z, zzzz.z); + checkEquals(m.z, zzzz.w); var wwww = m.shuffle(Float32x4.wwww); - Expect.equals(4.0, wwww.x); - Expect.equals(4.0, wwww.y); - Expect.equals(4.0, wwww.z); - Expect.equals(4.0, wwww.w); + checkEquals(m.w, wwww.x); + checkEquals(m.w, wwww.y); + checkEquals(m.w, wwww.z); + checkEquals(m.w, wwww.w); var wzyx = m.shuffle(Float32x4.wzyx); - Expect.equals(4.0, wzyx.x); - Expect.equals(3.0, wzyx.y); - Expect.equals(2.0, wzyx.z); - Expect.equals(1.0, wzyx.w); + checkEquals(m.w, wzyx.x); + checkEquals(m.z, wzyx.y); + checkEquals(m.y, wzyx.z); + checkEquals(m.x, wzyx.w); var wwzz = m.shuffle(Float32x4.wwzz); - Expect.equals(4.0, wwzz.x); - Expect.equals(4.0, wwzz.y); - Expect.equals(3.0, wwzz.z); - Expect.equals(3.0, wwzz.w); + checkEquals(m.w, wwzz.x); + checkEquals(m.w, wwzz.y); + checkEquals(m.z, wwzz.z); + checkEquals(m.z, wwzz.w); var xxyy = m.shuffle(Float32x4.xxyy); - Expect.equals(1.0, xxyy.x); - Expect.equals(1.0, xxyy.y); - Expect.equals(2.0, xxyy.z); - Expect.equals(2.0, xxyy.w); + checkEquals(m.x, xxyy.x); + checkEquals(m.x, xxyy.y); + checkEquals(m.y, xxyy.z); + checkEquals(m.y, xxyy.w); var yyww = m.shuffle(Float32x4.yyww); - Expect.equals(2.0, yyww.x); - Expect.equals(2.0, yyww.y); - Expect.equals(4.0, yyww.z); - Expect.equals(4.0, yyww.w); + checkEquals(m.y, yyww.x); + checkEquals(m.y, yyww.y); + checkEquals(m.w, yyww.z); + checkEquals(m.w, yyww.w); + + double getLane(Float32x4 lanes, int lane) => switch (lane) { + 0 => lanes.x, + 1 => lanes.y, + 2 => lanes.z, + 3 => lanes.w, + _ => throw UnsupportedError("Test failure, wrong lane number: $lane"), + }; + for (var i = 0; i < 256; i++) { + var shuffled = m.shuffle(i); + checkEquals(getLane(m, i & 3), shuffled.x); + checkEquals(getLane(m, (i >> 2) & 3), shuffled.y); + checkEquals(getLane(m, (i >> 4) & 3), shuffled.z); + checkEquals(getLane(m, (i >> 6) & 3), shuffled.w); + } } -testMin() { - var m = new Float32x4(1.0, 2.0, 3.0, 4.0); - var n = new Float32x4(1.0, 0.0, 2.5, 5.0); +void testMin() { + var m = Float32x4(1.0, 2.0, 3.0, 4.0); + var n = Float32x4(1.0, 0.0, 2.5, 5.0); m = m.min(n); - Expect.equals(1.0, m.x); - Expect.equals(0.0, m.y); - Expect.equals(2.5, m.z); - Expect.equals(4.0, m.w); + checkEquals(1.0, m.x); + checkEquals(0.0, m.y); + checkEquals(2.5, m.z); + checkEquals(4.0, m.w); + + var p = Float32x4(-0.0, -inf, -0.0, nan); + var q = Float32x4(0.0, -max, -min, 3.5); + var r = p.min(q); + checkOneOf([-0.0, 0.0], r.x); + checkEquals(-inf, r.y); + checkEquals(-min, r.z); + checkOneOf([nan, 3.5], r.w); + + r = q.min(p); + checkOneOf([-0.0, 0.0], r.x); + checkEquals(-inf, r.y); + checkEquals(-min, r.z); + checkOneOf([nan, 3.5], r.w); } -testMax() { - var m = new Float32x4(1.0, 2.0, 3.0, 4.0); - var n = new Float32x4(1.0, 0.0, 2.5, 5.0); +void testMax() { + var m = Float32x4(1.0, 2.0, 3.0, 4.0); + var n = Float32x4(1.0, 0.0, 2.5, 5.0); m = m.max(n); - Expect.equals(1.0, m.x); - Expect.equals(2.0, m.y); - Expect.equals(3.0, m.z); - Expect.equals(5.0, m.w); + checkEquals(1.0, m.x); + checkEquals(2.0, m.y); + checkEquals(3.0, m.z); + checkEquals(5.0, m.w); + + var p = Float32x4(-0.0, -inf, -0.0, nan); + var q = Float32x4(0.0, -max, -min, 3.5); + var r = p.max(q); + checkOneOf([-0.0, 0.0], r.x); + checkEquals(-max, r.y); + checkEquals(-0.0, r.z); + checkOneOf([nan, 3.5], r.w); + + r = q.max(p); + checkOneOf([-0.0, 0.0], r.x); + checkEquals(-max, r.y); + checkEquals(-0.0, r.z); + checkOneOf([nan, 3.5], r.w); } -testSqrt() { - var m = new Float32x4(1.0, 4.0, 9.0, 16.0); +void testSqrt() { + var m = Float32x4(1.0, 4.0, 9.0, 16.0); m = m.sqrt(); - Expect.equals(1.0, m.x); - Expect.equals(2.0, m.y); - Expect.equals(3.0, m.z); - Expect.equals(4.0, m.w); + checkEquals(1.0, m.x); + checkEquals(2.0, m.y); + checkEquals(3.0, m.z); + checkEquals(4.0, m.w); + + m = Float32x4(0.0, -4.0, inf, nan); + m = m.sqrt(); + checkEquals(0.0, m.x); + checkEquals(nan, m.y); + checkEquals(inf, m.z); + checkEquals(nan, m.w); + + m = Float32x4(-0.0, -inf, 12224, 12223.999023); + m = m.sqrt(); + checkEquals(-0.0, m.x); + checkEquals(nan, m.y); + Expect.approxEquals(110.56220245361328, m.z, 0.0001); + Expect.approxEquals(110.5621566772461, m.w, 0.0001); } -testReciprocal() { - var m = new Float32x4(1.0, 4.0, 9.0, 16.0); +void testReciprocal() { + var m = Float32x4(1.0, 4.0, 9.0, 16.0); m = m.reciprocal(); Expect.approxEquals(1.0, m.x, 0.001); Expect.approxEquals(0.25, m.y, 0.001); Expect.approxEquals(0.1111111, m.z, 0.001); Expect.approxEquals(0.0625, m.w, 0.001); + + m = Float32x4(0.0, -0.0, inf, nan); + m = m.reciprocal(); + checkEquals(inf, m.x); + checkEquals(-inf, m.y); + checkEquals(0, m.z); + checkEquals(nan, m.w); } -testReciprocalSqrt() { - var m = new Float32x4(1.0, 0.25, 0.111111, 0.0625); - m = m.reciprocalSqrt(); - Expect.approxEquals(1.0, m.x, 0.001); - Expect.approxEquals(2.0, m.y, 0.001); - Expect.approxEquals(3.0, m.z, 0.001); - Expect.approxEquals(4.0, m.w, 0.001); +void testReciprocalSqrt() { + var m = Float32x4(1.0, 0.25, 0.111111, 0.0625); + var n = m.reciprocalSqrt(); + Expect.approxEquals(1.0, n.x, 0.001); + Expect.approxEquals(2.0, n.y, 0.001); + Expect.approxEquals(3.0, n.z, 0.001); + Expect.approxEquals(4.0, n.w, 0.001); + + var o = m.reciprocal().sqrt(); + Expect.approxEquals(o.x, n.x, 0.001); + Expect.approxEquals(o.y, n.y, 0.001); + Expect.approxEquals(o.z, n.z, 0.001); + Expect.approxEquals(o.w, n.w, 0.001); + + m = Float32x4(0.0, -0.0, inf, nan); + n = m.reciprocalSqrt(); + checkEquals(inf, n.x); + checkOneOf([nan, -inf], n.y); // One of 1/sqrt(-inf) or sqrt(1/-inf). + checkEquals(0, n.z); + checkEquals(nan, n.w); } -testSelect() { - var m = new Int32x4.bool(true, true, false, false); - var t = new Float32x4(1.0, 2.0, 3.0, 4.0); - var f = new Float32x4(5.0, 6.0, 7.0, 8.0); +void testSelect() { + // Technically on `Int32x4`, but only works on `Float32x4`s. + var m = Int32x4.bool(true, true, false, false); + var t = Float32x4(1.0, 2.0, 3.0, 4.0); + var f = Float32x4(5.0, 6.0, 7.0, 8.0); var s = m.select(t, f); - Expect.equals(1.0, s.x); - Expect.equals(2.0, s.y); - Expect.equals(7.0, s.z); - Expect.equals(8.0, s.w); + checkEquals(1.0, s.x); + checkEquals(2.0, s.y); + checkEquals(7.0, s.z); + checkEquals(8.0, s.w); } -testConversions() { - var m = new Int32x4(0x3F800000, 0x40000000, 0x40400000, 0x40800000); - var n = new Float32x4.fromInt32x4Bits(m); - Expect.equals(1.0, n.x); - Expect.equals(2.0, n.y); - Expect.equals(3.0, n.z); - Expect.equals(4.0, n.w); - n = new Float32x4(5.0, 6.0, 7.0, 8.0); - m = new Int32x4.fromFloat32x4Bits(n); - Expect.equals(0x40A00000, m.x); - Expect.equals(0x40C00000, m.y); - Expect.equals(0x40E00000, m.z); - Expect.equals(0x41000000, m.w); - // Flip sign using bit-wise operators. - n = new Float32x4(9.0, 10.0, 11.0, 12.0); - m = new Int32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000); - var nMask = new Int32x4.fromFloat32x4Bits(n); - nMask = nMask ^ m; // flip sign. - n = new Float32x4.fromInt32x4Bits(nMask); - Expect.equals(-9.0, n.x); - Expect.equals(-10.0, n.y); - Expect.equals(-11.0, n.z); - Expect.equals(-12.0, n.w); - nMask = new Int32x4.fromFloat32x4Bits(n); - nMask = nMask ^ m; // flip sign. - n = new Float32x4.fromInt32x4Bits(nMask); - Expect.equals(9.0, n.x); - Expect.equals(10.0, n.y); - Expect.equals(11.0, n.z); - Expect.equals(12.0, n.w); +void testConversions() { + var signMask = Int32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000); + + for (var (bits, float) in [ + // Simple values. + (0x3F800000, 1.0), + (0x40000000, 2.0), + (0x40400000, 3.0), + (0x40800000, 4.0), + // Special values. + (0x00000000, 0.0), + (0x80000000, -0.0), + (0x00000001, 1.401298464324817e-45), + (0x80000001, -1.401298464324817e-45), + (0x007FFFFF, 1.1754942106924411e-38), + (0x807FFFFF, -1.1754942106924411e-38), + (0x00800000, 1.1754943508222875e-38), + (0x80800000, -1.1754943508222875e-38), + (0x3F7FFFFF, 0.9999999403953552), + (0xBF7FFFFF, -0.9999999403953552), + (0x3F800000, 1.0), + (0xBF800000, -1.0), + (0x3F800001, 1.0000001192092896), + (0xBF800001, -1.0000001192092896), + (0x4AFFFFFF, 8388607.5), + (0xCAFFFFFF, -8388607.5), + (0x4B800000, 16777216.0), + (0xCB800000, -16777216.0), + (0x7F7FFFFF, 3.4028234663852886e+38), + (0xFF7FFFFF, -3.4028234663852886e+38), + (0x7F800000, inf), + (0xFF800000, -inf), + (0x7FC00000, nan), // Quiet NaN + (0xFFC00000, -nan), // Negative Quiet NaN. + (0x7F800001, nan), // Signaling NaN + (0x7F800001, -nan), // Signaling NaN + (0x3F7FFFFF, 0.9999999403953552), + (0xBF7FFFFF, -0.9999999403953552), + (0x4B000001, 8388609.0), + (0xCB000001, -8388609.0), + (0x4B7FFFFF, 16777215.0), + (0xCB7FFFFF, -16777215.0), + ]) { + var b = Int32x4(bits, bits, bits, bits); + var f = Float32x4.fromInt32x4Bits(b); + checkEquals(float, f.x); + checkEquals(float, f.y); + checkEquals(float, f.z); + checkEquals(float, f.w); + // Flip sign using bit mask. + bits ^= 0x80000000; + b = Int32x4(bits, bits, bits, bits); + f = Float32x4.fromInt32x4Bits(b); + checkEquals(-float, f.x); + checkEquals(-float, f.y); + checkEquals(-float, f.z); + checkEquals(-float, f.w); + } } -testBitOperators() { - var m = new Int32x4(0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA); - var n = new Int32x4(0x5555555, 0x5555555, 0x5555555, 0x5555555); - Expect.equals(0xAAAAAAA, m.x); - Expect.equals(0xAAAAAAA, m.y); - Expect.equals(0xAAAAAAA, m.z); - Expect.equals(0xAAAAAAA, m.w); - Expect.equals(0x5555555, n.x); - Expect.equals(0x5555555, n.y); - Expect.equals(0x5555555, n.z); - Expect.equals(0x5555555, n.w); - Expect.equals(true, n.flagX); - Expect.equals(true, n.flagY); - Expect.equals(true, n.flagZ); - Expect.equals(true, n.flagW); - var o = m | n; // or - Expect.equals(0xFFFFFFF, o.x); - Expect.equals(0xFFFFFFF, o.y); - Expect.equals(0xFFFFFFF, o.z); - Expect.equals(0xFFFFFFF, o.w); - Expect.equals(true, o.flagX); - Expect.equals(true, o.flagY); - Expect.equals(true, o.flagZ); - Expect.equals(true, o.flagW); - o = m & n; // and - Expect.equals(0x0, o.x); - Expect.equals(0x0, o.y); - Expect.equals(0x0, o.z); - Expect.equals(0x0, o.w); - n = n.withX(0xAAAAAAA); - n = n.withY(0xAAAAAAA); - n = n.withZ(0xAAAAAAA); - n = n.withW(0xAAAAAAA); - Expect.equals(0xAAAAAAA, n.x); - Expect.equals(0xAAAAAAA, n.y); - Expect.equals(0xAAAAAAA, n.z); - Expect.equals(0xAAAAAAA, n.w); - o = m ^ n; // xor - Expect.equals(0x0, o.x); - Expect.equals(0x0, o.y); - Expect.equals(0x0, o.z); - Expect.equals(0x0, o.w); - Expect.equals(false, o.flagX); - Expect.equals(false, o.flagY); - Expect.equals(false, o.flagZ); - Expect.equals(false, o.flagW); -} - -testSetters() { - var f = new Float32x4.zero(); - Expect.equals(0.0, f.x); - Expect.equals(0.0, f.y); - Expect.equals(0.0, f.z); - Expect.equals(0.0, f.w); +void testSetters() { + var f = Float32x4.zero(); + checkEquals(0.0, f.x); + checkEquals(0.0, f.y); + checkEquals(0.0, f.z); + checkEquals(0.0, f.w); f = f.withX(4.0); - Expect.equals(4.0, f.x); + checkEquals(4.0, f.x); f = f.withY(3.0); - Expect.equals(3.0, f.y); + checkEquals(3.0, f.y); f = f.withZ(2.0); - Expect.equals(2.0, f.z); + checkEquals(2.0, f.z); f = f.withW(1.0); - Expect.equals(1.0, f.w); - f = new Float32x4.zero(); + checkEquals(1.0, f.w); + f = Float32x4.zero(); f = f.withX(4.0).withZ(2.0).withW(1.0).withY(3.0); - Expect.equals(4.0, f.x); - Expect.equals(3.0, f.y); - Expect.equals(2.0, f.z); - Expect.equals(1.0, f.w); - var m = new Int32x4.bool(false, false, false, false); - Expect.equals(false, m.flagX); - Expect.equals(false, m.flagY); - Expect.equals(false, m.flagZ); - Expect.equals(false, m.flagW); - m = m.withFlagX(true); - Expect.equals(true, m.flagX); - Expect.equals(false, m.flagY); - Expect.equals(false, m.flagZ); - Expect.equals(false, m.flagW); - m = m.withFlagY(true); - Expect.equals(true, m.flagX); - Expect.equals(true, m.flagY); - Expect.equals(false, m.flagZ); - Expect.equals(false, m.flagW); - m = m.withFlagZ(true); - Expect.equals(true, m.flagX); - Expect.equals(true, m.flagY); - Expect.equals(true, m.flagZ); - Expect.equals(false, m.flagW); - m = m.withFlagW(true); - Expect.equals(true, m.flagX); - Expect.equals(true, m.flagY); - Expect.equals(true, m.flagZ); - Expect.equals(true, m.flagW); -} - -testGetters() { - var f = new Float32x4(1.0, 2.0, 3.0, 4.0); - Expect.equals(1.0, f.x); - Expect.equals(2.0, f.y); - Expect.equals(3.0, f.z); - Expect.equals(4.0, f.w); - var m = new Int32x4.bool(false, true, true, false); - Expect.equals(false, m.flagX); - Expect.equals(true, m.flagY); - Expect.equals(true, m.flagZ); - Expect.equals(false, m.flagW); + checkEquals(4.0, f.x); + checkEquals(3.0, f.y); + checkEquals(2.0, f.z); + checkEquals(1.0, f.w); } void testSplat() { - var f = new Float32x4.splat(2.0); - Expect.equals(2.0, f.x); - Expect.equals(2.0, f.y); - Expect.equals(2.0, f.z); - Expect.equals(2.0, f.w); + for (var v in [2.0, 0.0, -0.0, inf, -inf, nan, max, min]) { + var f = Float32x4.splat(v); + checkEquals(v, f.x); + checkEquals(v, f.y); + checkEquals(v, f.z); + checkEquals(v, f.w); + } } -void testZero() { - var f = new Float32x4.zero(); - Expect.equals(0.0, f.x); - Expect.equals(0.0, f.y); - Expect.equals(0.0, f.z); - Expect.equals(0.0, f.w); +void testZeroConstructor() { + var f = Float32x4.zero(); + checkEquals(0.0, f.x); + checkEquals(0.0, f.y); + checkEquals(0.0, f.z); + checkEquals(0.0, f.w); } -void testConstructor() { - var f = new Float32x4(1.0, 2.0, 3.0, 4.0); - Expect.equals(1.0, f.x); - Expect.equals(2.0, f.y); - Expect.equals(3.0, f.z); - Expect.equals(4.0, f.w); +void testConstructorAndGetters() { + var f = Float32x4(1.0, 2.0, 3.0, 4.0); + checkEquals(1.0, f.x); + checkEquals(2.0, f.y); + checkEquals(3.0, f.z); + checkEquals(4.0, f.w); } -// TODO(eernst): Come pure null-safety, this can only be `TypeError`. -bool isTypeError(e) => e is TypeError || e is ArgumentError; - void testBadArguments() { - dynamic dynamicNull = null; - Expect.throws(() => new Float32x4(dynamicNull, 2.0, 3.0, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, dynamicNull, 3.0, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, 2.0, dynamicNull, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, 2.0, 3.0, dynamicNull), isTypeError); + // Checks that non-double values are not accepted. + // The compiler should insert a dynamic downcast to `double` for each + // `dynamic`-typed argument. This test checks that no optimization gets + // in the way of that test. - // Use local variable typed as "dynamic" to avoid static warnings. - dynamic str = "foo"; - Expect.throws(() => new Float32x4(str, 2.0, 3.0, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, str, 3.0, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, 2.0, str, 4.0), isTypeError); - Expect.throws(() => new Float32x4(1.0, 2.0, 3.0, str), isTypeError); + dynamic dynamicValue = null; + Expect.throwsTypeError(() => Float32x4(dynamicValue, 2.0, 3.0, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, dynamicValue, 3.0, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, 2.0, dynamicValue, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, 2.0, 3.0, dynamicValue)); + + dynamicValue = "foo"; + Expect.throwsTypeError(() => Float32x4(dynamicValue, 2.0, 3.0, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, dynamicValue, 3.0, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, 2.0, dynamicValue, 4.0)); + Expect.throwsTypeError(() => Float32x4(1.0, 2.0, 3.0, dynamicValue)); } void testSpecialValues() { - /// Same as Expect.identical, but also works with NaNs and -0.0 for dart2js. - void checkEquals(expected, actual) { - if (expected.isNaN) { - Expect.isTrue(actual.isNaN); - } else if (expected == 0.0 && expected.isNegative) { - Expect.isTrue(actual == 0.0 && actual.isNegative); - } else { - Expect.equals(expected, actual); - } - } - + // Pairs of double values and (a double representation of) their closest + // 32-bit floating point value. + // The second value is what the first value is rounded to when converted + // to 32-bit float. var pairs = [ - [0.0, 0.0], - [5e-324, 0.0], - [2.225073858507201e-308, 0.0], - [2.2250738585072014e-308, 0.0], - [0.9999999999999999, 1.0], - [1.0, 1.0], - [1.0000000000000002, 1.0], - [4294967295.0, 4294967296.0], - [4294967296.0, 4294967296.0], - [4503599627370495.5, 4503599627370496.0], - [9007199254740992.0, 9007199254740992.0], - [1.7976931348623157e+308, double.infinity], - [0.49999999999999994, 0.5], - [4503599627370497.0, 4503599627370496.0], - [9007199254740991.0, 9007199254740992.0], - [double.infinity, double.infinity], - [double.nan, double.nan], + // Values that are precisely representable as float-32. + for (var f32 in [ + 0.0, + 1.0, + 1.401298464324817e-45, + 1.1754942106924411e-38, + 1.1754943508222875e-38, + 0.9999999403953552, + 1.0000001192092896, + 8388607.5, + 8388608.0, + 3.4028234663852886e+38, + 8388609.0, + 16777215.0, + 4294967296.0, + inf, + nan, + ]) + (f32, f32), + // Values that round when converted. + (5e-324, 0.0), + (2.225073858507201e-308, 0.0), + (2.2250738585072014e-308, 0.0), + (0.9999999999999999, 1.0), + (1.0000000000000002, 1.0), + (4294967295.0, 4294967296.0), + (4503599627370495.5, 4503599627370496.0), + (9007199254740992.0, 9007199254740992.0), + (1.7976931348623157e+308, inf), + (0.49999999999999994, 0.5), + (4503599627370497.0, 4503599627370496.0), + (9007199254740991.0, 9007199254740992.0), ]; - var conserved = [ - 1.401298464324817e-45, - 1.1754942106924411e-38, - 1.1754943508222875e-38, - 0.9999999403953552, - 1.0000001192092896, - 8388607.5, - 8388608.0, - 3.4028234663852886e+38, - 8388609.0, - 16777215.0, + var allTests = [ + ...pairs, + // Add negative variant of every pair. + for (var (d, f) in pairs) (-d, -f), ]; - var minusPairs = pairs.map((pair) { - return [-pair[0], -pair[1]]; - }); - var conservedPairs = conserved.map((value) => [value, value]); - - var allTests = [pairs, minusPairs, conservedPairs].expand((x) => x); - - for (var pair in allTests) { - var input = pair[0]; - var expected = pair[1]; + for (var (input, expected) in allTests) { var f; - f = new Float32x4(input, 2.0, 3.0, 4.0); + f = Float32x4(input, 2.0, 3.0, 4.0); checkEquals(expected, f.x); - Expect.equals(2.0, f.y); - Expect.equals(3.0, f.z); - Expect.equals(4.0, f.w); + checkEquals(2.0, f.y); + checkEquals(3.0, f.z); + checkEquals(4.0, f.w); - f = new Float32x4(1.0, input, 3.0, 4.0); - Expect.equals(1.0, f.x); + f = Float32x4(1.0, input, 3.0, 4.0); + checkEquals(1.0, f.x); checkEquals(expected, f.y); - Expect.equals(3.0, f.z); - Expect.equals(4.0, f.w); + checkEquals(3.0, f.z); + checkEquals(4.0, f.w); - f = new Float32x4(1.0, 2.0, input, 4.0); - Expect.equals(1.0, f.x); - Expect.equals(2.0, f.y); + f = Float32x4(1.0, 2.0, input, 4.0); + checkEquals(1.0, f.x); + checkEquals(2.0, f.y); checkEquals(expected, f.z); - Expect.equals(4.0, f.w); + checkEquals(4.0, f.w); - f = new Float32x4(1.0, 2.0, 3.0, input); - Expect.equals(1.0, f.x); - Expect.equals(2.0, f.y); - Expect.equals(3.0, f.z); + f = Float32x4(1.0, 2.0, 3.0, input); + checkEquals(1.0, f.x); + checkEquals(2.0, f.y); + checkEquals(3.0, f.z); checkEquals(expected, f.w); } } -main() { +void main() { for (int i = 0; i < 20; i++) { - testConstructor(); - testSplat(); - testZero(); - testAdd(); - testGetters(); + testConstructorAndGetters(); testSetters(); - testBitOperators(); + testSplat(); + testZeroConstructor(); + testAdd(); testConversions(); testSelect(); testShuffle(); @@ -526,3 +661,27 @@ main() { testSpecialValues(); } } + +void checkEquals(double expected, double actual) { + if (!_sameDouble(expected, actual)) { + Expect.fail("Not equal. Expected: $expected, actual: $actual"); + } +} + +void checkOneOf(List possibleValues, double actual) { + if (!possibleValues.any((v) => _sameDouble(v, actual))) { + Expect.fail( + "Not equal. Expected one of: ${possibleValues.join(', ')}, " + "actual: $actual", + ); + } +} + +bool _sameDouble(double v1, double v2) { + if (v1 == v2) { + // False positive for 0.0 and -0.0. + return v1.isNegative == v2.isNegative; + } + // False negative for NaN. + return v1.isNaN && v2.isNaN; +} diff --git a/tests/lib/typed_data/int32x4_test.dart b/tests/lib/typed_data/int32x4_test.dart index 897c8a50949..aa0a117187c 100644 --- a/tests/lib/typed_data/int32x4_test.dart +++ b/tests/lib/typed_data/int32x4_test.dart @@ -81,9 +81,97 @@ void testBigArguments() { } } +// TODO: Maybe move to `int32x4_arithmetic_test.dart`. +void testBitOperators() { + var m = Int32x4(0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA); + var n = Int32x4(0x5555555, 0x5555555, 0x5555555, 0x5555555); + Expect.equals(0xAAAAAAA, m.x); + Expect.equals(0xAAAAAAA, m.y); + Expect.equals(0xAAAAAAA, m.z); + Expect.equals(0xAAAAAAA, m.w); + Expect.equals(0x5555555, n.x); + Expect.equals(0x5555555, n.y); + Expect.equals(0x5555555, n.z); + Expect.equals(0x5555555, n.w); + Expect.equals(true, n.flagX); + Expect.equals(true, n.flagY); + Expect.equals(true, n.flagZ); + Expect.equals(true, n.flagW); + var o = m | n; // or + Expect.equals(0xFFFFFFF, o.x); + Expect.equals(0xFFFFFFF, o.y); + Expect.equals(0xFFFFFFF, o.z); + Expect.equals(0xFFFFFFF, o.w); + Expect.equals(true, o.flagX); + Expect.equals(true, o.flagY); + Expect.equals(true, o.flagZ); + Expect.equals(true, o.flagW); + o = m & n; // and + Expect.equals(0x0, o.x); + Expect.equals(0x0, o.y); + Expect.equals(0x0, o.z); + Expect.equals(0x0, o.w); + n = n.withX(0xAAAAAAA); + n = n.withY(0xAAAAAAA); + n = n.withZ(0xAAAAAAA); + n = n.withW(0xAAAAAAA); + Expect.equals(0xAAAAAAA, n.x); + Expect.equals(0xAAAAAAA, n.y); + Expect.equals(0xAAAAAAA, n.z); + Expect.equals(0xAAAAAAA, n.w); + o = m ^ n; // xor + Expect.equals(0x0, o.x); + Expect.equals(0x0, o.y); + Expect.equals(0x0, o.z); + Expect.equals(0x0, o.w); + Expect.equals(false, o.flagX); + Expect.equals(false, o.flagY); + Expect.equals(false, o.flagZ); + Expect.equals(false, o.flagW); +} + +void testSetters() { + var m = Int32x4.bool(false, false, false, false); + Expect.equals(false, m.flagX); + Expect.equals(false, m.flagY); + Expect.equals(false, m.flagZ); + Expect.equals(false, m.flagW); + m = m.withFlagX(true); + Expect.equals(true, m.flagX); + Expect.equals(false, m.flagY); + Expect.equals(false, m.flagZ); + Expect.equals(false, m.flagW); + m = m.withFlagY(true); + Expect.equals(true, m.flagX); + Expect.equals(true, m.flagY); + Expect.equals(false, m.flagZ); + Expect.equals(false, m.flagW); + m = m.withFlagZ(true); + Expect.equals(true, m.flagX); + Expect.equals(true, m.flagY); + Expect.equals(true, m.flagZ); + Expect.equals(false, m.flagW); + m = m.withFlagW(true); + Expect.equals(true, m.flagX); + Expect.equals(true, m.flagY); + Expect.equals(true, m.flagZ); + Expect.equals(true, m.flagW); +} + +void testGetters() { + var m = Int32x4.bool(false, true, true, false); + Expect.equals(false, m.flagX); + Expect.equals(true, m.flagY); + Expect.equals(true, m.flagZ); + Expect.equals(false, m.flagW); +} + main() { for (int i = 0; i < 20; i++) { testBigArguments(); testBadArguments(); + testBitOperators(); + testSetters(); + testGetters(); } }