@thi.ng/soa 0.4.86 → 0.4.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-03T12:13:31Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/aos.js CHANGED
@@ -2,64 +2,31 @@ import { SIZEOF } from "@thi.ng/api/typedarray";
2
2
  import { align } from "@thi.ng/binary/align";
3
3
  import { SOA } from "./soa.js";
4
4
  import { prepareSpec } from "./utils.js";
5
- /**
6
- * Constructs SOA instance from given attrib specs and optional
7
- * ArrayBuffer (w/ optional start address / byte offset, which MUST be
8
- * properly pre-aligned). The resulting layout will be an underlying
9
- * interleaved AOS buffer with each attrib configured to map that same
10
- * array buffer relative to the given `byteOffset` (default: 0). If no
11
- * array buffer is given, a properly sized one will be created.
12
- *
13
- * First computes attrib offsets, alignments and the overall struct
14
- * size, then configures buffer views and strides for each attrib. This
15
- * is to ensure each attrib is correctly mapped in its buffer view (e.g.
16
- * float values need to be aligned to 4-byte boundaries). The overall
17
- * inter-struct packing/stride length is dependent on the largest attrib
18
- * type used. E.g. the following specs will cause a stride length of 16
19
- * bytes between each resulting SOA element, even though the actual
20
- * struct size is only 13 bytes:
21
- *
22
- * @example
23
- * ```ts
24
- * aos(
25
- * 1024,
26
- * {
27
- * a: { type: "u16", size: 1 }, // 2 bytes, align 2, offset 0
28
- * b: { type: "f32", size: 2 }, // 8 bytes, align 4, offset 4
29
- * c: { type: "u8", size: 1 }, // 1 byte, align 1, offset 12
30
- * }
31
- * );
32
- * ```
33
- *
34
- * @param num -
35
- * @param specs -
36
- * @param buf -
37
- * @param byteOffset -
38
- */
39
- export const aos = (num, specs, buf, byteOffset = 0) => {
40
- let total = 0;
41
- let maxSize = 0;
42
- const offsets = {};
43
- const soaSpecs = {};
44
- for (let id in specs) {
45
- const spec = prepareSpec(specs[id]);
46
- const tsize = SIZEOF[spec.type];
47
- maxSize = Math.max(maxSize, tsize);
48
- // align field to type size
49
- total = align(total, tsize);
50
- offsets[id] = total;
51
- total += tsize * spec.size;
52
- soaSpecs[id] = spec;
53
- }
54
- // align total struct size to largest type
55
- total = align(total, maxSize);
56
- buf = buf || new ArrayBuffer(total * num + byteOffset);
57
- for (let id in soaSpecs) {
58
- const spec = soaSpecs[id];
59
- const tsize = SIZEOF[spec.type];
60
- spec.stride = total / tsize;
61
- spec.buf = buf;
62
- spec.byteOffset = byteOffset + offsets[id];
63
- }
64
- return new SOA(num, soaSpecs);
5
+ const aos = (num, specs, buf, byteOffset = 0) => {
6
+ let total = 0;
7
+ let maxSize = 0;
8
+ const offsets = {};
9
+ const soaSpecs = {};
10
+ for (let id in specs) {
11
+ const spec = prepareSpec(specs[id]);
12
+ const tsize = SIZEOF[spec.type];
13
+ maxSize = Math.max(maxSize, tsize);
14
+ total = align(total, tsize);
15
+ offsets[id] = total;
16
+ total += tsize * spec.size;
17
+ soaSpecs[id] = spec;
18
+ }
19
+ total = align(total, maxSize);
20
+ buf = buf || new ArrayBuffer(total * num + byteOffset);
21
+ for (let id in soaSpecs) {
22
+ const spec = soaSpecs[id];
23
+ const tsize = SIZEOF[spec.type];
24
+ spec.stride = total / tsize;
25
+ spec.buf = buf;
26
+ spec.byteOffset = byteOffset + offsets[id];
27
+ }
28
+ return new SOA(num, soaSpecs);
29
+ };
30
+ export {
31
+ aos
65
32
  };
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/soa",
3
- "version": "0.4.86",
3
+ "version": "0.4.88",
4
4
  "description": "SOA & AOS memory mapped structured views with optional & extensible serialization",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,16 +35,16 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.10",
37
- "@thi.ng/binary": "^3.3.39",
38
- "@thi.ng/errors": "^2.4.4",
39
- "@thi.ng/transducers-binary": "^2.1.80",
40
- "@thi.ng/vectors": "^7.8.7"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/binary": "^3.4.0",
40
+ "@thi.ng/errors": "^2.4.6",
41
+ "@thi.ng/transducers-binary": "^2.1.82",
42
+ "@thi.ng/vectors": "^7.8.9"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@microsoft/api-extractor": "^7.38.3",
44
- "@thi.ng/equiv": "^2.1.35",
45
- "@thi.ng/testament": "^0.4.3",
46
+ "@thi.ng/equiv": "^2.1.37",
47
+ "esbuild": "^0.19.8",
46
48
  "rimraf": "^5.0.5",
47
49
  "tools": "^0.0.1",
48
50
  "typedoc": "^0.25.4",
@@ -104,5 +106,5 @@
104
106
  "status": "alpha",
105
107
  "year": 2019
106
108
  },
107
- "gitHead": "04d1de79f256d7a53c6b5fd157b37f49bc88e11d\n"
109
+ "gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
108
110
  }
package/serialize.js CHANGED
@@ -1,61 +1,52 @@
1
1
  import { identity } from "@thi.ng/api/fn";
2
2
  import { assert } from "@thi.ng/errors/assert";
3
3
  import { utf8Decode, utf8Encode } from "@thi.ng/transducers-binary/utf8";
4
- /**
5
- * Identity serializer pair (no op).
6
- */
7
- export const ident = {
8
- decode: identity,
9
- encode: identity,
4
+ const ident = {
5
+ decode: identity,
6
+ encode: identity
10
7
  };
11
- /**
12
- * Serializer pair for scalars.
13
- */
14
- export const scalar = {
15
- decode: (v) => v[0],
16
- encode: (x) => [x],
8
+ const scalar = {
9
+ decode: (v) => v[0],
10
+ encode: (x) => [x]
17
11
  };
18
12
  const toUTF8 = utf8Decode();
19
- /**
20
- * Zero-terminated UTF-8 string serializer pair for given max length
21
- * (incl. final \0 char).
22
- *
23
- * {@link SerializerPair.encode} throws error if resulting byte sequence
24
- * is larger than configured `maxLen`.
25
- *
26
- * @param maxLen -
27
- */
28
- export const utf8z = (maxLen) => ({
29
- decode: (v) => {
30
- let acc = "";
31
- const xf = toUTF8([null, null, (_, x) => (acc += x)])[2];
32
- for (let i = 0, n = v.length; i < n; i++) {
33
- const c = v[i];
34
- if (c === 0)
35
- break;
36
- xf(acc, c);
37
- }
38
- return acc;
39
- },
40
- encode: (v) => {
41
- const bytes = [...utf8Encode(v), 0];
42
- assert(bytes.length <= maxLen, `string too large: "${v}"`);
43
- return bytes;
44
- },
13
+ const utf8z = (maxLen) => ({
14
+ decode: (v) => {
15
+ let acc = "";
16
+ const xf = toUTF8([null, null, (_, x) => acc += x])[2];
17
+ for (let i = 0, n = v.length; i < n; i++) {
18
+ const c = v[i];
19
+ if (c === 0)
20
+ break;
21
+ xf(acc, c);
22
+ }
23
+ return acc;
24
+ },
25
+ encode: (v) => {
26
+ const bytes = [...utf8Encode(v), 0];
27
+ assert(bytes.length <= maxLen, `string too large: "${v}"`);
28
+ return bytes;
29
+ }
45
30
  });
46
- export const serializer = (specs) => ({
47
- decode(tuple) {
48
- const res = {};
49
- for (let id in tuple) {
50
- res[id] = specs[id].decode(tuple[id]);
51
- }
52
- return res;
53
- },
54
- encode: (tuple) => {
55
- const res = {};
56
- for (let id in tuple) {
57
- res[id] = specs[id].encode(tuple[id]);
58
- }
59
- return res;
60
- },
31
+ const serializer = (specs) => ({
32
+ decode(tuple) {
33
+ const res = {};
34
+ for (let id in tuple) {
35
+ res[id] = specs[id].decode(tuple[id]);
36
+ }
37
+ return res;
38
+ },
39
+ encode: (tuple) => {
40
+ const res = {};
41
+ for (let id in tuple) {
42
+ res[id] = specs[id].encode(tuple[id]);
43
+ }
44
+ return res;
45
+ }
61
46
  });
47
+ export {
48
+ ident,
49
+ scalar,
50
+ serializer,
51
+ utf8z
52
+ };
package/soa.js CHANGED
@@ -2,159 +2,163 @@ import { SIZEOF, typedArray } from "@thi.ng/api/typedarray";
2
2
  import { assert } from "@thi.ng/errors/assert";
3
3
  import { ensureIndex } from "@thi.ng/errors/out-of-bounds";
4
4
  import { prepareSpec } from "./utils.js";
5
- export class SOA {
6
- length;
7
- buffers;
8
- specs;
9
- constructor(num, specs) {
10
- this.length = num;
11
- this.buffers = {};
12
- this.specs = {};
13
- this.addSpecs(specs);
14
- }
15
- keys() {
16
- return Object.keys(this.specs);
17
- }
18
- *values(from = 0, to = this.length) {
19
- ensureIndex(from, 0, this.length);
20
- ensureIndex(to, from, this.length + 1);
21
- for (; from < to; from++) {
22
- yield this.indexUnsafe(from);
23
- }
24
- }
25
- attribValues(id, from = 0, to = this.length) {
26
- this.ensureAttrib(id);
27
- ensureIndex(from, 0, this.length);
28
- ensureIndex(to, from, this.length + 1);
29
- let { size, stride, type } = this.specs[id];
30
- const buf = this.buffers[id].buffer;
31
- stride *= SIZEOF[type];
32
- from *= stride;
33
- to *= stride;
34
- const res = [];
35
- for (; from < to; from += stride) {
36
- res.push(typedArray(type, buf, from, size));
37
- }
38
- return res;
39
- }
40
- attribValue(id, i) {
41
- this.ensureAttrib(id);
42
- ensureIndex(i, 0, this.length);
43
- return this.attribValueUnsafe(id, i);
44
- }
45
- attribValueUnsafe(id, i) {
46
- const spec = this.specs[id];
47
- i *= spec.stride;
48
- return this.buffers[id].subarray(i, i + spec.size);
49
- }
50
- setAttribValue(id, i, val) {
51
- this.ensureAttrib(id);
52
- ensureIndex(i, 0, this.length);
53
- const spec = this.specs[id];
54
- assert(val.length <= spec.size, `${id} value too large`);
55
- this.buffers[id].set(val, i * spec.stride);
56
- }
57
- setAttribValueUnsafe(id, i, val) {
58
- this.buffers[id].set(val, i * this.specs[id].stride);
59
- return this;
60
- }
61
- setAttribValues(id, vals, from = 0) {
62
- this.ensureAttrib(id);
63
- ensureIndex(from, 0, this.length);
64
- const buf = this.buffers[id];
65
- const stride = this.specs[id].stride;
66
- const end = this.length * stride;
67
- let i = from * stride;
68
- for (let v of vals) {
69
- buf.set(v, i);
70
- i += stride;
71
- if (i >= end)
72
- break;
73
- }
74
- return this;
75
- }
76
- index(i, ids) {
77
- ensureIndex(i, 0, this.length);
78
- return this.indexUnsafe(i, ids);
79
- }
80
- indexUnsafe(i, ids) {
81
- const res = {};
82
- if (ids) {
83
- for (let i = ids.length; i-- > 0;) {
84
- const id = ids[i];
85
- res[id] = this.attribValueUnsafe(id, i);
86
- }
87
- }
88
- else {
89
- for (let id in this.specs) {
90
- res[id] = this.attribValueUnsafe(id, i);
91
- }
5
+ class SOA {
6
+ length;
7
+ buffers;
8
+ specs;
9
+ constructor(num, specs) {
10
+ this.length = num;
11
+ this.buffers = {};
12
+ this.specs = {};
13
+ this.addSpecs(specs);
14
+ }
15
+ keys() {
16
+ return Object.keys(this.specs);
17
+ }
18
+ *values(from = 0, to = this.length) {
19
+ ensureIndex(from, 0, this.length);
20
+ ensureIndex(to, from, this.length + 1);
21
+ for (; from < to; from++) {
22
+ yield this.indexUnsafe(from);
23
+ }
24
+ }
25
+ attribValues(id, from = 0, to = this.length) {
26
+ this.ensureAttrib(id);
27
+ ensureIndex(from, 0, this.length);
28
+ ensureIndex(to, from, this.length + 1);
29
+ let { size, stride, type } = this.specs[id];
30
+ const buf = this.buffers[id].buffer;
31
+ stride *= SIZEOF[type];
32
+ from *= stride;
33
+ to *= stride;
34
+ const res = [];
35
+ for (; from < to; from += stride) {
36
+ res.push(typedArray(type, buf, from, size));
37
+ }
38
+ return res;
39
+ }
40
+ attribValue(id, i) {
41
+ this.ensureAttrib(id);
42
+ ensureIndex(i, 0, this.length);
43
+ return this.attribValueUnsafe(id, i);
44
+ }
45
+ attribValueUnsafe(id, i) {
46
+ const spec = this.specs[id];
47
+ i *= spec.stride;
48
+ return this.buffers[id].subarray(i, i + spec.size);
49
+ }
50
+ setAttribValue(id, i, val) {
51
+ this.ensureAttrib(id);
52
+ ensureIndex(i, 0, this.length);
53
+ const spec = this.specs[id];
54
+ assert(val.length <= spec.size, `${id} value too large`);
55
+ this.buffers[id].set(val, i * spec.stride);
56
+ }
57
+ setAttribValueUnsafe(id, i, val) {
58
+ this.buffers[id].set(val, i * this.specs[id].stride);
59
+ return this;
60
+ }
61
+ setAttribValues(id, vals, from = 0) {
62
+ this.ensureAttrib(id);
63
+ ensureIndex(from, 0, this.length);
64
+ const buf = this.buffers[id];
65
+ const stride = this.specs[id].stride;
66
+ const end = this.length * stride;
67
+ let i = from * stride;
68
+ for (let v of vals) {
69
+ buf.set(v, i);
70
+ i += stride;
71
+ if (i >= end)
72
+ break;
73
+ }
74
+ return this;
75
+ }
76
+ index(i, ids) {
77
+ ensureIndex(i, 0, this.length);
78
+ return this.indexUnsafe(i, ids);
79
+ }
80
+ indexUnsafe(i, ids) {
81
+ const res = {};
82
+ if (ids) {
83
+ for (let i2 = ids.length; i2-- > 0; ) {
84
+ const id = ids[i2];
85
+ res[id] = this.attribValueUnsafe(id, i2);
86
+ }
87
+ } else {
88
+ for (let id in this.specs) {
89
+ res[id] = this.attribValueUnsafe(id, i);
90
+ }
91
+ }
92
+ return res;
93
+ }
94
+ setIndex(i, vals) {
95
+ ensureIndex(i, 0, this.length);
96
+ for (let id in vals) {
97
+ this.setAttribValue(id, i, vals[id]);
98
+ }
99
+ return this;
100
+ }
101
+ setIndexUnsafe(i, vals) {
102
+ for (let id in vals) {
103
+ this.setAttribValueUnsafe(id, i, vals[id]);
104
+ }
105
+ return this;
106
+ }
107
+ setValues(vals, from = 0) {
108
+ for (let id in vals) {
109
+ this.setAttribValues(id, vals[id], from);
110
+ }
111
+ return this;
112
+ }
113
+ copyTo(dest, ids, destFrom = 0, srcFrom = 0, srcTo = this.length) {
114
+ ensureIndex(srcFrom, 0, this.length);
115
+ ensureIndex(srcTo, srcFrom, this.length + 1);
116
+ const num = srcTo - srcFrom;
117
+ ensureIndex(destFrom, 0, dest.length);
118
+ ensureIndex(destFrom + num, destFrom, dest.length + 1);
119
+ ids = ids || Object.keys(this.specs);
120
+ for (let k = ids.length; k-- > 0; ) {
121
+ const id = ids[k];
122
+ for (let i = srcFrom, j = destFrom; i < srcTo; i++, j++) {
123
+ dest.setAttribValueUnsafe(id, j, this.attribValueUnsafe(id, i));
124
+ }
125
+ }
126
+ return dest;
127
+ }
128
+ addSpecs(specs) {
129
+ const num = this.length;
130
+ for (let id in specs) {
131
+ assert(!this.specs[id], `attrib ${id} already exists`);
132
+ const spec = prepareSpec(specs[id]);
133
+ this.validateSpec(id, spec);
134
+ const { stride, default: defVal } = spec;
135
+ const buffer = spec.buf ? typedArray(spec.type, spec.buf, spec.byteOffset || 0) : typedArray(spec.type, num * stride);
136
+ if (defVal) {
137
+ for (let i = 0; i < num; i++) {
138
+ buffer.set(defVal, i * stride);
92
139
  }
93
- return res;
94
- }
95
- setIndex(i, vals) {
96
- ensureIndex(i, 0, this.length);
97
- for (let id in vals) {
98
- this.setAttribValue(id, i, vals[id]);
99
- }
100
- return this;
101
- }
102
- setIndexUnsafe(i, vals) {
103
- for (let id in vals) {
104
- this.setAttribValueUnsafe(id, i, vals[id]);
105
- }
106
- return this;
107
- }
108
- setValues(vals, from = 0) {
109
- for (let id in vals) {
110
- this.setAttribValues(id, vals[id], from);
111
- }
112
- return this;
113
- }
114
- copyTo(dest, ids, destFrom = 0, srcFrom = 0, srcTo = this.length) {
115
- ensureIndex(srcFrom, 0, this.length);
116
- ensureIndex(srcTo, srcFrom, this.length + 1);
117
- const num = srcTo - srcFrom;
118
- ensureIndex(destFrom, 0, dest.length);
119
- ensureIndex(destFrom + num, destFrom, dest.length + 1);
120
- ids = ids || Object.keys(this.specs);
121
- for (let k = ids.length; k-- > 0;) {
122
- const id = ids[k];
123
- for (let i = srcFrom, j = destFrom; i < srcTo; i++, j++) {
124
- dest.setAttribValueUnsafe(id, j, this.attribValueUnsafe(id, i));
125
- }
126
- }
127
- return dest;
128
- }
129
- addSpecs(specs) {
130
- const num = this.length;
131
- for (let id in specs) {
132
- assert(!this.specs[id], `attrib ${id} already exists`);
133
- const spec = prepareSpec(specs[id]);
134
- this.validateSpec(id, spec);
135
- const { stride, default: defVal } = spec;
136
- const buffer = spec.buf
137
- ? typedArray(spec.type, spec.buf, spec.byteOffset || 0)
138
- : typedArray(spec.type, num * stride);
139
- if (defVal) {
140
- for (let i = 0; i < num; i++) {
141
- buffer.set(defVal, i * stride);
142
- }
143
- }
144
- this.specs[id] = spec;
145
- this.buffers[id] = buffer;
146
- }
147
- }
148
- validateSpec(id, spec) {
149
- assert(spec.stride >= spec.size, `${id} illegal stride`);
150
- assert(!spec.buf ||
151
- spec.buf.byteLength >=
152
- ((this.length - 1) * spec.stride + spec.size) *
153
- SIZEOF[spec.type], `${id} buffer too small`);
154
- assert(spec.default === undefined || spec.default.length === spec.size, `illegal default value for ${id}, expected size: ${spec.size}`);
155
- }
156
- ensureAttrib(id) {
157
- assert(!!this.specs[id], `invalid attrib ${id}`);
158
- }
140
+ }
141
+ this.specs[id] = spec;
142
+ this.buffers[id] = buffer;
143
+ }
144
+ }
145
+ validateSpec(id, spec) {
146
+ assert(spec.stride >= spec.size, `${id} illegal stride`);
147
+ assert(
148
+ !spec.buf || spec.buf.byteLength >= ((this.length - 1) * spec.stride + spec.size) * SIZEOF[spec.type],
149
+ `${id} buffer too small`
150
+ );
151
+ assert(
152
+ spec.default === void 0 || spec.default.length === spec.size,
153
+ `illegal default value for ${id}, expected size: ${spec.size}`
154
+ );
155
+ }
156
+ ensureAttrib(id) {
157
+ assert(!!this.specs[id], `invalid attrib ${id}`);
158
+ }
159
159
  }
160
- export const soa = (num, specs) => new SOA(num, specs);
160
+ const soa = (num, specs) => new SOA(num, specs);
161
+ export {
162
+ SOA,
163
+ soa
164
+ };
package/utils.js CHANGED
@@ -1,5 +1,8 @@
1
- export const prepareSpec = (spec) => {
2
- spec = { type: "f32", size: 1, ...spec };
3
- !spec.stride && (spec.stride = spec.size);
4
- return spec;
1
+ const prepareSpec = (spec) => {
2
+ spec = { type: "f32", size: 1, ...spec };
3
+ !spec.stride && (spec.stride = spec.size);
4
+ return spec;
5
+ };
6
+ export {
7
+ prepareSpec
5
8
  };