Skip to content

Commit 510c9a2

Browse files
✨ feat: Add swap and swapRanges.
1 parent a501caf commit 510c9a2

File tree

11 files changed

+9658
-24
lines changed

11 files changed

+9658
-24
lines changed

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44
ArrayLike value swapping for JavaScript.
55
See [docs](https://array-like.github.io/swap/index.html).
66

7-
> :building_construction: Caveat emptor! This is work in progress. Code may be
8-
> working. Documentation may be present. Coherence may be. Maybe.
7+
```js
8+
import {swapRanges} from '@array-like/swap';
9+
import {alloc} from '@array-like/alloc';
10+
import {iota} from '@array-like/iota';
911

10-
> :warning: Depending on your environment, the code may require
11-
> `regeneratorRuntime` to be defined, for instance by importing
12-
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
12+
const n = 6;
13+
const a = alloc(n);
14+
iota(a, 0, n, 0);
15+
const b = alloc(n);
16+
iota(b, 0, n, 0);
17+
18+
swapRanges(a, 0, 3, b, 3);
19+
a; // 3 4 5 3 4 5
20+
b; // 0 1 2 0 1 2
21+
```
1322

1423
[![License](https://img.shields.io/github/license/array-like/swap.svg)](https://raw.githubusercontent.com/array-like/swap/main/LICENSE)
1524
[![Version](https://img.shields.io/npm/v/@array-like/swap.svg)](https://www.npmjs.org/package/@array-like/swap)

doc/manual/usage.md

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
# Usage
22

3-
> :warning: Depending on your environment, the code may require
4-
> `regeneratorRuntime` to be defined, for instance by importing
5-
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
6-
7-
First, require the polyfill at the entry point of your application
8-
```js
9-
await import('regenerator-runtime/runtime.js');
10-
// or
11-
import 'regenerator-runtime/runtime.js';
12-
```
13-
14-
Then, import the library where needed
3+
Import the library where needed
154
```js
165
const swap = await import('@array-like/swap');
176
// or

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@
6161
},
6262
"dependencies": {},
6363
"devDependencies": {
64+
"@array-like/alloc": "^0.0.1",
6465
"@babel/core": "7.14.8",
6566
"@babel/preset-env": "7.14.8",
6667
"@babel/register": "7.14.5",
6768
"@commitlint/cli": "13.1.0",
6869
"@js-library/commitlint-config": "0.0.4",
70+
"@randomized/random": "^4.0.0",
6971
"ava": "3.15.0",
7072
"babel-plugin-transform-remove-console": "6.9.4",
7173
"babel-plugin-unassert": "3.1.0",

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const answer = 42;
2-
export default answer;
1+
export {default as swap} from './swap.js';
2+
export {default as swapRanges} from './swapRanges.js';

src/swap.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Swap.
3+
*
4+
* @param {{[x: number]: any}} a
5+
* @param {number} i
6+
* @param {number} j
7+
*/
8+
const swap = (a, i, j) => {
9+
const ai = a[i];
10+
a[i] = a[j];
11+
a[j] = ai;
12+
};
13+
14+
export default swap;

src/swapRanges.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* SwapRanges.
3+
*
4+
* @param {{[x: number]: any}} a
5+
* @param {number} ai
6+
* @param {number} aj
7+
* @param {{[x: number]: any}} b
8+
* @param {number} bi
9+
*/
10+
const swapRanges = (a, ai, aj, b, bi) => {
11+
for (; ai < aj; ++ai, ++bi) {
12+
const temporary = a[ai];
13+
a[ai] = b[bi];
14+
b[bi] = temporary;
15+
}
16+
};
17+
18+
export default swapRanges;

test/src/_fixtures.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const arrayTypes = [
2+
Array,
3+
Int8Array,
4+
Int16Array,
5+
Int32Array,
6+
Uint8Array,
7+
Uint16Array,
8+
Uint32Array,
9+
Uint8ClampedArray,
10+
Float32Array,
11+
Float64Array,
12+
];

test/src/api.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/src/swap.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import test from 'ava';
2+
3+
import {_calloc} from '@array-like/alloc';
4+
import {randint} from '@randomized/random';
5+
6+
import {swap} from '../../src/index.js';
7+
8+
import {arrayTypes} from './_fixtures.js';
9+
10+
const macro = (t, Constructor) => {
11+
const calloc = _calloc(Constructor);
12+
13+
const n = 100;
14+
const ai = 23;
15+
const aj = 73;
16+
17+
const a = calloc(n);
18+
const b = calloc(n);
19+
20+
for (let i = 0; i < n; ++i) {
21+
a[i] = randint(1, 2 ** 31);
22+
b[i] = a[i];
23+
}
24+
25+
swap(a, ai, aj);
26+
27+
for (let i = 0; i < n; ++i) {
28+
if (i === ai || i === aj) {
29+
const j = ai + aj - i;
30+
t.deepEqual(a[i], b[j], `a[${i}] === b[${j}]`);
31+
} else {
32+
t.deepEqual(a[i], b[i], `a[${i}] === b[${i}]`);
33+
}
34+
}
35+
36+
swap(a, ai, aj);
37+
38+
t.deepEqual(a, b, 'swap back');
39+
40+
swap(a, ai, ai);
41+
42+
t.deepEqual(a, b, 'swap');
43+
};
44+
45+
macro.title = (title, Constructor) => title ?? Constructor.name;
46+
47+
for (const arrayType of arrayTypes) test(macro, arrayType);

test/src/swapRanges.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import test from 'ava';
2+
3+
import {_calloc} from '@array-like/alloc';
4+
import {randint} from '@randomized/random';
5+
6+
import {swapRanges} from '../../src/index.js';
7+
8+
import {arrayTypes} from './_fixtures.js';
9+
10+
const macro = (t, Constructor) => {
11+
const calloc = _calloc(Constructor);
12+
13+
const n = 100;
14+
const ai = 23;
15+
const aj = 73;
16+
const bi = 49;
17+
18+
const a = calloc(n);
19+
const b = calloc(n);
20+
const c = calloc(n);
21+
const d = calloc(n);
22+
23+
for (let i = 0; i < n; ++i) {
24+
a[i] = randint(1, 2 ** 31);
25+
b[i] = randint(1, 2 ** 31);
26+
c[i] = a[i];
27+
d[i] = b[i];
28+
}
29+
30+
swapRanges(a, ai, aj, b, bi);
31+
32+
for (let i = 0; i < n; ++i) {
33+
if (i < ai || i >= aj) {
34+
t.deepEqual(a[i], c[i], `a[${i}] === c[${i}]`);
35+
} else {
36+
const j = i - ai + bi;
37+
t.deepEqual(a[i], d[j], `a[${i}] === d[${j}]`);
38+
}
39+
40+
if (i < bi || i >= bi + aj - ai) {
41+
t.deepEqual(b[i], d[i], `b[${i}] === d[${i}]`);
42+
} else {
43+
const j = i - bi + ai;
44+
t.deepEqual(b[i], c[j], `b[${i}] === c[${j}]`);
45+
}
46+
}
47+
48+
swapRanges(a, ai, aj, b, bi);
49+
50+
t.deepEqual(a, c, 'swapranges back check a');
51+
t.deepEqual(b, d, 'swapranges back check b');
52+
53+
swapRanges(a, ai, aj, a, ai);
54+
55+
t.deepEqual(a, c, 'swapranges self check a');
56+
};
57+
58+
macro.title = (title, Constructor) => title ?? Constructor.name;
59+
60+
for (const arrayType of arrayTypes) test(macro, arrayType);

0 commit comments

Comments
 (0)