blob: bb95ec8d11e8cc4b89c2122f886098af2791699f [file] [log] [blame]
<!doctype html>
<head><meta charset="utf8">
<title>SIMD.js specification v0.7.1</title>
<link rel="stylesheet" href="https://bterlson.github.com/ecmarkup/elements.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/github.min.css">
</head><body><emu-biblio href="./biblio.json"></emu-biblio>
<h1>SIMD.js specification v0.7.1</h1>
<div><h2>Table of Contents</h2><ol class="toc"><li><a href="#intro"><span class="secnum"></span> Introduction</a></li><li><a href="#types"><span class="secnum">1</span> ECMAScript Data Types and Values (6)</a><ol class="toc"><li><a href="#all-types"><span class="secnum">1.1</span> ECMAScript language types (6.1)</a><ol class="toc"><li><a href="#intrinsics"><span class="secnum">1.1.1</span> Well-Known Intrinsic Objects (6.1.7.4)</a></li></ol></li><li><a href="#simd-types"><span class="secnum">1.2</span> SIMD types</a><ol class="toc"><li><a href="#float32x4"><span class="secnum">1.2.1</span> Float32x4</a></li><li><a href="#int32x4"><span class="secnum">1.2.2</span> Int32x4</a></li><li><a href="#int16x8"><span class="secnum">1.2.3</span> Int16x8</a></li><li><a href="#int8x16"><span class="secnum">1.2.4</span> Int8x16</a></li><li><a href="#bool32x4"><span class="secnum">1.2.5</span> Bool32x4</a></li><li><a href="#bool16x8"><span class="secnum">1.2.6</span> Bool16x8</a></li><li><a href="#bool8x16"><span class="secnum">1.2.7</span> Bool8x16</a></li></ol></li></ol></li><li><a href="#abstract-operations"><span class="secnum">2</span> Abstract Operations (7)</a><ol class="toc"><li><a href="#type-conversion"><span class="secnum">2.1</span> Type Conversion (7.1)</a><ol class="toc"><li><a href="#to-primitive"><span class="secnum">2.1.1</span> ToPrimitive ( input [, PreferredType] ) (7.1.1)</a></li><li><a href="#to-boolean"><span class="secnum">2.1.2</span> ToBoolean ( argument ) (7.1.2)</a></li><li><a href="#to-number"><span class="secnum">2.1.3</span> ToNumber ( argument ) (7.1.3)</a></li><li><a href="#to-string"><span class="secnum">2.1.4</span> ToString ( argument ) (7.1.12)</a></li><li><a href="#to-object"><span class="secnum">2.1.5</span> ToObject ( argument ) (7.1.13)</a></li></ol></li><li><a href="#require-object-coercible"><span class="secnum">2.2</span> RequireObjectCoercible ( argument ) (7.2.1)</a></li><li><a href="#same-value"><span class="secnum">2.3</span> SameValue(x, y) (7.2.9)</a></li><li><a href="#same-value-zero"><span class="secnum">2.4</span> SameValueZero(x, y) (7.2.10)</a></li><li><a href="#abstract-relational-comparison"><span class="secnum">2.5</span> Abstract Relational Comparison (7.2.11)</a></li><li><a href="#abstract-equality"><span class="secnum">2.6</span> Abstract Equality Comparison (7.2.12)</a></li><li><a href="#strict-equality-comparison"><span class="secnum">2.7</span> Strict Equality Comparison (7.2.13)</a></li></ol></li><li><a href="#typeof"><span class="secnum">3</span> The typeof Operator (12.5.6)</a><ol class="toc"><li><a href="#typeof-evaluation"><span class="secnum">3.1</span> Runtime Semantics: Evaluation (12.5.6.1)</a></li></ol></li><li><a href="#addition"><span class="secnum">4</span> The Addition operator ( + ) (12.7.3)</a><ol class="toc"><li><a href="#addition-semantics"><span class="secnum">4.1</span> Runtime Semantics: Evaluation (12.7.3.1)</a></li></ol></li><li><a href="#simd"><span class="secnum">5</span> SIMD</a><ol class="toc"><li><a href="#simd-algorithms"><span class="secnum">5.1</span> Internal algorithms on SIMD types</a><ol class="toc"><li><a href="#simd-create"><span class="secnum">5.1.1</span> SIMDCreate( descriptor, fields...)</a></li><li><a href="#simd-abstract-extract-lane"><span class="secnum">5.1.2</span> SIMDExtractLane( value, field )</a></li><li><a href="#simd-abstract-replace-lane"><span class="secnum">5.1.3</span> SIMDReplaceLane( value, field, replacement )</a></li><li><a href="#simd-binary"><span class="secnum">5.1.4</span> SIMDBinaryOp( a, b, op, outputDescriptor )</a></li><li><a href="#simd-unary"><span class="secnum">5.1.5</span> SIMDUnaryOp( a, op )</a></li><li><a href="#simd-scalar"><span class="secnum">5.1.6</span> SIMDScalarOp( a, scalar, op )</a></li><li><a href="#simd-load"><span class="secnum">5.1.7</span> SIMDLoad( dataBlock, descriptor, byteOffset [, length] )</a></li><li><a href="#simd-store"><span class="secnum">5.1.8</span> SIMDStore( dataBlock, descriptor, byteOffset, n [, length] )</a></li><li><a href="#simd-reinterpret-cast"><span class="secnum">5.1.9</span> SIMDReinterpretCast( value, newDescriptor )</a></li><li><a href="#simd-int-type"><span class="secnum">5.1.10</span> SIMDBoolType( descriptor )</a></li><li><a href="#simd-boolean-op"><span class="secnum">5.1.11</span> SIMDBooleanOp( a, b, op )</a></li><li><a href="#UnsignedValue"><span class="secnum">5.1.12</span> UnsignedValue( value, descriptor )</a></li><li><a href="#simd-unsigned-boolean-op"><span class="secnum">5.1.13</span> SIMDUnsignedBooleanOp( a, b, op )</a></li></ol></li><li><a href="#simd-constructor"><span class="secnum">5.2</span> _SIMD_Constructor</a><ol class="toc"><li><a href="#simd-wrap"><span class="secnum">5.2.1</span> _SIMD_Constructor( value )</a></li><li><a href="#simd-wrapper"><span class="secnum">5.2.2</span> _SIMD_Constructor( fields... )</a></li><li><a href="#simd-splat"><span class="secnum">5.2.3</span> _SIMD_Constructor.splat(n)</a></li><li><a href="#simd-check"><span class="secnum">5.2.4</span> _SIMD_Constructor.check(a)</a></li><li><a href="#simd-add"><span class="secnum">5.2.5</span> _SIMD_Constructor.add(a, b)</a></li><li><a href="#simd-sub"><span class="secnum">5.2.6</span> _SIMD_Constructor.sub(a, b)</a></li><li><a href="#simd-mul"><span class="secnum">5.2.7</span> _SIMD_Constructor.mul(a, b)</a></li><li><a href="#simd-div"><span class="secnum">5.2.8</span> _SIMD_Constructor.div(a, b)</a></li><li><a href="#simd-max"><span class="secnum">5.2.9</span> _SIMD_Constructor.max(a, b)</a></li><li><a href="#simd-min"><span class="secnum">5.2.10</span> _SIMD_Constructor.min(a, b)</a></li><li><a href="#max-num"><span class="secnum">5.2.11</span> MaxNum(n, m)</a></li><li><a href="#simd-max-num"><span class="secnum">5.2.12</span> _SIMD_Constructor.maxNum(a, b)</a></li><li><a href="#min-num"><span class="secnum">5.2.13</span> MinNum(n, m)</a></li><li><a href="#simd-min-num"><span class="secnum">5.2.14</span> _SIMD_Constructor.minNum(a, b)</a></li><li><a href="#simd-neg"><span class="secnum">5.2.15</span> _SIMD_Constructor.neg(a)</a></li><li><a href="#simd-sqrt"><span class="secnum">5.2.16</span> _SIMD_Constructor.sqrt(a)</a></li><li><a href="#reciprocal"><span class="secnum">5.2.17</span> ReciprocalApproximation(n)</a></li><li><a href="#simd-reciprocal-approximation"><span class="secnum">5.2.18</span> _SIMD_Constructor.reciprocalApproximation(a, b)</a></li><li><a href="#reciprocal"><span class="secnum">5.2.19</span> ReciprocalSqrtApproximation(n)</a></li><li><a href="#simd-reciprocal-sqrt-approximation"><span class="secnum">5.2.20</span> _SIMD_Constructor.reciprocalSqrtApproximation(a)</a></li><li><a href="#simd-abs"><span class="secnum">5.2.21</span> _SIMD_Constructor.abs(a)</a></li><li><a href="#simd-and"><span class="secnum">5.2.22</span> _SIMD_Constructor.and(a, b)</a></li><li><a href="#simd-xor"><span class="secnum">5.2.23</span> _SIMD_Constructor.xor(a, b)</a></li><li><a href="#simd-or"><span class="secnum">5.2.24</span> _SIMD_Constructor.or(a, b)</a></li><li><a href="#simd-not"><span class="secnum">5.2.25</span> _SIMD_Constructor.not(a)</a></li><li><a href="#simd-less-than"><span class="secnum">5.2.26</span> _SIMD_Constructor.lessThan(a, b)</a></li><li><a href="#simd-less-than-or-equal"><span class="secnum">5.2.27</span> _SIMD_Constructor.lessThanOrEqual(a, b)</a></li><li><a href="#simd-greater-than"><span class="secnum">5.2.28</span> _SIMD_Constructor.greaterThan(a, b)</a></li><li><a href="#simd-greater-than-or-equal"><span class="secnum">5.2.29</span> _SIMD_Constructor.greaterThanOrEqual(a, b)</a></li><li><a href="#simd-unsigned-less-than"><span class="secnum">5.2.30</span> _SIMD_Constructor.unsignedLessThan(a, b)</a></li><li><a href="#simd-unsigned-less-than-or-equal"><span class="secnum">5.2.31</span> _SIMD_Constructor.unsignedLessThanOrEqual(a, b)</a></li><li><a href="#simd-unsigned-greater-than"><span class="secnum">5.2.32</span> _SIMD_Constructor.unsignedGreaterThan(a, b)</a></li><li><a href="#simd-unsigned-greater-than-or-equal"><span class="secnum">5.2.33</span> _SIMD_Constructor.unsignedGreaterThanOrEqual(a, b)</a></li><li><a href="#simd-equal"><span class="secnum">5.2.34</span> _SIMD_Constructor.equal(a, b)</a></li><li><a href="#simd-not-equal"><span class="secnum">5.2.35</span> _SIMD_Constructor.notEqual(a, b)</a></li><li><a href="#simd-any-true"><span class="secnum">5.2.36</span> _SIMD_Constructor.anyTrue(a)</a></li><li><a href="#simd-all-true"><span class="secnum">5.2.37</span> _SIMD_Constructor.allTrue(a)</a></li><li><a href="#simd-select"><span class="secnum">5.2.38</span> _SIMD_Constructor.select( selector, a, b )</a></li><li><a href="#saturate"><span class="secnum">5.2.39</span> Saturate( byteWidth, x )</a></li><li><a href="#add-saturate"><span class="secnum">5.2.40</span> AddSaturate( byteWidth )( x, y )</a></li><li><a href="#simd-add-saturate"><span class="secnum">5.2.41</span> _SIMD_Constructor.addSaturate( a, b )</a></li><li><a href="#sub-saturate"><span class="secnum">5.2.42</span> SubSaturate( byteWidth )( x, y )</a></li><li><a href="#simd-sub-saturate"><span class="secnum">5.2.43</span> _SIMD_Constructor.subSaturate( a, b )</a></li><li><a href="#unsigned-saturate"><span class="secnum">5.2.44</span> UnsignedSaturate( byteWidth, x )</a></li><li><a href="#unsigned-add-saturate"><span class="secnum">5.2.45</span> UnsignedAddSaturate( byteWidth )( x, y )</a></li><li><a href="#simd-unsigned-add-saturate"><span class="secnum">5.2.46</span> _SIMD_Constructor.unsignedAddSaturate( a, b )</a></li><li><a href="#unsigned-sub-saturate"><span class="secnum">5.2.47</span> UnsignedSubSaturate( byteWidth )( x, y )</a></li><li><a href="#simd-unsigned-sub-saturate"><span class="secnum">5.2.48</span> _SIMD_Constructor.unsignedSubSaturate( a, b )</a></li><li><a href="#simd-shift-left-by-scalar"><span class="secnum">5.2.49</span> _SIMD_Constructor.shiftLeftByScalar( a, scalar )</a></li><li><a href="#simd-shift-right-logical-by-scalar"><span class="secnum">5.2.50</span> _SIMD_Constructor.shiftRightLogicalByScalar( a, scalar )</a></li><li><a href="#simd-shift-right-arithmetic-by-scalar"><span class="secnum">5.2.51</span> _SIMD_Constructor.shiftRightArithmeticByScalar( a, scalar )</a></li><li><a href="#simd-unsigned-horizontal-sum"><span class="secnum">5.2.52</span> _SIMD_Constructor.unsignedHorizontalSum( a )</a></li><li><a href="#absolute-difference"><span class="secnum">5.2.53</span> AbsoluteDifference( a, b )</a></li><li><a href="#simd-unsigned-absolte-difference"><span class="secnum">5.2.54</span> _SIMD_Constructor.unsignedAbsoluteDifference( a, b )</a></li><li><a href="#simd-unsigned-widened-absolute-difference"><span class="secnum">5.2.55</span> _SIMD_Constructor.widenedUnsignedAbsoluteDifference( a, b )</a></li><li><a href="#simd-extract-lane"><span class="secnum">5.2.56</span> _SIMD_Constructor.extractLane( simd, field )</a></li><li><a href="#simd-unsigned-extract-lane"><span class="secnum">5.2.57</span> _SIMD_Constructor.unsignedExtractLane( simd, field )</a></li><li><a href="#simd-replace-lane"><span class="secnum">5.2.58</span> _SIMD_Constructor.replaceLane(simd, field, value)</a></li><li><a href="#simd-store-function"><span class="secnum">5.2.59</span> _SIMD_Constructor.store(tarray, index, simd)</a></li><li><a href="#simd-store1"><span class="secnum">5.2.60</span> _SIMD_Constructor.store1(tarray, index, simd)</a></li><li><a href="#simd-store2"><span class="secnum">5.2.61</span> _SIMD_Constructor.store2(tarray, index, simd)</a></li><li><a href="#simd-store3"><span class="secnum">5.2.62</span> _SIMD_Constructor.store3(tarray, index)</a></li><li><a href="#simd-load-function"><span class="secnum">5.2.63</span> _SIMD_Constructor.load(tarray, index)</a></li><li><a href="#simd-load1"><span class="secnum">5.2.64</span> _SIMD_Constructor.load1(tarray, index)</a></li><li><a href="#simd-load2"><span class="secnum">5.2.65</span> _SIMD_Constructor.load2(tarray, index)</a></li><li><a href="#simd-load3"><span class="secnum">5.2.66</span> _SIMD_Constructor.load3(tarray, index)</a></li><li><a href="#simd-to-timd"><span class="secnum">5.2.67</span> SIMDConstructor.fromTIMDBits( value )</a></li><li><a href="#simd-to-timd-logical"><span class="secnum">5.2.68</span> SIMDConstructor.fromTIMD( value )</a></li><li><a href="#swizzle"><span class="secnum">5.2.69</span> _SIMD_.swizzle( a, lanes... )</a></li><li><a href="#shuffle"><span class="secnum">5.2.70</span> _SIMD_.shuffle( a, b, lanes... )</a></li></ol></li><li><a href="#simd-proto"><span class="secnum">5.3</span> The _SIMD_Constructor.prototype</a><ol class="toc"><li><a href="#simd-proto-constructor"><span class="secnum">5.3.1</span> _SIMD_Constructor.prototype.constructor</a></li><li><a href="#simd-prototype-valueof"><span class="secnum">5.3.2</span> _SIMD_Constructor.prototype.valueOf()</a></li><li><a href="#simd-prototype-tolocalestring"><span class="secnum">5.3.3</span> _SIMD_Constructor.prototype.toLocaleString()</a></li><li><a href="#simd-prototype-tostring"><span class="secnum">5.3.4</span> _SIMD_Constructor.prototype.toString()</a></li><li><a href="#"><span class="secnum">5.3.5</span> _SIMD_Constructor.prototype [ @@toStringTag ]</a></li></ol></li><li><a href="#simd-descriptors"><span class="secnum">5.4</span> SIMD type descriptors</a><ol class="toc"><li><a href="#simd-float32x4"><span class="secnum">5.4.1</span> Float32x4Descriptor type descriptor</a><ol class="toc"><li><a href="#serialize-float32"><span class="secnum">5.4.1.1</span> SerializeFloat32( block, offset, n, isLittleEndian )</a></li><li><a href="#deserialize-float32"><span class="secnum">5.4.1.2</span> DeserializeFloat32( block, offset, isLittleEndian )</a></li></ol></li><li><a href="#simd-int32x4"><span class="secnum">5.4.2</span> Int32x4Descriptor type descriptor</a><ol class="toc"><li><a href="#serialize-int"><span class="secnum">5.4.2.1</span> SerializeInt( block, offset, n, isLittleEndian, descriptor )</a></li><li><a href="#deserialize-int32"><span class="secnum">5.4.2.2</span> DeserializeInt( block, offset, isLittleEndian, descriptor )</a></li><li><a href="#serialize-int32"><span class="secnum">5.4.2.3</span> SerializeInt32( block, offset, n, isLittleEndian )</a></li><li><a href="#deserialize-int32"><span class="secnum">5.4.2.4</span> DeserializeInt32( block, offset, isLittleEndian )</a></li></ol></li><li><a href="#simd-int16x8"><span class="secnum">5.4.3</span> Int16x8Descriptor type descriptor</a><ol class="toc"><li><a href="#serialize-int16"><span class="secnum">5.4.3.1</span> SerializeInt16( block, offset, n, isLittleEndian )</a></li><li><a href="#deserialize-int16"><span class="secnum">5.4.3.2</span> DeserializeInt16( block, offset, isLittleEndian )</a></li></ol></li><li><a href="#simd-int8x16"><span class="secnum">5.4.4</span> Int8x16Descriptor type descriptor</a><ol class="toc"><li><a href="#serialize-int8"><span class="secnum">5.4.4.1</span> SerializeInt8( block, offset, n, isLittleEndian )</a></li><li><a href="#deserialize-int8"><span class="secnum">5.4.4.2</span> DeserializeInt8( block, offset, isLittleEndian )</a></li></ol></li><li><a href="#simd-bool32x4"><span class="secnum">5.4.5</span> Bool32x4 type descriptor</a></li><li><a href="#simd-bool16x8"><span class="secnum">5.4.6</span> Bool16x8 type descriptor</a></li><li><a href="#simd-bool8x16"><span class="secnum">5.4.7</span> Bool8x16 type descriptor</a></li></ol></li></ol></li></ol></div><emu-intro id="intro">
<h1><span class="secnum"></span>Introduction</h1>
<p>
This proposal adds SIMD types and operations to ECMAScript. The proposal adds new primitive types Float32x4, etc, together with wrappers and a definition of their behavior in the language. The current proposal should form a full first draft with all functions and types included.
</p>
<p>
One problem that this spec aims to solve is to define equality for SIMD values. Existing implementations use object identity-based equality. However, maintaining object identity puts a big burden on compilers to maintain this identity through operations, where they would rather be able to duplicate and de-duplicate SIMD values arbitrarily based on algebraic identities. By making SIMD values into primitive types with structural equality, compilers are given more freedom.
</p>
<p>
Ideally, SIMD values will fit into a larger value types proposal. Such a proposal would be a bit more involved, but good work has already been done in that direction. This document describes SIMD without a larger value type system, but it aims to be consistent with how value types might work, and once someone steps forward to describe value types in more detail, it will be great to simplify this text by just explaining SIMD in terms of value types. On the other hand, this proposal gives a vehicle to work out some of the issues in value types and can be used as a guide for future value type designs.
</p>
<p>
This document is organized in terms of where changes would be made to the ES6 spec. Although ecmarkup generates numbering at the beginning of headers, these won't correspond to the numbering within the existing ECMA spec, so I've included a matching numbering in parentheses afterwards, referring to the ES6 spec.
</p>
<p>
In this text, <var>SIMD</var> is used to refer to the various SIMD types: Float32x4, Int32x4, Int16x8 Int8x16, Bool32x4, Bool16x8 and Bool8x16. Similarly to Number, <var>SIMD</var> is used to refer to both the type <em>and</em> the wrapper constructor object. This looks a bit confusing, but it provides the most regularity, as an aim of this specification is to make SIMD types primitives that operate analogously to the existing primitives, rather than a new, exotic sort of thing. To reduce ambiguity, the wrapper constructor is usually referred to as <var>SIMD</var>Constructor, and the type is referred to as <var>SIMD</var>Type. SIMD types are associated with a descriptor spec object, called <var>SIMD</var>Descriptor.</p>
<p><strong>Please file any issues <a href="https://github.com/johnmccutchan/ecmascript_simd/issues">here</a>!</strong> The authoritative copy of this file is in <a href="https://github.com/johnmccutchan/ecmascript_simd/blob/master/tc39/spec.html">in the simd.js repo</a>; to propose changes to this spec, please send pull requests against that repository. Daniel Ehrenberg (littledan) is responsible for watching for changes to that file, generating the output with ecmarkup and pushing it to <a href="http://littledan.github.io/simd.html">the current location</a>.</p>
<p>Because this document is in spec order, rather than written for direct readability, the logical starting point is actually <a href="#simd">halfway down</a>.</p>
<p>
Related links:
</p>
<ul>
<li><a href="https://github.com/nikomatsakis/typed-objects-explainer/blob/master/valuetypes.md">Value types proposal</a></li>
<li><a href="https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js">SIMD polyfill</a></li>
<li><a href="https://github.com/johnmccutchan/ecmascript_simd/issues/157">Bug about SIMD.js value semantics</a></li>
</ul>
<p>Changelog:</p>
<ul>
<li>v0.1: Initial proposal based on SIMD values held in Data Blocks</li>
<li>v0.2:
<ul>
<li>SIMD values are explained as Lists of Numbers, and serialized/deserialized only on loads and stores to TypedArrays, and casts.</li>
<li>SIMD values point to a type descriptor, not to the wrapper constructor, which makes cross-realm access more straightforward.</li>
<li>Add all SIMD types, more SIMD operations and all DataView operations.</li>
</ul>
</li>
<li>v0.3: Add more operations, fix some errors and clarify wording.</li>
<li>v0.4: Fix various bugs, mostly reported by rwaldron.</li>
<li>v0.4.1: Refactor definitions for integer types to reduce duplication.</li>
<li>v0.5: Logical and bitwise operations; Int64x2.</li>
<li>v0.5.1: Logical casts between types, like SIMD.float32x4.fromInt32x4; Less exact definition for reciprocalApproximation, reciprocalSqrtApproximation</li>
<li>v0.5.2: Saturating arithmetic; fix mul mis-spec.</li>
<li>v0.5.3: Remove mention of signalling NaN (matches ES6).</li>
<li>v0.5.4: Better formatting for modifications of existing algorithms.</li>
<li>v0.5.5: toLocaleString, shifts, saturating functions only on int16 and smaller, sumOfAbsoluteDifferences. This is the first version to include all functions.</li>
<li>v0.5.6: Fix a few typos, added notes, removed DataView methods, store returns value.</li>
<li>v0.6: Remove Int64x2 and add boolean vectors.</li>
<li>v0.6.1: Relax behavior on subnormals, float to int conversion throws on out of bounds, shift does not mask.</li>
<li>v0.7: Remove Float64x2, Bool64x2, {load,store}[123], selectBits (could be in phase 2); add unsigned operations and sum of absolute differences operations; minor fix in 'shift' definition; clarify what the SIMD object is.</li>
<li>v0.7.1: Add back in {load,store}[123], make ToString() homoiconic.</li>
</ul>
</emu-intro>
<emu-clause id="types">
<h1><span class="secnum">1</span>ECMAScript Data Types and Values (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">6</a>)</h1>
<emu-clause id="all-types">
<h1><span class="secnum">1.1</span>ECMAScript language types (<a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-language-types">6.1</a>)</h1>
<emu-clause id="intrinsics">
<h1><span class="secnum">1.1.1</span>Well-Known Intrinsic Objects (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-well-known-intrinsic-objects">6.1.7.4</a>)</h1>
<p>
<strong>Intrinsic name</strong>: %SIMD%
<br>
<strong>Global name</strong>: <code>SIMD</code>
<br>
<strong>ECMAScript Language Association</strong>: The <a href="#simd"><code>SIMD</code></a> object
</p>
<p>
<strong>Intrinsic name</strong>: %<var>SIMD</var>Constructor%
<br>
<strong>Global name</strong>: <code>SIMD.</code><var>SIMD</var> (e.g., <code>SIMD.Float32x4</code>)
<br>
<strong>ECMAScript Language Association</strong>: The <a href="#simd-constructor"><var>SIMD</var>Constructor</a> constructor
</p>
<p>
<strong>Intrinsic name</strong>: %<var>SIMD</var>Prototype%
<br>
<strong>Global name</strong>: <code>SIMD.</code><var>SIMD</var><code>.prototype</code> (e.g., <code>SIMD.Float32x4.prototype</code>)
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the prototype data property of <a href="#simd-constructor">%<var>SIMD</var>Constructor%</a>
</p>
<p>
<strong>Intrinsic name</strong>: %ArrayPrototype_join%
<br>
<strong>Global name</strong>: <code>Array.prototype.join</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "join" data property of the intrinsic %ArrayPrototype% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.join">ES2015 2.1.3.12</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_abs%
<br>
<strong>Global name</strong>: <code>Math.abs</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "abs" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.abs">ES2015 20.2.2.1</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_fround%
<br>
<strong>Global name</strong>: <code>Math.fround</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "fround" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.fround">ES2015 20.2.2.17</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_max%
<br>
<strong>Global name</strong>: <code>Math.max</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "max" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.max">ES2015 20.2.2.24</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_min%
<br>
<strong>Global name</strong>: <code>Math.min</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "min" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.min">ES2015 20.2.2.25</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_sqrt%
<br>
<strong>Global name</strong>: <code>Math.sqrt</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "max" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.sqrt">ES2015 20.2.2.32</a>)
</p>
<p>
<strong>Intrinsic name</strong>: %Math_imul%
<br>
<strong>Global name</strong>: <code>Math.imul</code>
<br>
<strong>ECMAScript Language Association</strong>: The initial value of the "imul" data property of the intrinsic %Math% object (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.imul">ES2015 20.2.2.19</a>)
</p>
</emu-clause>
</emu-clause>
<emu-clause id="simd-types">
<h1><span class="secnum">1.2</span>SIMD types</h1>
<emu-clause id="float32x4">
<h1><span class="secnum">1.2.1</span>Float32x4</h1>
<p>
<code>Float32x4</code> is a SIMD type representing four 32-bit floating point values. Float32x4 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Float32x4</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-float32x4">Float32x4 SIMD type descriptor</a>.
</p>
</emu-clause>
<emu-clause id="int32x4">
<h1><span class="secnum">1.2.2</span>Int32x4</h1>
<p>
<code>Int32x4</code> is a SIMD type representing four 32-bit integer values. Int32x4 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Int32x4</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-int32x4">Int32x4 SIMD type descriptor</a>
</p>
</emu-clause>
<emu-clause id="int16x8">
<h1><span class="secnum">1.2.3</span>Int16x8</h1>
<p>
<code>Int16x8</code> is a SIMD type representing eight 16-bit integer values. Int16x8 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Int16x8</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-int16x8">Int16x8 SIMD type descriptor</a>
</p>
</emu-clause>
<emu-clause id="int8x16">
<h1><span class="secnum">1.2.4</span>Int8x16</h1>
<p>
<code>Int8x16</code> is a SIMD type representing sixteen 8-bit integer values. Int8x16 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Int8x16</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-int8x16">Int8x16 SIMD type descriptor</a>
</p>
</emu-clause>
<emu-clause id="bool32x4">
<h1><span class="secnum">1.2.5</span>Bool32x4</h1>
<p>
<code>Bool32x4</code> is a SIMD type representing two boolean values, as an intermediate value in manipulating 128-bit vectors. Bool32x4 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Bool32x4</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-bool32x4">Bool32x4 SIMD type descriptor</a>
</p>
</emu-clause>
<emu-clause id="bool16x8">
<h1><span class="secnum">1.2.6</span>Bool16x8</h1>
<p>
<code>Bool16x8</code> is a SIMD type representing two boolean values, as an intermediate value in manipulating 128-bit vectors. Bool16x8 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Bool16x8</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-bool16x8">Bool16x8 SIMD type descriptor</a>
</p>
</emu-clause>
<emu-clause id="bool8x16">
<h1><span class="secnum">1.2.7</span>Bool8x16</h1>
<p>
<code>Bool8x16</code> is a SIMD type representing two boolean values, as an intermediate value in manipulating 128-bit vectors. Bool8x16 values can be created using the [[Call]] operation on the <a href="#simd-wrap">SIMD.Bool8x16</a> object. Its behavior as a SIMD type is defined by the <a href="#simd-bool8x16">Bool8x16 SIMD type descriptor</a>
</p>
</emu-clause>
</emu-clause>
</emu-clause>
<emu-clause id="abstract-operations">
<h1><span class="secnum">2</span>Abstract Operations (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-operations">7</a>)</h1>
<emu-clause id="type-conversion">
<h1><span class="secnum">2.1</span>Type Conversion (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-type-conversion">7.1</a>)</h1>
<emu-clause id="to-primitive">
<h1><span class="secnum">2.1.1</span>ToPrimitive ( input [, PreferredType] ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toprimitive">7.1.1</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>: return <var>input</var>
<emu-note><span class="note">Note</span>
An additional option considered is to define this as calling ToObject on it, and then ToPrimitive on the resulting wrapper object. This would have the advantage of allowing toString and valueOf be defined on the wrapper prototype, which seems more realistic to me as a path for value types.
</emu-note>
</emu-clause>
<emu-clause id="to-boolean">
<h1><span class="secnum">2.1.2</span>ToBoolean ( argument ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toboolean">7.1.2</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>: return <emu-const>true</emu-const>
<emu-note><span class="note">Note</span>
While it would be possible to make the zero-vector false as a boolean, there are multiple possible interepretations of ToBoolean, and if a programmer is refactoring scalar code, naively keeping in a conditional will lead to a false outcome. Implementation constraints make it expensive to throw on ToBoolean, so returning <emu-const>true</emu-const> (as Objects do) is a nice, neutral answer.
</emu-note>
</emu-clause>
<emu-clause id="to-number">
<h1><span class="secnum">2.1.3</span>ToNumber ( argument ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber">7.1.3</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>: throw a <emu-const>TypeError</emu-const> exception
</emu-clause>
<emu-clause id="to-string">
<h1><span class="secnum">2.1.4</span>ToString ( argument ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring">7.1.12</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>:
<emu-alg><ol>
<li>Let <var>elements</var> be an Array containing the contents of <var>argument</var>.[[SIMDElements]]</li>
<li>Let <var>t</var> be the string <code>"</code><var>SIMD</var><code>"</code>, e.g., <code>"Float32x4"</code>.</li>
<li>Let e be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args">Call</a>(%ArrayPrototype_join%, <var>elements</var>, «<code>","</code>»).</li>
<li>Return a new String value computed by concatenating the previous value of <code>"SIMD."</code>, <var>t</var>, <code>"("</code>, <var>e</var>, and <code>")"</code>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>On a SIMD vector, <code>eval(vector.toString()) == vector</code> in the initial global environment.</emu-note>
</emu-clause>
<emu-clause id="to-object">
<h1><span class="secnum">2.1.5</span>ToObject ( argument ) (<a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-toobject">7.1.13</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>: Return a new %<var>SIMD</var>Constructor% wrapper object whose [[SIMDWrapperData]] internal slot is set to <var>argument</var>.
</emu-clause>
</emu-clause>
<emu-clause id="require-object-coercible">
<h1><span class="secnum">2.2</span>RequireObjectCoercible ( argument ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-requireobjectcoercible">7.2.1</a>)</h1>
<strong>Argument type</strong>: <var>SIMD</var>Type
<br>
<strong>Result</strong>: return <var>argument</var>
</emu-clause>
<emu-clause id="same-value">
<h1><span class="secnum">2.3</span>SameValue(x, y) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevalue">7.2.9</a>)</h1>
<emu-alg><ol>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>x</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is different from <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>), return <emu-const>false</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Undefined, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Null, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Number, then
<ol>
<li>If <var>x</var> is <emu-const>NaN</emu-const> and <var>y</var> is <emu-const>NaN</emu-const>, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is +0 and <var>y</var> is -0, return <emu-const>false</emu-const>.</li>
<li>If <var>x</var> is -0 and <var>y</var> is +0, return <emu-const>false</emu-const>.</li>
<li>If <var>x</var> is the same Number value as <var>y</var>, return <emu-const>true</emu-const>.</li>
<li>Return <emu-const>false</emu-const>.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is String, then
<ol>
<li>If <var>x</var> and <var>y</var> are exactly the same sequence of code units (same length and same code units at corresponding indices) return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Boolean, then
<ol>
<li>If <var>x</var> and <var>y</var> are both true or both false, return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Symbol, then
<ol>
<li>If <var>x</var> and <var>y</var> are both the same Symbol value, return true; otherwise, return false.</li>
</ol>
</li>
<li>
<ins>For each SIMD type <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>Assert <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is <var>SIMD</var>Type.</ins>
</li>
<li>
<ins>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1:</ins>
<ol>
<li>
<ins>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevalue">SameValue</a>(<a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>x</var>, <var>i</var>), <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>y</var>, <var>i</var>)) is <emu-const>false</emu-const>, return <emu-const>false</emu-const>.</ins>
</li>
</ol>
</li>
<li>
<ins>return <emu-const>true</emu-const>
</ins>
</li>
</ol>
</li>
</ol>
</li>
<li>Return <emu-const>true</emu-const> if <var>x</var> and <var>y</var> are the same Object value. Otherwise, return <emu-const>false</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="same-value-zero">
<h1><span class="secnum">2.4</span>SameValueZero(x, y) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero">7.2.10</a>)</h1>
Add an extra step at the bottom of the definition of SameValueZero for the new case involving the new type:
<emu-alg><ol>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>x</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is different from <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>), return <emu-const>false</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Undefined, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Null, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Number, then
<ol>
<li>If <var>x</var> is <emu-const>NaN</emu-const> and <var>y</var> is <emu-const>NaN</emu-const>, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is +0 and <var>y</var> is -0, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is -0 and <var>y</var> is +0, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is the same Number value as <var>y</var>, return <emu-const>true</emu-const>.</li>
<li>Return <emu-const>false</emu-const>.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is String, then
<ol>
<li>If <var>x</var> and <var>y</var> are exactly the same sequence of code units (same length and same code units at corresponding indices) return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Boolean, then
<ol>
<li>If <var>x</var> and <var>y</var> are both true or both false, return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Symbol, then
<ol>
<li>If <var>x</var> and <var>y</var> are both the same Symbol value, return true; otherwise, return false.</li>
</ol>
</li>
<li>
<ins>For each SIMD type <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>Assert <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is <var>SIMD</var>Type.</ins>
</li>
<li>
<ins>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1:</ins>
<ol>
<li>
<ins>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero">SameValueZero</a>(<a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>x</var>, <var>i</var>), <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>y</var>, <var>i</var>)) is <emu-const>false</emu-const>, return <emu-const>false</emu-const>.</ins>
</li>
</ol>
</li>
<li>
<ins>return <emu-const>true</emu-const>
</ins>
</li>
</ol>
</li>
</ol>
</li>
<li>Return <emu-const>true</emu-const> if <var>x</var> and <var>y</var> are the same Object value. Otherwise, return <emu-const>false</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="abstract-relational-comparison">
<h1><span class="secnum">2.5</span>Abstract Relational Comparison (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">7.2.11</a>)</h1>
<emu-note><span class="note">Note</span><p>No changes needed for SIMD; it will throw a TypeError if either operand is a SIMD value because the algorithm will call ToNumber in step 6.a or 6.c, which throws on SIMD values.</p><p>It is important for Abstract Relational Comparison to throw on SIMD types because there is no clear scalar boolean interpretation, and allowing it to throw makes it possible overload the operator in the future.</p></emu-note>
</emu-clause>
<emu-clause id="abstract-equality">
<h1><span class="secnum">2.6</span>Abstract Equality Comparison (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-equality-comparison">7.2.12</a>)</h1>
Replace step 10 with the following:
<emu-alg><ol>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>x</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is the same as <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>), then
<ol>
<li>Return the result of performing Strict Equality Comparison x === y.</li>
</ol>
</li>
<li>If x is null and y is undefined, return <emu-const>true</emu-const>.</li>
<li>If x is undefined and y is null, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Number and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is String,<br> return the result of the comparison x == <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber">ToNumber</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is String and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is Number,<br> return the result of the comparison <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber">ToNumber</a>(<var>x</var>) == y.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Boolean, return the result of the comparison <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber">ToNumber</a>(<var>x</var>) == y.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is Boolean, return the result of the comparison x == <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber">ToNumber</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is either String, Number,
<ins>any <var>SIMD</var>Type,</ins> or Symbol and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is Object, then<br>return the result of the comparison x == <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toprimitive">ToPrimitive</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Object and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is either String, Number,
<ins>any <var>SIMD</var>Type,</ins> or Symbol, then<br>return the result of the comparison <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toprimitive">ToPrimitive</a>(<var>x</var>) == y.</li>
<li>Return <emu-const>false</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="strict-equality-comparison">
<h1><span class="secnum">2.7</span>Strict Equality Comparison (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-equality-comparison">7.2.13</a>)</h1>
Add a new step 9, before the existing step 9:
<emu-alg><ol>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>x</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>y</var>).</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is different from <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>), return <emu-const>false</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Undefined, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Null, return <emu-const>true</emu-const>.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Number, then
<ol>
<li>If <var>x</var> is <emu-const>NaN</emu-const>, return <emu-const>false</emu-const>.</li>
<li>If <var>y</var> is <emu-const>NaN</emu-const>, return <emu-const>false</emu-const>.</li>
<li>If <var>x</var> is the same Number value as y, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is +0 and y is −0, return <emu-const>true</emu-const>.</li>
<li>If <var>x</var> is −0 and y is +0, return <emu-const>true</emu-const>.</li>
<li>Return <emu-const>false</emu-const>.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is String, then
<ol>
<li>If <var>x</var> and <var>y</var> are exactly the same sequence of code units (same length and same code units at corresponding indices) return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Boolean, then
<ol>
<li>If <var>x</var> and <var>y</var> are both true or both false, return true; otherwise, return false.</li>
</ol>
</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is Symbol, then
<ol>
<li>If <var>x</var> and <var>y</var> are both the same Symbol value, return true; otherwise, return false.</li>
</ol>
</li>
<li>
<ins>For each SIMD type <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>x</var>) is <var>SIMD</var>Type:</ins>
<ol>
<li>
<ins>Assert <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>y</var>) is <var>SIMD</var>Type.</ins>
</li>
<li>
<ins>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1:</ins>
<ol>
<li>
<ins>If <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>x</var>, <var>i</var>) === <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>y</var>, <var>i</var>) is <emu-const>false</emu-const>, return <emu-const>false</emu-const>.</ins>
</li>
</ol>
</li>
<li>
<ins>return <emu-const>true</emu-const>
</ins>
</li>
</ol>
</li>
</ol>
</li>
<li>Return <emu-const>true</emu-const> if <var>x</var> and <var>y</var> are the same Object value. Otherwise, return <emu-const>false</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="typeof">
<h1><span class="secnum">3</span>The typeof Operator (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-typeof-operator">12.5.6</a>)</h1>
<emu-clause id="typeof-evaluation">
<h1><span class="secnum">3.1</span>Runtime Semantics: Evaluation (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-typeof-operator-runtime-semantics-evaluation">12.5.6.1</a>)</h1>
<strong>Type of val</strong>: Float32x4
<br>
<strong>Result</strong>: "float32x4"
<br>
<strong>Type of val</strong>: Int32x4
<br>
<strong>Result</strong>: "int32x4"
<br>
<strong>Type of val</strong>: Int16x8
<br>
<strong>Result</strong>: "int16x8"
<br>
<strong>Type of val</strong>: Int8x16
<br>
<strong>Result</strong>: "int8x16"
<br>
<strong>Type of val</strong>: Bool32x4
<br>
<strong>Result</strong>: "bool32x4"
<br>
<strong>Type of val</strong>: Bool16x8
<br>
<strong>Result</strong>: "bool16x8"
<br>
<strong>Type of val</strong>: Bool8x16
<br>
<strong>Result</strong>: "bool8x16"
<emu-note><span class="note">Note</span>This follows the pattern for Number ("number"), Boolean ("boolean"), etc.</emu-note>
</emu-clause>
</emu-clause>
<emu-clause id="addition">
<h1><span class="secnum">4</span>The Addition operator ( + ) (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-addition-operator-plus">12.7.3</a>)</h1>
<emu-clause id="addition-semantics">
<h1><span class="secnum">4.1</span>Runtime Semantics: Evaluation (<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-addition-operator-plus">12.7.3.1</a>)</h1>
<emu-note><span class="note">Note</span><p>No changes needed for SIMD. With one SIMD argument and one argument which is a String after ToPrimitive is applied, this will coerce the SIMD value to a string, giving a printed representation like <code>"float32x4(1, 2, 3, 4)"</code>. Otherwise, if either argument is a SIMD value, then ToNumber will be run on step 12. or 14., which would throw a TypeError.</p><p>It is important for <code>+</code> to throw when applied to SIMD types to allow the future definition of operator overloading on <code>+</code> . Is the current SIMD+String behavior acceptable, or should that throw too?</p></emu-note>
</emu-clause>
</emu-clause>
<emu-clause id="simd">
<h1><span class="secnum">5</span>SIMD</h1>
<p>
The SIMD object is the %SIMD% intrinsic object and the initial value of the SIMD property of the global object. The SIMD object is a single ordinary object.
</p>
<p>
The value of the [[Prototype]] internal slot of the SIMD object is the intrinsic object %ObjectPrototype% (19.1.3).
</p>
<p>
The SIMD object is not a function object. It does not have a [[Construct]] internal method; it is not possible to use the SIMD object as a constructor with the new operator. The SIMD object also does not have a [[Call]] internal method; it is not possible to invoke the SIMD object as a function.
</p>
<p>
The SIMD global object has several constructor properties, one for each SIMD type.
</p>
<p>
Each SIMD value is specified as a record with the following internal attributes:
</p>
<ul>
<li>[[SIMDTypeDescriptor]], which refers to the wrapper constructor for the type.</li>
<li>[[SIMDElements]], which is a List of values representing the SIMD contents. The [[SIMDElements]] List is modified in internal algorithms when building a SIMD value, but never modified after that. As a rule, the elements list may be modified before putting it in the record, but may not be modified once it is in a record for a SIMD value.</li>
</ul>
SIMD type descriptors have the following internal slots:
<ul>
<li>[[SIMDLength]]: The number of elements present in a SIMD value of the type</li>
<li>[[SIMDElementSize]]: Size in bytes of each element</li>
<li>[[SIMDCastNumber]]: An internal algorithm for down-casting a Number to the precision representable in the SIMD type</li>
<li>[[SIMDSerializeElement]]: An internal algorithm for writing a Number as [[SIMDElementSize]] bytes</li>
<li>[[SIMDDeserializeElement]]: An internal algorithm for converting [[SIMDElementSize]] bytes into a Number</li>
</ul>
<p>
All SIMD types are either integer SIMD types, boolean SIMD types or or floating point SIMD types. Certain operations are defined on either integer, boolean or floating point types. It is noted in the section on each SIMD type whether it is an integer, boolean or floating point type.
</p>
<p>
The [[SIMDElementSize]], [[SIMDSerializeElement]] and [[SIMDDeserializeElement]] slots are optional, and defined only on certain SIMD types. Without these, cast, load and store operations are undefined. They come as a pair.
</p>
<emu-note><span class="note">Note</span>Rather than constructors having internal slots, this could be specified by a table analogous to Table 49 in the ES6 description for TypedArrays. However, the author finds it easier to express this purely in terms of records. TypedArrays could be specified like this too, and share some infrastructure with SIMD, but in their current form, it seems difficult to generalize them to SIMD directly.</emu-note>
<emu-note><span class="note">Note</span>SIMDCastNumber converts elements to Numbers; however, for most SIMD types, it will convert them to a restricted range of Number. In a real implementation, the numbers would likely be represented in a more compact form. However, the internal representation is not observable.</emu-note>
<emu-clause id="simd-algorithms">
<h1><span class="secnum">5.1</span>Internal algorithms on SIMD types</h1>
<emu-clause id="simd-create" aoid="SIMDCreate">
<h1><span class="secnum">5.1.1</span>SIMDCreate( descriptor, fields...)</h1>
This internal algorithm creates a new value of the type corresponding to the specified wrapper with the following procedure:
<emu-note><span class="note">Note</span>The following algorithm uses splat arguments in the spec and indexes them as an array, but there isn't proper machinery in the spec to describe this behavior</emu-note>
<emu-alg><ol>
<li>If Length(fields) == <var>descriptor</var>.[[SIMDLength]], then throw a TypeError.</li>
<li>Let <var>list</var> be a new List of length <var>descriptor</var>.[[SIMDLength]].</li>
<li>For <var>i</var> from 0 to <var>descriptor</var>.[[SIMDLength]],
<ol>
<li>Let <var>n</var> be <var>descriptor</var>.[[SIMDCastNumber]](fields[<var>i</var>]).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>n</var>).</li>
<li>Set <var>list</var>[<var>i</var>] to <var>n</var>.</li>
</ol>
</li>
<li>Return the record { [[SIMDTypeDescriptor]]: <var>descriptor</var>, [[SIMDElements]]: <var>list</var> }.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-abstract-extract-lane" aoid="SIMDExtractLane">
<h1><span class="secnum">5.1.2</span>SIMDExtractLane( value, field )</h1>
<emu-alg><ol>
<li>Assert: <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>value</var>) is a <var>SIMD</var>Type.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>field</var>) is not Number, throw a TypeError</li>
<li>If <var>field</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>field</var>) or <var>field</var> &lt; 0 or <var>field</var> &gt;= <var>descriptor</var>.[[SIMDLength]], throw a RangeError.</li>
<li>Return <var>value</var>.[[SIMDElements]][<var>field</var>]</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>While this single definition doesn't explicitly refer to the SIMD type in indexing the list, an implementation may use different representations for the Number elements on different types and generate different code for the accesses.</emu-note>
</emu-clause>
<emu-clause id="simd-abstract-replace-lane" aoid="SIMDReplaceLane">
<h1><span class="secnum">5.1.3</span>SIMDReplaceLane( value, field, replacement )</h1>
<emu-alg><ol>
<li>Assert: <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>value</var>) is a <var>SIMD</var>Type.</li>
<li>Let <var>descriptor</var> be <var>a</var>.[[SIMDTypeDescriptor]].</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>field</var>) is not Number, throw a TypeError</li>
<li>If <var>field</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>field</var>) or <var>field</var> &lt; 0 or <var>field</var> &gt;= <var>descriptor</var>.[[SIMDLength]], throw a RangeError.</li>
<li>Let <var>list</var> be a copy of <var>value</var>.[[SIMDElements]].</li>
<li>Set <var>list</var>[<var>field</var>] to <var>replacement</var>.</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>descriptor</var>, ...<var>list</var>).</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>While this single definition doesn't explicitly refer to the SIMD type in indexing the list, an implementation may use different representations for the Number elements on different types and generate different code for the accesses.</emu-note>
</emu-clause>
<emu-clause id="simd-binary" aoid="SIMDBinaryOp">
<h1><span class="secnum">5.1.4</span>SIMDBinaryOp( a, b, op, outputDescriptor )</h1>
<emu-alg><ol>
<li>Assert: <var>a</var>.[[SIMDTypeDescriptor]] is <var>b</var>.[[SIMDTypeDescriptor]]</li>
<li>Let <var>descriptor</var> be <var>a</var>.[[SIMDTypeDescriptor]].</li>
<li>If <var>outputDescriptor</var> is not provided, let <var>outputDescriptor</var> be <var>descriptor</var>.</li>
<li>Let <var>list</var> be a new List of length <var>descriptor</var>.[[SIMDLength]].</li>
<li>For <var>i</var> from 0 to <var>descriptor</var>.[[SIMDLength]],
<ol>
<li>Let <var>ax</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>i</var>).</li>
<li>Let <var>bx</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>b</var>, <var>i</var>).</li>
<li>Let <var>res</var> = op(<var>ax</var>, <var>bx</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>res</var>).</li>
<li>Set <var>list</var>[<var>i</var>] to <var>res</var>.</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>outputDescriptor</var>, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unary" aoid="SIMDUnaryOp">
<h1><span class="secnum">5.1.5</span>SIMDUnaryOp( a, op )</h1>
<emu-alg><ol>
<li>Let <var>descriptor</var> be <var>a</var>.[[SIMDTypeDescriptor]].</li>
<li>Let <var>list</var> be a new List of length <var>descriptor</var>.[[SIMDLength]].</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>block</var>).</li>
<li>For <var>i</var> from 0 to <var>descriptor</var>.[[SIMDLength]],
<ol>
<li>Let <var>ax</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>i</var>).</li>
<li>Let <var>res</var> = op(<var>ax</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>res</var>).</li>
<li>Set <var>list</var>[<var>i</var>] to <var>res</var>.</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>descriptor</var>, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-scalar" aoid="SIMDUnaryOp">
<h1><span class="secnum">5.1.6</span>SIMDScalarOp( a, scalar, op )</h1>
<emu-alg><ol>
<li>Let <var>descriptor</var> be <var>a</var>.[[SIMDTypeDescriptor]].</li>
<li>Let <var>list</var> be a new List of length <var>descriptor</var>.[[SIMDLength]].</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>block</var>).</li>
<li>For <var>i</var> from 0 to <var>descriptor</var>.[[SIMDLength]],
<ol>
<li>Let <var>ax</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>i</var>).</li>
<li>Let <var>res</var> = op(<var>ax</var>, <var>scalar</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>res</var>).</li>
<li>Set <var>list</var>[<var>i</var>] to <var>res</var>.</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>descriptor</var>, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-load" aoid="SIMDLoad">
<h1><span class="secnum">5.1.7</span>SIMDLoad( dataBlock, descriptor, byteOffset [, length] )</h1>
<emu-alg><ol>
<li>Assert: <var>dataBlock</var> is a Data Block, <var>descriptor</var> is a SIMD type descriptor</li>
<li>If <var>length</var> is not provided, let <var>length</var> be <var>descriptor</var>.[[SIMDLength]]. Otherwise, assert <var>length</var> &lt;= <var>descriptor</var>.[[SIMDLength]].</li>
<li>Assert: <var>byteOffset</var> is an integer greater than or equal to zero, and less than or equal to the size of <var>dataBlock</var> - <var>descriptor</var>.[[SIMDElementSize]] * <var>length</var>.</li>
<li>Let <var>list</var> be a List of length <var>descriptor</var>.[[SIMDLength]], initialized to all 0.</li>
<li>For <var>i</var> from 0 to <var>length</var> - 1,
<ol>
<li>Set <var>list</var>[<var>i</var>] to <var>descriptor</var>.[[SIMDDeserializeElement]](<var>dataBlock</var>, <var>byteOffset</var>).</li>
</ol>
</li>
<li>Return the record { [[SIMDTypeDescriptor]]: <var>descriptor</var>, [[SIMDElements]]: <var>list</var> }.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-store" aoid="SIMDStore">
<h1><span class="secnum">5.1.8</span>SIMDStore( dataBlock, descriptor, byteOffset, n [, length] )</h1>
<emu-alg><ol>
<li>Assert: <var>dataBlock</var> is a Data Block, <var>descriptor</var> is a SIMD type descriptor</li>
<li>If <var>length</var> is not provided, let <var>length</var> be <var>descriptor</var>.[[SIMDLength]]. Otherwise, assert <var>length</var> &lt;= <var>descriptor</var>.[[SIMDLength]].</li>
<li>Assert: <var>byteOffset</var> is an integer greater than or equal to zero, and less than or equal to the size of <var>dataBlock</var> - <var>descriptor</var>.[[SIMDElementSize]] * <var>length</var>.</li>
<li>For <var>i</var> from 0 to <var>length</var> - 1,
<ol>
<li><var>descriptor</var>.[[SIMDSerializeElement]](<var>dataBlock</var>, <var>byteOffset</var> + <var>i</var> * <var>descriptor</var>.[[SIMDElementSize]], <var>n</var>.[[SIMDElements]][<var>i</var>]).</li>
</ol>
</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-reinterpret-cast" aoid="SIMDReinterpretCast">
<h1><span class="secnum">5.1.9</span>SIMDReinterpretCast( value, newDescriptor )</h1>
<emu-note><span class="note">Note</span>This is used to define operations like SIMD.Float32x4.fromInt8x16Bits.</emu-note>
<emu-alg><ol>
<li>Assert: <var>value</var>.[[SIMDTypeDescriptor]].[[SIMDLength]] * <var>value</var>.[[SIMDTypeDescriptor]].[[SIMDElementSize]] == <var>newDescriptor</var>.[[SIMDLength]] * <var>newDescriptor</var>.[[SIMDElementSize]].</li>
<li>Let <var>bytes</var> be <var>newDescriptor</var>.[[SIMDLength]] * <var>newDescriptor</var>.[[SIMDElementSize]].</li>
<li>Let <var>block</var> be the result of <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-createbytedatablock">CreateByteDataBlock</a>(<var>bytes</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>block</var>).</li>
<li><a href="#simd-store">SIMDStore</a>(<var>block</var>, <var>value</var>, 0).</li>
<li>Return <a href="#simd-load">SIMDLoad</a>(<var>block</var>, <var>newDescriptor</var>, 0).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-int-type" aoid="SIMDBoolType">
<h1><span class="secnum">5.1.10</span>SIMDBoolType( descriptor )</h1>
<emu-alg><ol>
<li>Assert: <var>descriptor</var>.[[SIMDLength]] * _descriptor.[[SIMDElementSize]] = 128. Otherwise, in a future extension to the spec, different boolean descriptors will be returned.</li>
<li>Let <var>length</var> be <var>descriptor</var>.[[SIMDLength]].</li>
<li>If <var>length</var> = 4, return Bool32x4Descriptor.</li>
<li>If <var>length</var> = 8, return Bool16x8Descriptor.</li>
<li>Assert <var>length</var> = 16.</li>
<li>Return Bool8x16Descriptor.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-boolean-op" aoid="SIMDBooleanOp">
<h1><span class="secnum">5.1.11</span>SIMDBooleanOp( a, b, op )</h1>
<emu-alg><ol>
<li>Let <var>outputDescriptor</var> be <a href="#simd-int-type">SIMDBoolType</a>(<var>a</var>.[[SIMDTypeDescriptor]]).</li>
<li>Return <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <var>op</var>, <var>outputDescriptor</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="UnsignedValue">
<h1><span class="secnum">5.1.12</span>UnsignedValue( value, descriptor )</h1>
<emu-alg><ol>
<li>If <var>value</var> &lt; 0, let <var>value</var> be <var>value</var> + 1 &lt;&lt; (<var>descriptor</var>.[[SIMDElementSize]] * 8).</li>
<li>Return <var>value</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-boolean-op" aoid="SIMDUnsignedBooleanOp">
<h1><span class="secnum">5.1.13</span>SIMDUnsignedBooleanOp( a, b, op )</h1>
<emu-alg><ol>
<li>Let <var>outputDescriptor</var> be <a href="#simd-int-type">SIMDBoolType</a>(<var>a</var>.[[SIMDTypeDescriptor]]).</li>
<li>Define the internal algorithm <var>unsignedOp</var>( <var>x</var>, <var>y</var> ) as performing the following steps:
<ol>
<li>Return <var>op_(UnsignedValue(_a</var>.[[SIMDTypeDescriptor]], <var>x</var>), UnsignedValue(<var>a</var>.[[SIMDTypeDescriptor]], <var>y</var>))</li>
</ol>
</li>
<li>Return <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <var>unsignedOp</var>, <var>outputDescriptor</var>).</li>
</ol></emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="simd-constructor">
<h1><span class="secnum">5.2</span><var>SIMD</var>Constructor</h1>
<p>
Each <var>SIMD</var>Constructor, namely Float32x4, Int32x4, Int16x8, and Int8x16, is associated with a <var>SIMD</var>Type and <var>SIMD</var>Descriptor. This section describes the constructors and properties on them. Most properties are identical, existing separately defined on each constructor, with most differences being in the <var>SIMD</var>Descriptor. Certain functions are defined only on a subset of <var>SIMD</var>Constructors, however, and this is noted above their algorithm definition.
</p>
<p>
The definitions of the constructor and properties of the constructor to follow constitute different identities of functions and objects for each of the copies; in a real implementation, they may call out to completely different pieces of code, even if their implementation in the spec is the same.
</p>
<emu-note><span class="note">Note</span>
As with Boolean, String, etc, <var>SIMD</var>Constructor is a constructor for the wrapper when invoked with new, and returns a primitive when called as a function.
</emu-note>
<emu-clause id="simd-wrap">
<h1><span class="secnum">5.2.1</span><var>SIMD</var>Constructor( value )</h1>
This description applies if the constructor is called with exactly one argument.
<emu-alg><ol>
<li>If <emu-const>NewTarget</emu-const> is undefined, throw a <emu-const>ReferenceError</emu-const> (NB: <emu-const>TypeError</emu-const>?).</li>
<li>If <var>value</var> is not of the type <var>SIMD</var>Type, throw a <emu-const>TypeError</emu-const>.</li>
<li>Let <var>O</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinarycreatefromconstructor">OrdinaryCreateFromConstructor</a>(<emu-const>NewTarget</emu-const>, <code>"%_SIMD_Prototype%"</code>, «[[SIMDWrapperData]]» ).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>O</var>).</li>
<li>Set the value of <var>O</var>’s [[SIMDWrapperData]] internal slot to <var>value</var>.</li>
<li>Return <var>O</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-wrapper">
<h1><span class="secnum">5.2.2</span><var>SIMD</var>Constructor( fields... )</h1>
This description applies if the constructor is called with more than one argument.
<emu-alg><ol>
<li>If <var>SIMD</var>Descriptor.[[SIMDElementsLength]] does not equal Length(fields), throw a TypeError.</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, fields...).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-splat">
<h1><span class="secnum">5.2.3</span><var>SIMD</var>Constructor.splat(n)</h1>
<emu-alg><ol>
<li>Let <var>list</var> be a new List of length <var>SIMD</var>Descriptor.[[SIMDLength]], with all entries filled with <var>n</var>.</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-check">
<h1><span class="secnum">5.2.4</span><var>SIMD</var>Constructor.check(a)</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Return <var>a</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-add">
<h1><span class="secnum">5.2.5</span><var>SIMD</var>Constructor.add(a, b)</h1>
This definition uses the refers to + as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-addition-operator-plus">ES2015 12.7.3 (The Addition operator ( + ))</a>, with the following change in behavior: If either argument to + is a sub-normal floating point number, then the result is defined as either gradual underflow or flushing that argument to 0.
<emu-note><span class="note">Note</span>The definition is weaker for SIMD than for scalar + to allow for implementation on some SIMD architectures which flush to 0 on subnormals.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, +).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-sub">
<h1><span class="secnum">5.2.6</span><var>SIMD</var>Constructor.sub(a, b)</h1>
This definition uses the refers to - as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-subtraction-operator-minus">ES2015 12.7.4 (The Subtraction operator ( - ))</a>, with the following change in behavior: If either argument to - is a sub-normal floating point number, then the result is defined as either gradual underflow or flushing that argument to 0.
<emu-note><span class="note">Note</span>The definition is weaker for SIMD than for scalar - to allow for implementation on some SIMD architectures which flush to 0 on subnormals.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, -).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-mul">
<h1><span class="secnum">5.2.7</span><var>SIMD</var>Constructor.mul(a, b)</h1>
This definition uses the refers to - as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-applying-the-mul-operator">ES2015 12.6.3.1 (Applying the * Operator)</a>, with the following change in behavior: If either argument to * is a sub-normal floating point number, then the result is defined as either gradual underflow or flushing that argument to 0.
<emu-note><span class="note">Note</span>The definition is weaker for SIMD than for scalar * to allow for implementation on some SIMD architectures which flush to 0 on subnormals.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>SIMD</var>Type is an integer SIMD type, let <var>op</var> be %Math_imul%; otherwise, <var>SIMD</var>Type is a floating point SIMD type, and let <var>op</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-applying-the-mul-operator">*</a>.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <var>op</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-div">
<h1><span class="secnum">5.2.8</span><var>SIMD</var>Constructor.div(a, b)</h1>
<p>
This definition uses the refers to - as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-applying-the-div-operator">ES2015 12.6.3.2 (Applying the / Operator)</a>, with the following change in behavior: If either argument to / is a sub-normal floating point number, then the result is defined as either as either gradual underflow or flushing that argument to 0.
</p>
<emu-note><span class="note">Note</span>The definition is weaker for SIMD than for scalar / to allow for implementation on some SIMD architectures which flush to 0 on subnormals.</emu-note>
<p>
This function is defined only on floating point SIMD types.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-applying-the-div-operator">/</a>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-max">
This property is defined only on floating point SIMD types.
<h1><span class="secnum">5.2.9</span><var>SIMD</var>Constructor.max(a, b)</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, %Math_max%).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-min">
This property is defined only on floating point SIMD types.
<h1><span class="secnum">5.2.10</span><var>SIMD</var>Constructor.min(a, b)</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, %Math_min%).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="max-num" aoid="MaxNum">
<h1><span class="secnum">5.2.11</span>MaxNum(n, m)</h1>
<emu-alg><ol>
<li>Assert <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>n</var>) is Number and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>m</var>) is Number.</li>
<li>If <var>n</var> is <emu-const>NaN</emu-const>, return <var>m</var>.</li>
<li>If <var>m</var> is <emu-const>NaN</emu-const>, return <var>n</var>.</li>
<li>Let <var>result</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args">Call</a>(%Math_max%, %Math%, «<var>n</var>, <var>m</var>»).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-max-num">
<h1><span class="secnum">5.2.12</span><var>SIMD</var>Constructor.maxNum(a, b)</h1>
This property is defined only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, MaxNum).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="min-num" aoid="MinNum">
<h1><span class="secnum">5.2.13</span>MinNum(n, m)</h1>
<emu-alg><ol>
<li>Assert <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>n</var>) is Number and <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-data-types-and-values">Type</a>(<var>m</var>) is Number.</li>
<li>If <var>n</var> is <emu-const>NaN</emu-const>, return <var>m</var>.</li>
<li>If <var>m</var> is <emu-const>NaN</emu-const>, return <var>n</var>.</li>
<li>Let <var>result</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args">Call</a>(%Math_min%, %Math%, «<var>n</var>, <var>m</var>»).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-min-num">
<h1><span class="secnum">5.2.14</span><var>SIMD</var>Constructor.minNum(a, b)</h1>
This property is defined only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, MinNum).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-neg">
<h1><span class="secnum">5.2.15</span><var>SIMD</var>Constructor.neg(a)</h1>
This definition uses the refers to unary - as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-unary-minus-operator">ES2015 12.5.10 (Unary - Operator)</a>.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-unary-minus-operator">-</a>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-sqrt">
<h1><span class="secnum">5.2.16</span><var>SIMD</var>Constructor.sqrt(a)</h1>
This property is defined only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, %Math_sqrt%).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="reciprocal" aoid="ReciprocalApproximation">
<h1><span class="secnum">5.2.17</span>ReciprocalApproximation(n)</h1>
Returns an implementation-dependent approximation to the reciprocal of <var>n</var>.
<ul>
<li>If <var>n</var> is <emu-const>NaN</emu-const>, the result is <emu-const>NaN</emu-const>.</li>
<li>If <var>n</var> is +0, the result is +∞.</li>
<li>If <var>n</var> is -0, the result is -∞.</li>
<li>If <var>n</var> is +∞, the result is +0.</li>
<li>If <var>n</var> is -∞, the result is -0.</li>
</ul>
</emu-clause>
<emu-clause id="simd-reciprocal-approximation">
<h1><span class="secnum">5.2.18</span><var>SIMD</var>Constructor.reciprocalApproximation(a, b)</h1>
This property is defined only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, ReciprocalApproximation).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="reciprocal" aoid="ReciprocalSqrtApproximation">
<h1><span class="secnum">5.2.19</span>ReciprocalSqrtApproximation(n)</h1>
Returns an implementation-dependent approximation to the reciprocal of the square root of <var>n</var>.
<ul>
<li>If <var>n</var> is <emu-const>NaN</emu-const>, the result is <emu-const>NaN</emu-const>.</li>
<li>If <var>n</var> is +0, the result is +∞.</li>
<li>If <var>n</var> is -0, the result is -∞.</li>
<li>If <var>n</var> is +∞, the result is +0.</li>
<li>If <var>n</var> is less than 0, the result is <emu-const>NaN</emu-const>.</li>
</ul>
</emu-clause>
<emu-clause id="simd-reciprocal-sqrt-approximation">
<h1><span class="secnum">5.2.20</span><var>SIMD</var>Constructor.reciprocalSqrtApproximation(a)</h1>
This property is defined only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, ReciprocalSqrtApproximation).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-abs">
<h1><span class="secnum">5.2.21</span><var>SIMD</var>Constructor.abs(a)</h1>
This operation exists only on floating point SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, %Math_abs%).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-and">
<h1><span class="secnum">5.2.22</span><var>SIMD</var>Constructor.and(a, b)</h1>
<p>
This definition uses the refers to &amp; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-binary-bitwise-operators">ES2015 12.11 (Binary Bitwise Operators)</a>.
</p>
<p>
This operation exists only on integer and boolean SIMD types.
</p>
<emu-note><span class="note">Note</span>On boolean types, this could have been specified as using &amp;&amp; rather than &amp;. However, the behavior is the same, as <code>ToBoolean(x&amp;y)</code> is the same as <code>x &amp;&amp; y</code> for boolean <code>x</code> and <code>y</code>. The same goes for <code>or</code> below.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, &amp;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-xor">
<h1><span class="secnum">5.2.23</span><var>SIMD</var>Constructor.xor(a, b)</h1>
<p>
This definition uses the refers to ^ as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-binary-bitwise-operators">ES2015 12.11 (Binary Bitwise Operators)</a>.
</p>
<p>
This operation exists only on integer and boolean SIMD types.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, ^).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-or">
<h1><span class="secnum">5.2.24</span><var>SIMD</var>Constructor.or(a, b)</h1>
<p>
This definition uses the refers to | as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-binary-bitwise-operators">ES2015 12.11 (Binary Bitwise Operators)</a>.
</p>
<p>
This operation exists only on integer and boolean SIMD types.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, |).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-not">
<h1><span class="secnum">5.2.25</span><var>SIMD</var>Constructor.not(a)</h1>
<p>
This definition uses the refers to ~ as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-bitwise-not-operator">ES2015 12.5.11</a> (Bitwise NOT Operator ( ~ )).
</p>
<p>
This operation exists only on integer and boolean SIMD types.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-scalar">SIMDUnaryOp</a>(<var>a</var>, ~).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-less-than">
<h1><span class="secnum">5.2.26</span><var>SIMD</var>Constructor.lessThan(a, b)</h1>
<p>
This definition uses the refers to &lt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, &lt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-less-than-or-equal">
<h1><span class="secnum">5.2.27</span><var>SIMD</var>Constructor.lessThanOrEqual(a, b)</h1>
<p>
This definition uses the refers to &lt;= as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, &lt;=).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-greater-than">
<h1><span class="secnum">5.2.28</span><var>SIMD</var>Constructor.greaterThan(a, b)</h1>
<p>
This definition uses the refers to &gt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, &gt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-greater-than-or-equal">
<h1><span class="secnum">5.2.29</span><var>SIMD</var>Constructor.greaterThanOrEqual(a, b)</h1>
<p>
This definition uses the refers to &gt;= as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, &gt;=).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-unsigned-less-than">
<h1><span class="secnum">5.2.30</span><var>SIMD</var>Constructor.unsignedLessThan(a, b)</h1>
<p>
This definition uses the refers to &lt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<p>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-unsigned-boolean-op">SIMDUnsignedBooleanOp</a>(<var>a</var>, <var>b</var>, &lt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-unsigned-less-than-or-equal">
<h1><span class="secnum">5.2.31</span><var>SIMD</var>Constructor.unsignedLessThanOrEqual(a, b)</h1>
<p>
This definition uses the refers to &lt;= as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<p>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-unsigned-boolean-op">SIMDUnsignedBooleanOp</a>(<var>a</var>, <var>b</var>, &lt;=).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-unsigned-greater-than">
<h1><span class="secnum">5.2.32</span><var>SIMD</var>Constructor.unsignedGreaterThan(a, b)</h1>
<p>
This definition uses the refers to &gt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<p>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-unsigned-boolean-op">SIMDUnsignedBooleanOp</a>(<var>a</var>, <var>b</var>, &gt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-greater-than-or-equal">
<h1><span class="secnum">5.2.33</span><var>SIMD</var>Constructor.unsignedGreaterThanOrEqual(a, b)</h1>
<p>
This definition uses the refers to &gt;= as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-relational-comparison">ES2015 7.2.11 (Abstract Relational Comparison)</a>.
</p>
<p>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, &gt;=).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Does abstract relational comparison correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-equal">
<h1><span class="secnum">5.2.34</span><var>SIMD</var>Constructor.equal(a, b)</h1>
<p>
This definition uses the refers to === as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-equality-comparison">ES2015 7.2.13 (Strict Equality Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, ===).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>The polyfill uses ==. Does this behavior on NaN, +0, -0 correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-not-equal">
<h1><span class="secnum">5.2.35</span><var>SIMD</var>Constructor.notEqual(a, b)</h1>
<p>
This definition uses the refers to !== as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-equality-comparison">ES2015 7.2.13 (Strict Equality Comparison)</a>.
</p>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-boolean-op">SIMDBooleanOp</a>(<var>a</var>, <var>b</var>, !==).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>The polyfill uses ==. Does this behavior on NaN, +0, -0 correspond to what hardware accelerates?</emu-note>
</emu-clause>
<emu-clause id="simd-any-true">
<h1><span class="secnum">5.2.36</span><var>SIMD</var>Constructor.anyTrue(a)</h1>
This is defined on boolean SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>If <var>a</var>.[[SIMDElements]][<var>i</var>] is <emu-const>true</emu-const>, return <emu-const>true</emu-const>.</li>
</ol>
</li>
<li>Return <emu-const>false</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-all-true">
<h1><span class="secnum">5.2.37</span><var>SIMD</var>Constructor.allTrue(a)</h1>
This is defined on boolean SIMD types.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>If <var>a</var>.[[SIMDElements]][<var>i</var>] is <emu-const>false</emu-const>, return <emu-const>false</emu-const>.</li>
</ol>
</li>
<li>Return <emu-const>true</emu-const>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-select">
<h1><span class="secnum">5.2.38</span><var>SIMD</var>Constructor.select( selector, a, b )</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>outputDescriptor</var> be <a href="#simd-int-type">SIMDBoolType</a>(<var>SIMD</var>Descriptor).</li>
<li>If <var>selector</var>.[[SIMDTypeDescriptor]] is not <var>outputDescriptor</var>, throw a TypeError.</li>
<li>Let <var>list</var> be a new List.</li>
<li>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>If <var>sector</var>.[[SIMDElements]][<var>i</var>] is <emu-const>true</emu-const>, let <var>list</var>[<var>i</var>] be <var>a</var>.[[SIMDElements]][<var>i</var>].</li>
<li>Otherwise, let <var>list</var>[<var>i</var>] be <var>b</var>.[[SIMDElements]][<var>i</var>].</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="saturate" aoid="Saturate">
<h1><span class="secnum">5.2.39</span>Saturate( byteWidth, x )</h1>
<emu-alg><ol>
<li>Let <var>max</var> be 1 &lt;&lt; (<var>byteWidth</var> * 8 - 1).</li>
<li>Let <var>z</var> be <var>x</var> + <var>y</var>.</li>
<li>If <var>z</var> &gt;= <var>max</var>, let <var>z</var> be <var>max</var> - 1.</li>
<li>Otherwise, if <var>z</var> &lt; -<var>max</var>, let <var>z</var> be -<var>max</var>.</li>
<li>Return <var>z</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="add-saturate" aoid="AddSaturate">
<h1><span class="secnum">5.2.40</span>AddSaturate( byteWidth )( x, y )</h1>
<emu-alg><ol>
<li>Return <a href="#saturate">Saturate</a>(<var>byteWidth</var>, <var>x</var> + <var>y</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-add-saturate">
<h1><span class="secnum">5.2.41</span><var>SIMD</var>Constructor.addSaturate( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <a href="#add-saturate">AddSaturate</a>(<var>a</var>.[[SIMDTypeDescriptor]].[[SIMDElementSize]])).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="sub-saturate" aoid="SubSaturate">
<h1><span class="secnum">5.2.42</span>SubSaturate( byteWidth )( x, y )</h1>
<emu-alg><ol>
<li>Return <a href="#saturate">Saturate</a>(<var>byteWidth</var>, <var>x</var> - <var>y</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-sub-saturate">
<h1><span class="secnum">5.2.43</span><var>SIMD</var>Constructor.subSaturate( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <a href="#sub-saturate">SubSaturate</a>(<var>a</var>.[[SIMDTypeDescriptor]].[[SIMDElementSize]])).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="unsigned-saturate" aoid="UnsignedSaturate">
<h1><span class="secnum">5.2.44</span>UnsignedSaturate( byteWidth, x )</h1>
<emu-alg><ol>
<li>Let <var>max</var> be 1 &lt;&lt; <var>byteWidth</var> * 8.</li>
<li>Let <var>z</var> be <var>x</var> + <var>y</var>.</li>
<li>If <var>z</var> &gt;= <var>max</var>, let <var>z</var> be <var>max</var> - 1.</li>
<li>Otherwise, if <var>z</var> &lt; 0, let <var>z</var> be 0.</li>
<li>Return <var>z</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="unsigned-add-saturate" aoid="UnsignedAddSaturate">
<h1><span class="secnum">5.2.45</span>UnsignedAddSaturate( byteWidth )( x, y )</h1>
<emu-alg><ol>
<li>Return <a href="#unsigned-saturate">UnsignedSaturate</a>(<var>byteWidth</var>, <var>x</var> + <var>y</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-add-saturate">
<h1><span class="secnum">5.2.46</span><var>SIMD</var>Constructor.unsignedAddSaturate( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <a href="#unsigned-add-saturate">UnsignedAddSaturate</a>(<var>a</var>.[[SIMDTypeDescriptor]].[[SIMDElementSize]])).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="unsigned-sub-saturate" aoid="UnsignedSubSaturate">
<h1><span class="secnum">5.2.47</span>UnsignedSubSaturate( byteWidth )( x, y )</h1>
<emu-alg><ol>
<li>Return <a href="#unsigned-saturate">UnsignedSaturate</a>(<var>byteWidth</var>, <var>x</var> - <var>y</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-sub-saturate">
<h1><span class="secnum">5.2.48</span><var>SIMD</var>Constructor.unsignedSubSaturate( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, <a href="#unsigned-sub-saturate">UnsignedSubSaturate</a>(<var>a</var>.[[SIMDTypeDescriptor]].[[SIMDElementSize]])).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-shift-left-by-scalar">
<h1><span class="secnum">5.2.49</span><var>SIMD</var>Constructor.shiftLeftByScalar( a, scalar )</h1>
This operation is only defined on integer SIMD types. This definition uses the refers to &lt;&lt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-left-shift-operator">ES2015 12.8.3 (The Left Shift Operator ( &lt;&lt; ))</a>.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint32">ToUint32</a>(<var>scalar</var>) does not equal <var>scalar</var>, throw a TypeError.</li>
<li>If <var>scalar</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 8, then
<ol>
<li>Let <var>list</var> be a list of length <var>SIMD</var>Descriptor.[[SIMDLength]], filled with 0.</li>
<li>return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, <var>list</var>).</li>
</ol>
</li>
<li>Let <var>result</var> be SIMDScalarOp(<var>a</var>, <var>scalar</var>, &lt;&lt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Unlike ECMAScript scalar shift, there is no "wrap-around" behavior.</emu-note>
</emu-clause>
<emu-clause id="simd-shift-right-logical-by-scalar">
<h1><span class="secnum">5.2.50</span><var>SIMD</var>Constructor.shiftRightLogicalByScalar( a, scalar )</h1>
This operation is only defined on integer SIMD types. This definition uses the refers to &gt;&gt;&gt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-unsigned-right-shift-operator">ES2015 12.8.5 (The Unsigned Right Shift Operator ( &gt;&gt;&gt; ))</a>.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint32">ToUint32</a>(<var>scalar</var>) does not equal <var>scalar</var>, throw a TypeError.</li>
<li>If <var>scalar</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 8, then
<ol>
<li>Let <var>list</var> be a list of length <var>SIMD</var>Descriptor.[[SIMDLength]], filled with 0.</li>
<li>return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, <var>list</var>).</li>
</ol>
</li>
<li>Let <var>result</var> be SIMDScalarOp(<var>a</var>, <var>scalar</var>, &gt;&gt;&gt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Unlike ECMAScript scalar shift, there is no "wrap-around" behavior.</emu-note>
</emu-clause>
<emu-clause id="simd-shift-right-arithmetic-by-scalar">
<h1><span class="secnum">5.2.51</span><var>SIMD</var>Constructor.shiftRightArithmeticByScalar( a, scalar )</h1>
This operation is only defined on integer SIMD types. This definition uses the refers to &gt;&gt; as defined by <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-signed-right-shift-operator">ES2015 12.8.4 (The Signed Right Shift Operator ( &gt;&gt; ))</a>.
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint32">ToUint32</a>(<var>scalar</var>) does not equal <var>scalar</var>, throw a TypeError.</li>
<li>If <var>scalar</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 8, then
<ol>
<li>Let <var>list</var> be a list of length <var>SIMD</var>Descriptor.[[SIMDLength]], filled with 0.</li>
<li>return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, <var>list</var>).</li>
</ol>
</li>
<li>Let <var>result</var> be SIMDScalarOp(<var>a</var>, <var>scalar</var>, &gt;&gt;).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>Unlike ECMAScript scalar shift, there is no "wrap-around" behavior.</emu-note>
</emu-clause>
<emu-clause id="simd-unsigned-horizontal-sum">
<h1><span class="secnum">5.2.52</span><var>SIMD</var>Constructor.unsignedHorizontalSum( a )</h1>
This operation is only defined on integer SIMD types.
<emu-note><span class="note">Note</span>This operation is still under discussion. See <a href="https://github.com/johnmccutchan/ecmascript_simd/issues/135">this bug thread</a>.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>sum</var> be 0.</li>
<li>For <var>i</var> from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>Let <var>sum</var> be <var>sum</var> + UnsignedValue(<var>a</var>.[[SIMDElements]][<var>i</var>], <var>SIMD</var>Descriptor).</li>
</ol>
</li>
<li>Return <var>sum</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="absolute-difference" aoid="AbsoluteDifference">
<h1><span class="secnum">5.2.53</span>AbsoluteDifference( a, b )</h1>
<emu-alg><ol>
<li>Return <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args">Call</a>(%Math_abs%, %Math%, «<var>a</var> - <var>b</var>»).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-absolte-difference">
<h1><span class="secnum">5.2.54</span><var>SIMD</var>Constructor.unsignedAbsoluteDifference( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-note><span class="note">Note</span>This operation is still under discussion. See <a href="https://github.com/johnmccutchan/ecmascript_simd/issues/135">this bug thread</a>.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>result</var> be <a href="#simd-binary">SIMDBinaryOp</a>(<var>a</var>, <var>b</var>, AbsoluteDifference).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>result</var>).</li>
<li>Return <var>result</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-widened-absolute-difference">
<h1><span class="secnum">5.2.55</span><var>SIMD</var>Constructor.widenedUnsignedAbsoluteDifference( a, b )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-note><span class="note">Note</span>This operation is still under discussion. See <a href="https://github.com/johnmccutchan/ecmascript_simd/issues/135">this bug thread</a>. To use this operation and get at the upper half of a vector, a shuffle is required.</emu-note>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor or <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>SIMD</var>Descriptor is <code>Int8x16</code>, then let <var>outputDescriptor</var> be <code>Int16x8</code>.</li>
<li>Else, Assert <var>SIMD</var>Descriptor is <code>Int16x8</code>; let <var>outputDescriptor</var> be <code>Int32x4</code>.</li>
<li>Let <var>list</var> be a new List of length <var>descriptor</var>.[[SIMDLength]].</li>
<li>For <var>i</var> from 0 to <var>outputDescriptor</var>.[[SIMDLength]],
<ol>
<li>Let <var>ax</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>i</var>).</li>
<li>Let <var>bx</var> = <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>b</var>, <var>i</var>).</li>
<li>Let <var>res</var> = <a href="#absolute-difference">AbsoluteDifference</a>(<var>ax</var>, <var>bx</var>).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>res</var>).</li>
<li>Set <var>list</var>[<var>i</var>] to <var>res</var>.</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>outputDescriptor</var>, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-extract-lane">
<h1><span class="secnum">5.2.56</span><var>SIMD</var>Constructor.extractLane( simd, field )</h1>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Return <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>simd</var>, <var>field</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-unsigned-extract-lane">
<h1><span class="secnum">5.2.57</span><var>SIMD</var>Constructor.unsignedExtractLane( simd, field )</h1>
This operation is only defined on integer SIMD types whose <var>SIMD</var>Descriptor.[[SIMDElementSize]] &lt;= 2.
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>value</var> <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>simd</var>, <var>field</var>).</li>
<li>Return UnsignedValue(<var>value</var>, <var>descriptor</var>).</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>No unsignedReplaceLane or unsigned constructor is needed because replaceLane's implicit cast will handle unsigned elements.</emu-note>
</emu-clause>
<emu-clause id="simd-replace-lane">
<h1><span class="secnum">5.2.58</span><var>SIMD</var>Constructor.replaceLane(simd, field, value)</h1>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>Return <a href="#simd-abstract-replace-lane">SIMDReplaceLane</a>(<var>simd</var>, <var>field</var>, <var>value</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-store-function">
<h1><span class="secnum">5.2.59</span><var>SIMD</var>Constructor.store(tarray, index, simd)</h1>
This is defined when <var>SIMD</var>Descriptor has a [[SIMDSerializeElement]] internal slot.
<emu-note><span class="note">Note</span>The first seven steps of the following <code>store</code>/<code>load</code> functions are very similar. A refactoring could reduce the spec size.</emu-note>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * <var>SIMD</var>Descriptor.[[SIMDLength]] &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li><a href="#simd-store">SIMDStore</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, <var>simd</var>).</li>
<li>Return <var>simd</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-store1">
<h1><span class="secnum">5.2.60</span><var>SIMD</var>Constructor.store1(tarray, index, simd)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4, and when <var>SIMD</var>Descriptor has a [[SIMDSerializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li><a href="#simd-store">SIMDStore</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, <var>simd</var>, 1).</li>
<li>Return <var>simd</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-store2">
<h1><span class="secnum">5.2.61</span><var>SIMD</var>Constructor.store2(tarray, index, simd)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4, and when <var>SIMD</var>Descriptor has a [[SIMDSerializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 2 &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li><a href="#simd-store">SIMDStore</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, <var>simd</var>, 2).</li>
<li>Return <var>simd</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-store3">
<h1><span class="secnum">5.2.62</span><var>SIMD</var>Constructor.store3(tarray, index)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4, and when <var>SIMD</var>Descriptor has a [[SIMDSerializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>simd</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a TypeError.</li>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 3 &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li><a href="#simd-store">SIMDStore</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, 3).</li>
<li>Return <var>simd</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-load-function">
<h1><span class="secnum">5.2.63</span><var>SIMD</var>Constructor.load(tarray, index)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor has a [[SIMDDeserializeElement]] internal slot.
<emu-note><span class="note">Note</span><code>load</code> takes a TypedArray of any element type as an argument. One way to use it is to pass in a <code>Uint8Array</code> regardless of SIMD type, which is useful because it allows the compiler to eliminate the shift in going from the index to the pointer offset. Other options considered were to use an ArrayBuffer (but this is not idiomatic, to take an ArrayBuffer directly as an argument to read off of) or a DataView (but DataViews don't tend to expose platform-dependent endianness, which is important here, and they tend to use methods on <code>DataView.prototype</code>, which are harder to optimize in an asm.js context).</emu-note>
<emu-alg><ol>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / <var>tarray</var>.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * <var>SIMD</var>Descriptor.[[SIMDLength]] &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li>Return <a href="#simd-load">SIMDLoad</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-load1">
<h1><span class="secnum">5.2.64</span><var>SIMD</var>Constructor.load1(tarray, index)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4 and <var>SIMD</var>Descriptor has a [[SIMDDeserializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li>Return <a href="#simd-load">SIMDLoad</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, 1).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-load2">
<h1><span class="secnum">5.2.65</span><var>SIMD</var>Constructor.load2(tarray, index)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4 and <var>SIMD</var>Descriptor has a [[SIMDDeserializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 2 &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li>Return <a href="#simd-load">SIMDLoad</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, 2).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-load3">
<h1><span class="secnum">5.2.66</span><var>SIMD</var>Constructor.load3(tarray, index)</h1>
This function is defined only on SIMD types where <var>SIMD</var>Descriptor.[[SIMDLength]] == 4 and <var>SIMD</var>Descriptor has a [[SIMDDeserializeElement]] internal slot.
<emu-note><span class="note">Note</span>In this specification, that set consists of Float32x4 and Int32x4.</emu-note>
<emu-alg><ol>
<li>If <var>tarray</var> does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError.</li>
<li>Let <var>block</var> be <var>tarray</var>.[[ViewedArrayBuffer]].[[ArrayBufferData]]</li>
<li>If <var>index</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>index</var>), throw a TypeError.</li>
<li>Let <var>elementLength</var> be <var>tarray</var>.[[ByteLength]] / _tarray.[[ArrayLength]].</li>
<li>Let <var>byteIndex</var> be <var>index</var> * <var>elementLength</var>.</li>
<li>If <var>byteIndex</var> + <var>SIMD</var>Descriptor.[[SIMDElementSize]] * 3 &gt; <var>tarray</var>.[[ByteLength]] or <var>byteIndex</var> &lt; 0, throw a RangeError.</li>
<li>Return <a href="#simd-load">SIMDLoad</a>(<var>block</var>, <var>SIMD</var>Descriptor, <var>byteIndex</var>, 3).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-to-timd">
<h1><span class="secnum">5.2.67</span><var>SIMD</var>Constructor.from<var>TIMD</var>Bits( value )</h1>
In this definition, <var>TIMD</var> ranges over all SIMD types for which <var>SIMD</var>Descriptor.[[SIMDElementSize]] * <var>SIMD</var>Descriptor.[[SIMDLength]] == <var>TIMD</var>Descriptor.[[SIMDElementSize]] * <var>TIMD</var>Descriptor.[[SIMDLength]].
<emu-note><span class="note">Note</span>All of the SIMD types described in this spec are 16 bytes, so all pairs are included.</emu-note>
<emu-alg><ol>
<li>If <var>value</var>.[[SIMDTypeDescriptor]] is not <var>TIMD</var>Descriptor, throw a TypeError.</li>
<li>Return <a href="#simd-reinterpret-cast">SIMDReinterpretCast</a>(<var>value</var>, <var>SIMD</var>Descriptor).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-to-timd-logical">
<h1><span class="secnum">5.2.68</span><var>SIMD</var>Constructor.from<var>TIMD</var>( value )</h1>
In this definition, <var>TIMD</var> ranges over all SIMD types for which <var>SIMD</var>Descriptor.[[SIMDLength]] == <var>TIMD</var>Descriptor.[[SIMDLength]].
<emu-alg><ol>
<li>If <var>value</var>.[[SIMDTypeDescriptor]] is not <var>TIMD</var>Descriptor, throw a TypeError.</li>
<li>Let <var>list</var> be a copy of <var>value</var>.[[SIMDElements]].</li>
<li>For <var>element</var> in <var>list</var>,
<ol>
<li>If <var>SIMD</var> is an integer type and <var>TIMD</var> is a floating point type, and <var>element</var> is greater than the maximum value or less than the minimum value of <var>SIMD</var>, throw a <emu-const>RangeError</emu-const>.</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="swizzle">
<h1><span class="secnum">5.2.69</span><var>SIMD</var>.swizzle( a, lanes... )</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a <emu-const>TypeError</emu-const>.</li>
<li>If the length of <var>lanes</var> does not equal <var>SIMD</var>Descriptor.[[SIMDLength]], throw a <emu-const>TypeError</emu-const>.</li>
<li>For each <var>lane</var> in <var>lanes</var>:
<ol>
<li>If <var>lane</var> is not a Number, or <var>lane</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>lane</var>), throw a <emu-const>TypeError</emu-const>.</li>
<li>If <var>lane</var> &lt; 0 or <var>lane</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDLength]], throw a <emu-const>RangeError</emu-const>.</li>
</ol>
</li>
<li>Let <var>list</var> be a new List of length <var>SIMD</var>Descriptor.[[SIMDLength]].</li>
<li>For <var>i</var> in from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>Set <var>list</var>[<var>i</var>] to <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>lanes</var>[<var>i</var>])</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="shuffle">
<h1><span class="secnum">5.2.70</span><var>SIMD</var>.shuffle( a, b, lanes... )</h1>
<emu-alg><ol>
<li>If <var>a</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, or if <var>b</var>.[[SIMDTypeDescriptor]] is not <var>SIMD</var>Descriptor, throw a <emu-const>TypeError</emu-const>.</li>
<li>If the length of <var>lanes</var> does not equal <var>SIMD</var>Descriptor.[[SIMDLength]] * 2, throw a <emu-const>TypeError</emu-const>.</li>
<li>For each <var>lane</var> in <var>lanes</var>:
<ol>
<li>If <var>lane</var> is not a Number, or <var>lane</var> != <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32">ToInt32</a>(<var>lane</var>), throw a <emu-const>TypeError</emu-const>.</li>
<li>If <var>lane</var> &lt; 0 or <var>lane</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDLength]] * 2, throw a <emu-const>RangeError</emu-const>.</li>
</ol>
</li>
<li>Let <var>list</var> be a new List of length <var>SIMD</var>Descriptor.[[SIMDLength]].</li>
<li>For <var>i</var> in from 0 to <var>SIMD</var>Descriptor.[[SIMDLength]] - 1,
<ol>
<li>Let <var>idx</var> be <var>lanes</var>[<var>i</var>].</li>
<li>If <var>idx</var> &gt;= <var>SIMD</var>Descriptor.[[SIMDLength]],
<ol>
<li>Set <var>list</var>[<var>i</var>] to <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>b</var>, <var>lanes</var>[<var>i</var>] - <var>SIMD</var>Descriptor.[[SIMDLength]])</li>
</ol>
</li>
<li>Otherwise,
<ol>
<li>Set <var>list</var>[<var>i</var>] to <a href="#simd-abstract-extract-lane">SIMDExtractLane</a>(<var>a</var>, <var>lanes</var>[<var>i</var>])</li>
</ol>
</li>
</ol>
</li>
<li>Return <a href="#simd-create">SIMDCreate</a>(<var>SIMD</var>Descriptor, ...<var>list</var>).</li>
</ol></emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="simd-proto">
<h1><span class="secnum">5.3</span>The <var>SIMD</var>Constructor.prototype</h1>
<emu-note><span class="note">Note</span>
Previously, if accessors like x were included, these would be spec'd as getters (with null setter) on the <var>SIMD</var>Constructor.prototype . However, they have been removed in favor of <var>SIMD</var>Constructor.extractLane. Are there any non-trivial properties? Users could add methods like .add() here if they want to use SIMD in an object-oriented way. It would also be easy to define properties on the prototype that would make SIMD values and wrapper objects array-like.
</emu-note>
<emu-clause id="simd-proto-constructor">
<h1><span class="secnum">5.3.1</span><var>SIMD</var>Constructor.prototype.constructor</h1>
The initial value of <var>SIMD</var>Constructor.prototype.constructor is the intrinsic object %<var>SIMD</var>Constructor%
</emu-clause>
<emu-clause id="simd-prototype-valueof">
<h1><span class="secnum">5.3.2</span><var>SIMD</var>Constructor.prototype.valueOf()</h1>
<emu-alg><ol>
<li>If <emu-const>this</emu-const> does not have a [[SIMDWrapperData]] internal slot, throw a <emu-const>TypeError</emu-const>.</li>
<li>Return <emu-const>this</emu-const>.[[SIMDWrapperData]].</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-prototype-tolocalestring">
<h1><span class="secnum">5.3.3</span><var>SIMD</var>Constructor.prototype.toLocaleString()</h1>
<emu-alg><ol>
<li>If <emu-const>this</emu-const> does not have a [[SIMDWrapperData]] internal slot, throw a <emu-const>TypeError</emu-const>.</li>
<li>Let <var>separator</var> be the String value for the list-separator String appropriate for the host environment’s current locale (this is derived in an implementation-defined way).</li>
<li>Let <var>list</var> be an empty List</li>
<li>For each element <var>element</var> in <var>argument</var>.[[SIMDElements]],
<ol>
<li>Let <var>R</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring">ToString</a>(<a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-invoke">Invoke</a>(<var>element</var>, <code>"toLocaleString"</code>)).</li>
<li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-returnifabrupt">ReturnIfAbrupt</a>(<var>R</var>).</li>
<li>Append <var>R</var> to <var>list</var>.</li>
</ol>
</li>
<li>Let <var>results</var> be an Array containing the contents of <var>list</var>.</li>
<li>Let <var>t</var> be the string <code>"</code><var>SIMD</var><code>"</code>, e.g., <code>"Float32x4"</code>.</li>
<li>Let <var>e</var> be <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args">Call</a>(%ArrayPrototype_join%, <var>results</var>, «<var>separator</var>»).</li>
<li>Return a new String value computed by concatenating the previous value of <var>t</var>, <code>"("</code>, <var>e</var>, and <code>")"</code>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="simd-prototype-tostring">
<h1><span class="secnum">5.3.4</span><var>SIMD</var>Constructor.prototype.toString()</h1>
<emu-alg><ol>
<li>If <emu-const>this</emu-const> does not have a [[SIMDWrapperData]] internal slot, throw a <emu-const>TypeError</emu-const>.</li>
<li>Return <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring">ToString</a>(<emu-const>this</emu-const>.[[SIMDWrapperData]]).</li>
</ol></emu-alg>
<emu-note><span class="note">Note</span>This definition depends on the primitive <var>SIMD</var>Type's behavior under ToString. Alternatively, <var>SIMD</var>Type could have ToString defined by calling ToObject and then reaching this method (or whatever the user overrides it with), in which case the current definition in ToString would be brought down here.</emu-note>
</emu-clause>
<emu-clause>
<h1><span class="secnum">5.3.5</span><var>SIMD</var>Constructor.prototype [ @@toStringTag ]</h1>
<p>
The initial value of the @@toStringTag property is the String value <code>"SIMD.</code><var>SIMD</var><code>"</code>, e.g., <code>"SIMD.Float32x4"</code>.
</p><p>
</p>
This property has the attributes { [[Writable]]: <emu-const>false</emu-const>, [[Enumerable]]: <emu-const>false</emu-const>, [[Configurable]]: <emu-const>true</emu-const> }.
<p></p>
</emu-clause>
</emu-clause>
<emu-clause id="simd-descriptors">
<h1><span class="secnum">5.4</span>SIMD type descriptors</h1>
In the internal algorithms in this section, preceding the first step, if <var>isLittleEndian</var> is not present, set <var>isLittleEndian</var> to either <emu-const>true</emu-const> or <emu-const>false</emu-const>. The choice is implementation dependent and should be the alternative that is most efficient for the implementation. An implementation must use the same value each time one of the following algorithms is executed, and it must be consistent across all algorithms.
<emu-clause id="simd-float32x4">
<h1><span class="secnum">5.4.1</span>Float32x4Descriptor type descriptor</h1>
<p>
The Float32x4Descriptor floating point SIMD type descriptor has the following internal slots:
</p>
<ul>
<li>[[SIMDLength]]: 4</li>
<li>[[SIMDElementSize]]: 4</li>
<li>[[SIMDCastNumber]]: %Math_fround%</li>
<li>[[SIMDSerializeElement]]: SerializeFloat32</li>
<li>[[SIMDDeserializeElement]]: DeserializeFloat32</li>
</ul>
<emu-clause id="serialize-float32" aoid="SerializeFloat32">
<h1><span class="secnum">5.4.1.1</span>SerializeFloat32( block, offset, n, isLittleEndian )</h1>
<emu-note><span class="note">Note</span>Derived from part of <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-setvalueinbuffer">SetValueInBuffer</a>. Note that this specification does not require a particular bit pattern for <emu-const>NaN</emu-const>, and that it does not need to be the same across calls.</emu-note>
<emu-alg><ol>
<li>Assert: <var>block</var> is a Data Block.</li>
<li>Assert: <var>offset</var> is a number.</li>
<li>Assert: <var>n</var> is a number.</li>
<li>Assert: <var>offset</var> + 4 is less than or equal to the size of <var>block</var>.</li>
<li>Set <var>rawBytes</var> to a List containing the 4 bytes that are the result of converting value to IEEE 754-2008 binary32 format using “Round to nearest, ties to even” rounding mode. If <var>isLittleEndian</var> is <emu-const>false</emu-const>, the bytes are arranged in big endian order. Otherwise, the bytes are arranged in little endian order. If value is <emu-const>NaN</emu-const>, <var>rawValue</var> may be set to any implementation chosen <emu-const>NaN</emu-const> encoding. An implementation must always choose the same <emu-const>NaN</emu-const> encoding for a distinct Not-a-Number value.</li>
<li>Store the individual bytes of <var>rawBytes</var> into <var>block</var>, in order, starting at <var>block</var>[<var>offset</var>].</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="deserialize-float32" aoid="DeserializeFloat32">
<h1><span class="secnum">5.4.1.2</span>DeserializeFloat32( block, offset, isLittleEndian )</h1>
<emu-note><span class="note">Note</span>Derived from part of <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-getvaluefrombuffer">GetValueFromBuffer</a>. Note that while this says to return "the <emu-const>NaN</emu-const> value", the binary representation is not observable and canonicalization is not required.</emu-note>
<emu-alg><ol>
<li>Assert: <var>block</var> is a Data Block.</li>
<li>Assert: <var>offset</var> is a number.</li>
<li>Assert: <var>offset</var> + 4 is less than or equal to the size of <var>block</var>.</li>
<li>Let <var>rawValue</var> be a List of 4 containing, in order, the sequence of 4 bytes starting with <var>block</var>[<var>offset</var>].</li>
<li>If <var>isLittleEndian</var> is <emu-const>false</emu-const>, reverse the order of the elements of <var>rawValue</var>.</li>
<li>Let <var>value</var> be the byte elements of rawValue concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2008 binary32 value.</li>
<li>If <var>value</var> is an IEEE 754-2008 binary32 <emu-const>NaN</emu-const> value, return the <emu-const>NaN</emu-const> Number value.</li>
<li>Return the Number value that corresponds to <var>value</var>.</li>
</ol></emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="simd-int32x4">
<h1><span class="secnum">5.4.2</span>Int32x4Descriptor type descriptor</h1>
<p>
The Int32x4Descriptor integer SIMD type descriptor has the following internal slots:
</p>
<ul>
<li>[[SIMDLength]]: 4</li>
<li>[[SIMDElementSize]]: 4</li>
<li>[[SIMDCastNumber]]: ToInt32</li>
<li>[[SIMDSerializeElement]]: SerializeInt32</li>
<li>[[SIMDDeserializeElement]]: DeserializeInt32</li>
</ul>
<emu-clause id="serialize-int" aoid="SerializeInt">
<h1><span class="secnum">5.4.2.1</span>SerializeInt( block, offset, n, isLittleEndian, descriptor )</h1>
<emu-note><span class="note">Note</span>Derived from part of <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-setvalueinbuffer">SetValueInBuffer</a>.</emu-note>
<emu-alg><ol>
<li>Assert: <var>block</var> is a Data Block.</li>
<li>Assert: <var>offset</var> is a number.</li>
<li>Assert: <var>n</var> is a number.</li>
<li>Assert: <var>n</var> == <var>descriptor_.[[SIMDCastNumber]](_n</var>).</li>
<li>Assert: <var>offset</var> + <var>descriptor</var>.[[SIMDElementSize]] is less than or equal to the size of <var>block</var>.</li>
<li>Let <var>rawBytes</var> be a List containing the <var>descriptor</var>.[[SIMDElementSize]]-byte binary 2’s complement encoding of <var>n</var>. If <var>isLittleEndian</var> is <emu-const>false</emu-const>, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.</li>
<li>Store the individual bytes of <var>rawBytes</var> into <var>block</var>, in order, starting at <var>block</var>[<var>offset</var>].</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="deserialize-int32" aoid="DeserializeInt">
<h1><span class="secnum">5.4.2.2</span>DeserializeInt( block, offset, isLittleEndian, descriptor )</h1>
<emu-note><span class="note">Note</span>Derived from part of <a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-getvaluefrombuffer">GetValueFromBuffer</a>.</emu-note>
<emu-alg><ol>
<li>Assert: <var>block</var> is a Data Block.</li>
<li>Assert: <var>offset</var> is a number.</li>
<li>Assert: <var>offset</var> + <var>descriptor</var>.[[SIMDElementSize]] is less than or equal to the size of <var>block</var>.</li>
<li>Let <var>rawValue</var> be a List of <var>descriptor</var>.[[SIMDElementSize]] containing, in order, the sequence of <var>descriptor</var>.[[SIMDElementSize]] bytes starting with <var>block</var>[<var>offset</var>].</li>
<li>If <var>isLittleEndian</var> is <emu-const>false</emu-const>, reverse the order of the elements of <var>rawValue</var>.</li>
<li>Let <var>intValue</var> be the byte elements of <var>rawValue</var> concatenated and interpreted as a bit string encoding of a binary little-endian 2’s complement number of bit length <var>descriptor</var>.[[SIMDElementSize]] × 8.</li>
<li>Return the Number value that corresponds to <var>intValue</var>.</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="serialize-int32" aoid="SerializeInt32">
<h1><span class="secnum">5.4.2.3</span>SerializeInt32( block, offset, n, isLittleEndian )</h1>
<emu-alg><ol>
<li><a href="#serialize-int">SerializeInt</a>( block, offset, n, isLittleEndian, Int32x4Descriptor ).</li>
</ol></emu-alg>
</emu-clause>
<emu-clause id="deserialize-int32" aoid="DeserializeInt32">
<h1><span class="secnum">5.4.2.4</span>DeserializeInt32( block, offset, isLittleEndian )</h1>
<emu-alg><ol>
<li>Return <a href="#deserialize-int32">DeserializeInt</a>( block, offset, isLittleEndian, Int32x4Descriptor).</li>
</ol></emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="simd-int16x8">
<h1><span class="secnum">5.4.3</span>Int16x8Descriptor type descriptor</h1>
<p>
The Int16x8Descriptor integer SIMD type descriptor has the following internal slots:
</p>
<ul>
<li>[[SIMDLength]]: 8</li>
<li>[[SIMDElementSize]]: 2</li>
<li>[[SIMDCastNumber]]: ToInt16</li>
<li>[[SIMDSerializeElement]]: SerializeInt16</li>
<li>[[SIMDDeserializeElement]]: DeserializeInt16</li>
</ul>
<emu-clause id="serialize-int16" aoid="SerializeInt16">
<h1><span class="secnum">5.4.3.1</span>SerializeInt16( block, offset, n, isLittleEndian )</h1>
<emu-alg><ol>
<li><a href="#serialize-int">SerializeInt</a>( block, offset, n, isLittleEndian, Int16x8Descriptor ).</li>
</ol></emu-alg>
</emu-clause>