Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Array by copy #537

Merged
merged 15 commits into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,26 @@ export interface Float16Array {
*/
subarray(begin?: number, end?: number): Float16Array;

/**
* Copies the array and returns the copy with the elements in reverse order.
*/
toReversed(): Float16Array;

/**
* Copies and sorts the array.
* @param compareFn Function used to determine the order of the elements. It is expected to return
* a negative value if first argument is less than second argument, zero if they're equal and a positive
* value otherwise. If omitted, the elements are sorted in ascending.
*/
toSorted(compareFn?: (a: number, b: number) => number): Float16Array;

/**
* Copies the array and replaces the element at the given index with the provided value.
* @param index The zero-based location in the array for which to replace an element.
* @param value Element to insert into the array in place of the replaced element.
*/
with(index: number, value: number): Float16Array;

/**
* Converts a number to a string by using the current locale.
*/
Expand Down
87 changes: 87 additions & 0 deletions src/Float16Array.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
OFFSET_IS_OUT_OF_BOUNDS,
REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE,
SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT,
THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED,
THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY,
THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT,
} from "./_util/messages.mjs";
Expand Down Expand Up @@ -524,6 +525,39 @@ export class Float16Array {
return convertToNumber(float16bitsArray[k]);
}

/** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with */
with(index, value) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);

const length = TypedArrayPrototypeGetLength(float16bitsArray);
const relativeIndex = ToIntegerOrInfinity(index);
const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex;

const number = +value;

if (k < 0 || k >= length) {
throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);
}

// don't use SpeciesConstructor
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);
const array = getFloat16BitsArray(cloned);

array[k] = roundToFloat16Bits(number);

return cloned;
}

/** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.map */
map(callback, ...opts) {
assertFloat16Array(this);
Expand Down Expand Up @@ -839,6 +873,29 @@ export class Float16Array {
return this;
}

/** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed */
toReversed() {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);

// don't use SpeciesConstructor
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);

const clonedFloat16bitsArray = getFloat16BitsArray(cloned);
TypedArrayPrototypeReverse(clonedFloat16bitsArray);

return cloned;
}

/** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill */
fill(value, ...opts) {
assertFloat16Array(this);
Expand Down Expand Up @@ -876,6 +933,36 @@ export class Float16Array {
return this;
}

/** @see https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSorted */
toSorted(compareFn) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);

if (compareFn !== undefined && typeof compareFn !== "function") {
throw new NativeTypeError(THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED);
}
const sortCompare = compareFn !== undefined ? compareFn : defaultCompare;

// don't use SpeciesConstructor
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);

const clonedFloat16bitsArray = getFloat16BitsArray(cloned);
TypedArrayPrototypeSort(clonedFloat16bitsArray, (x, y) => {
return sortCompare(convertToNumber(x), convertToNumber(y));
});

return cloned;
}

/** @see https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice */
slice(start, end) {
assertFloat16Array(this);
Expand Down
2 changes: 2 additions & 0 deletions src/_util/messages.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ export const CANNOT_MIX_BIGINT_AND_OTHER_TYPES =
export const ITERATOR_PROPERTY_IS_NOT_CALLABLE = "@@iterator property is not callable";
export const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE =
"Reduce of empty array with no initial value";
export const THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED =
"The comparison function must be either a function or undefined";
export const OFFSET_IS_OUT_OF_BOUNDS = "Offset is out of bounds";
147 changes: 146 additions & 1 deletion test/Float16Array.js
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,60 @@ describe("Float16Array", () => {
});
});

describe("#with()", () => {
it("property `name` is 'with'", () => {
assert(Float16Array.prototype.with.name === "with");
});

it("property `length` is 1", () => {
assert(Float16Array.prototype.with.length === 2);
});

it("with", () => {
const float16_1 = new Float16Array([1, 2, 3]);
const float16_2 = float16_1.with(1, 4);

assert(float16_1.buffer !== float16_2.buffer);
assert.equalFloat16ArrayValues(float16_1, [1, 2, 3]);
assert.equalFloat16ArrayValues(float16_2, [1, 4, 3]);

const float16_3 = float16_1.with(-1, 4);

assert(float16_1.buffer !== float16_3.buffer);
assert.equalFloat16ArrayValues(float16_1, [1, 2, 3]);
assert.equalFloat16ArrayValues(float16_3, [1, 2, 4]);

const float16_4 = float16_1.with(0, "aaa");

assert(float16_1.buffer !== float16_4.buffer);
assert.equalFloat16ArrayValues(float16_1, [1, 2, 3]);
assert.equalFloat16ArrayValues(float16_4, [NaN, 2, 3]);
});

it("throw Error with invalid index", () => {
const float16 = new Float16Array([1, 2, 3]);

// out of range
assert.throws(() => {
float16.with(5, 0);
}, RangeError);
assert.throws(() => {
float16.with(-5, 0);
}, RangeError);

assert.throws(() => {
float16.with(Symbol(), 0);
}, TypeError);

// Safari 13 doesn't have BigInt
if (typeof BigInt !== "undefined") {
assert.throws(() => {
float16.with(BigInt(0), 0);
}, TypeError);
}
});
});

describe("#map()", () => {
it("property `name` is 'map'", () => {
assert(Float16Array.prototype.map.name === "map");
Expand Down Expand Up @@ -1436,6 +1490,25 @@ describe("Float16Array", () => {
});
});

describe("#toReversed()", () => {
it("property `name` is 'reverse'", () => {
assert(Float16Array.prototype.toReversed.name === "toReversed");
});

it("property `length` is 0", () => {
assert(Float16Array.prototype.toReversed.length === 0);
});

it("toReversed", () => {
const float16_1 = new Float16Array([1, 2, 3]);
const float16_2 = float16_1.toReversed();

assert(float16_1.buffer !== float16_2.buffer);
assert.equalFloat16ArrayValues(float16_1, [1, 2, 3]);
assert.equalFloat16ArrayValues(float16_2, [3, 2, 1]);
});
});

describe("#fill()", () => {
it("property `name` is 'fill'", () => {
assert(Float16Array.prototype.fill.name === "fill");
Expand Down Expand Up @@ -1526,14 +1599,86 @@ describe("Float16Array", () => {
it("check custom compare", () => {
const float16 = new Float16Array([1, 2, -1, -2, Infinity, -Infinity]);

assert(float16.sort((x, y) => x - y) === float16);
assert(float16.sort((x, y) => y - x) === float16);
assert.equalFloat16ArrayValues(float16, [
Infinity,
2,
1,
-1,
-2,
-Infinity,
]);
});
});

describe("#toSorted()", () => {
it("property `name` is 'toSorted'", () => {
assert(Float16Array.prototype.toSorted.name === "toSorted");
});

it("property `length` is 1", () => {
assert(Float16Array.prototype.toSorted.length === 1);
});

it("check default compare", () => {
const float16_1 = new Float16Array([
1,
2,
-1,
-2,
0,
-0,
NaN,
Infinity,
-Infinity,
]);
const float16_2 = float16_1.toSorted();

assert(float16_1.buffer !== float16_2.buffer);
assert.equalFloat16ArrayValues(float16_1, [
1,
2,
-1,
-2,
0,
-0,
NaN,
Infinity,
-Infinity,
]);
assert.equalFloat16ArrayValues(float16_2, [
-Infinity,
-2,
-1,
-0,
0,
1,
2,
Infinity,
NaN,
]);
});

it("check custom compare", () => {
const float16_1 = new Float16Array([1, 2, -1, -2, Infinity, -Infinity]);
const float16_2 = float16_1.toSorted((x, y) => y - x);

assert(float16_1.buffer !== float16_2.buffer);
assert.equalFloat16ArrayValues(float16_1, [
1,
2,
-1,
-2,
Infinity,
-Infinity,
]);
assert.equalFloat16ArrayValues(float16_2, [
Infinity,
2,
1,
-1,
-2,
-Infinity,
]);
});
});
Expand Down