Skip to content

Commit 623b796

Browse files
committed
v.1.0.0
1 parent 6c54b81 commit 623b796

File tree

3 files changed

+116
-104
lines changed

3 files changed

+116
-104
lines changed

README.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
View one-dimensional array data, typed array data and/or multi-dimensional array data as multidimensional tensors of various shapes efficiently.
44

5-
version: **1.0.0**
5+
version: **1.0.0** (8.8 kB minified)
66

77
`TensorView` is both memory-efficient and speed-efficient since it only creates ways to view array data as multidimensional tensors **without** actually creating new arrays. One can nevertheless explicitly store a TensorView instance as a single-dimensional or multi-dimensional array using `view.toArray()` or `view.toNDArray()` methods.
88

@@ -104,4 +104,31 @@ view.op(op, otherView=null); // apply lazy, when requested, pointwise operation
104104

105105
// creating an actual copy and not share data is easy to do in various ways, eg:
106106
const copied = TensorView(view.toArray(), {shape:view.size()}); // any active slicing and/or operation will be applied on view output
107-
```
107+
108+
view.dispose(); // dispose view if no longer needed
109+
```
110+
111+
**see also:**
112+
113+
* [Abacus](https://github.com/foo123/Abacus) advanced Combinatorics and Algebraic Number Theory Symbolic Computation library for JavaScript, Python
114+
* [TensorView](https://github.com/foo123/TensorView) view array data as multidimensional tensors of various shapes efficiently
115+
* [Geometrize](https://github.com/foo123/Geometrize) Computational Geometry and Rendering Library for JavaScript
116+
* [Plot.js](https://github.com/foo123/Plot.js) simple and small library which can plot graphs of functions and various simple charts and can render to Canvas, SVG and plain HTML
117+
* [CanvasLite](https://github.com/foo123/CanvasLite) an html canvas implementation in pure JavaScript
118+
* [Rasterizer](https://github.com/foo123/Rasterizer) stroke and fill lines, rectangles, curves and paths, without canvas
119+
* [Gradient](https://github.com/foo123/Gradient) create linear, radial, conic and elliptic gradients and image patterns without canvas
120+
* [css-color](https://github.com/foo123/css-color) simple class to parse and manipulate colors in various formats
121+
* [MOD3](https://github.com/foo123/MOD3) 3D Modifier Library in JavaScript
122+
* [HAAR.js](https://github.com/foo123/HAAR.js) image feature detection based on Haar Cascades in JavaScript (Viola-Jones-Lienhart et al Algorithm)
123+
* [HAARPHP](https://github.com/foo123/HAARPHP) image feature detection based on Haar Cascades in PHP (Viola-Jones-Lienhart et al Algorithm)
124+
* [FILTER.js](https://github.com/foo123/FILTER.js) video and image processing and computer vision Library in pure JavaScript (browser and node)
125+
* [Xpresion](https://github.com/foo123/Xpresion) a simple and flexible eXpression parser engine (with custom functions and variables support), based on [GrammarTemplate](https://github.com/foo123/GrammarTemplate), for PHP, JavaScript, Python
126+
* [Regex Analyzer/Composer](https://github.com/foo123/RegexAnalyzer) Regular Expression Analyzer and Composer for PHP, JavaScript, Python
127+
* [GrammarTemplate](https://github.com/foo123/GrammarTemplate) grammar-based templating for PHP, JavaScript, Python
128+
* [codemirror-grammar](https://github.com/foo123/codemirror-grammar) transform a formal grammar in JSON format into a syntax-highlight parser for CodeMirror editor
129+
* [ace-grammar](https://github.com/foo123/ace-grammar) transform a formal grammar in JSON format into a syntax-highlight parser for ACE editor
130+
* [prism-grammar](https://github.com/foo123/prism-grammar) transform a formal grammar in JSON format into a syntax-highlighter for Prism code highlighter
131+
* [highlightjs-grammar](https://github.com/foo123/highlightjs-grammar) transform a formal grammar in JSON format into a syntax-highlight mode for Highlight.js code highlighter
132+
* [syntaxhighlighter-grammar](https://github.com/foo123/syntaxhighlighter-grammar) transform a formal grammar in JSON format to a highlight brush for SyntaxHighlighter code highlighter
133+
* [SortingAlgorithms](https://github.com/foo123/SortingAlgorithms) implementations of Sorting Algorithms in JavaScript
134+
* [PatternMatchingAlgorithms](https://github.com/foo123/PatternMatchingAlgorithms) implementations of Pattern Matching Algorithms in JavaScript

src/TensorView.js

Lines changed: 86 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -29,54 +29,27 @@ function TensorView(data, o, _)
2929
op = null, refs = null,
3030
stack = null, stack_axis = -1,
3131
global_indices = null, nd_shape = null,
32-
ndim = 0, shape = null, slicing = null, size = null,
33-
length = 0, total = 0;
32+
ndim = 0, shape = null, stride = null,
33+
slicing = null, size = null, length = 0, total = 0;
3434

35-
function compute_index(indices, ndim, transposed, shape, size, slicing)
35+
function compute_index(indices, ndim, transposed, shape, stride, size, slicing)
3636
{
3737
// compute single index for row/column-major ordering scheme from multidimensional indices
3838
var index = 0, axis, i;
39-
if (transposed)
39+
if (slicing)
4040
{
41-
if (slicing)
42-
{
43-
for (axis=ndim-1; axis>=0; --axis)
44-
{
45-
i = /*size[axis] - 1 -*/ indices[axis];
46-
index *= shape[axis];
47-
index += slicing[axis].start + ((0 > i ? size[axis] : 0) + i) * slicing[axis].step;
48-
}
49-
}
50-
else
41+
for (axis=0; axis<ndim; ++axis)
5142
{
52-
for (axis=ndim-1; axis>=0; --axis)
53-
{
54-
i = /*size[axis] - 1 -*/ indices[axis];
55-
index *= shape[axis];
56-
index += (0 > i ? size[axis] : 0) + i;
57-
}
43+
i = indices[axis];
44+
index += stride[axis] * (slicing[axis].start + ((0 > i ? size[axis] : 0) + i) * slicing[axis].step);
5845
}
59-
//index = total - 1 - index;
6046
}
6147
else
6248
{
63-
if (slicing)
64-
{
65-
for (axis=0; axis<ndim; ++axis)
66-
{
67-
i = indices[axis];
68-
index *= shape[axis];
69-
index += slicing[axis].start + ((0 > i ? size[axis] : 0) + i) * slicing[axis].step;
70-
}
71-
}
72-
else
49+
for (axis=0; axis<ndim; ++axis)
7350
{
74-
for (axis=0; axis<ndim; ++axis)
75-
{
76-
i = indices[axis];
77-
index *= shape[axis];
78-
index += (0 > i ? size[axis] : 0) + i;
79-
}
51+
i = indices[axis];
52+
index += stride[axis] * ((0 > i ? size[axis] : 0) + i);
8053
}
8154
}
8255
return index;
@@ -88,14 +61,13 @@ function TensorView(data, o, _)
8861
var axis, i;
8962
if (transposed)
9063
{
91-
//index = total - 1 - index;
9264
if (slicing)
9365
{
9466
for (axis=0; axis<ndim; ++axis)
9567
{
9668
i = index % shape[axis];
9769
index = stdMath.floor(index / shape[axis]);
98-
indices[axis] = /*size[axis] - 1 -*/ stdMath.floor((i - slicing[axis].start) / slicing[axis].step);
70+
indices[axis] = stdMath.floor((i - slicing[axis].start) / slicing[axis].step);
9971
}
10072
}
10173
else
@@ -104,7 +76,7 @@ function TensorView(data, o, _)
10476
{
10577
i = index % shape[axis];
10678
index = stdMath.floor(index / shape[axis]);
107-
indices[axis] = /*size[axis] - 1 -*/ i;
79+
indices[axis] = i;
10880
}
10981
}
11082
}
@@ -207,6 +179,10 @@ function TensorView(data, o, _)
207179
{
208180
walk(data, compute_indices(index, nd_shape.length, false, nd_shape, nd_shape, null, global_indices), value);
209181
}
182+
else if (is_value)
183+
{
184+
data = value;
185+
}
210186
else
211187
{
212188
data[index] = value;
@@ -217,7 +193,16 @@ function TensorView(data, o, _)
217193

218194
is_transposed = _ ? !!_._transposed : false;
219195

220-
if (_ && _._refs && (_._refs[0] instanceof TensorView))
196+
if (data instanceof TensorView)
197+
{
198+
is_transposed = false;
199+
refs = [data];
200+
data = refs[0].data();
201+
total = refs[0].length();
202+
shape = o.shape || refs[0].size();
203+
ndim = shape.length;
204+
}
205+
else if (_ && _._refs && (_._refs[0] instanceof TensorView))
221206
{
222207
is_transposed = false;
223208
op = _._op || null;
@@ -291,6 +276,18 @@ function TensorView(data, o, _)
291276
}
292277
}
293278

279+
stride = new Array(ndim);
280+
if (is_transposed)
281+
{
282+
stride[0] = 1;
283+
for (var i=1; i<ndim; ++i) stride[i] = stride[i-1]*shape[i-1];
284+
}
285+
else
286+
{
287+
stride[ndim-1] = 1;
288+
for (var i=ndim-2; i>=0; --i) stride[i] = stride[i+1]*shape[i+1];
289+
}
290+
294291
size = new Array(ndim);
295292
for (var i=0; i<ndim; ++i) size[i] = slicing[i].count(shape[i]);
296293
length = ndim ? product(size) : 0;
@@ -304,6 +301,7 @@ function TensorView(data, o, _)
304301
nd_shape = null;
305302
data = null;
306303
shape = null;
304+
stride = null;
307305
slicing = null;
308306
size = null;
309307
};
@@ -326,72 +324,74 @@ function TensorView(data, o, _)
326324
return length;
327325
};
328326
self.index = function(/*indices*/) {
329-
return compute_index(Array.isArray(arguments[0]) ? arguments[0] : arguments, ndim, is_transposed, shape, size, slicing);
327+
return compute_index(Array.isArray(arguments[0]) ? arguments[0] : arguments, ndim, is_transposed, shape, stride, size, slicing);
330328
};
331329
self.indices = function(index) {
332330
return compute_indices(index, ndim, is_transposed, shape, size, slicing);
333331
};
334332
self.iterator = function() {
335-
var i = 0 < length ? ndim - 1 : -1, j, index,
336-
indices = 0 < length ? (new Array(ndim)).fill(0) : null,
337-
ind = indices ? new Array(ndim) : null;
333+
var i = 0 < length ? ndim - 1 : -1,
334+
indices = null, ind = null, index = 0,
335+
ret = {value: null};
338336
return {next:function next() {
339337
if (0 > i)
340338
{
341-
return {done:true};
339+
indices = ind = ret = null;
340+
return {done: true};
342341
}
343342
else
344343
{
345-
index = compute_index(indices, ndim, is_transposed, shape, size, slicing);
346-
for (j=0; j<ndim; ++j) ind[j] = indices[j];
347-
var value = [get(index, indices), ind/*, index*/];
348-
while (i >= 0 && indices[i]+1 >= size[i]) --i;
349-
if (0 <= i)
344+
if (!indices)
350345
{
351-
++indices[i];
352-
while (i+1 < ndim) indices[++i] = 0;
346+
indices = (new Array(ndim)).fill(0);
347+
ind = indices.slice();
348+
index = compute_index(indices, ndim, is_transposed, shape, stride, size, slicing);
349+
ret.value = [get(index, indices), ind/*, index*/];
350+
}
351+
else
352+
{
353+
while (i >= 0 && indices[i]+1 >= size[i])
354+
{
355+
index -= stride[i] * (slicing[i].start + indices[i] * slicing[i].step);
356+
--i;
357+
}
358+
if (0 <= i)
359+
{
360+
++indices[i];
361+
ind[i] = indices[i];
362+
index += stride[i] * slicing[i].step;
363+
while (i+1 < ndim)
364+
{
365+
++i;
366+
indices[i] = 0;
367+
ind[i] = 0;
368+
index += stride[i] * slicing[i].start;
369+
}
370+
ret.value = [get(index, indices), ind/*, index*/];
371+
}
372+
else
373+
{
374+
indices = ind = ret = null;
375+
return {done: true};
376+
}
353377
}
354-
return {value:value};
378+
return ret;
355379
}
356380
}};
357381
};
358382
self.forEach = function(f) {
359383
if (0 < length && is_function(f))
360384
{
361-
var indices = (new Array(ndim)).fill(0),
362-
indices2 = indices.slice(),
363-
index = 0, i = ndim - 1, ret = null;
385+
var iter = self.iterator(), next, ret = null;
364386
while (true)
365387
{
366-
// way to compute index incrementally here ..??
367-
index = compute_index(indices, ndim, is_transposed, shape, size, slicing);
368-
ret = f(get(index, indices), indices2, data/*, index*/, self);
388+
next = iter.next();
389+
if (!next || next.done) return;
390+
ret = f(next.value[0], next.value[1], data/*, next.value[2]*/, self);
369391
if (false === ret) return; // if false returned end forEach
370-
while (i >= 0 && indices[i]+1 >= size[i]) --i;
371-
if (0 > i) return;
372-
++indices[i];
373-
indices2[i] = indices[i];
374-
while (i+1 < ndim)
375-
{
376-
++i;
377-
indices[i] = 0;
378-
indices2[i] = 0;
379-
}
380392
}
381393
}
382394
};
383-
self.indexOf = function(x, eq) {
384-
eq = eq || equ;
385-
var indices = null;
386-
self.forEach(function(di, i) {
387-
if (eq(x, di))
388-
{
389-
indices = i; // found
390-
return false; // stop
391-
}
392-
});
393-
return indices;
394-
};
395395
self.slice = function(slices) {
396396
return new TensorView(
397397
data,
@@ -412,15 +412,7 @@ function TensorView(data, o, _)
412412
);
413413
};
414414
self.reshape = function(shape) {
415-
return new TensorView(
416-
data,
417-
{
418-
shape: shape
419-
},
420-
{
421-
_refs: [self]
422-
}
423-
);
415+
return new TensorView(self, {shape: shape});
424416
};
425417
self.concat = function(others, axis) {
426418
axis = axis || 0;
@@ -441,13 +433,13 @@ function TensorView(data, o, _)
441433
};
442434
self.get = function(indices) {
443435
if (indices.length < ndim) throw "TensorView::get:indices do not match shape!";
444-
var index = stack ? 0 : compute_index(indices, ndim, is_transposed, shape, size, slicing);
436+
var index = stack ? 0 : compute_index(indices, ndim, is_transposed, shape, stride, size, slicing);
445437
if (0 > index || index >= total) throw "TensorView::get:index out of data bounds!";
446438
return get(index, indices);
447439
};
448440
self.set = function(indices, value) {
449441
if (indices.length < ndim) throw "TensorView::set:indices do not match shape!";
450-
var index = stack ? 0 : compute_index(indices, ndim, is_transposed, shape, size, slicing);
442+
var index = stack ? 0 : compute_index(indices, ndim, is_transposed, shape, stride, size, slicing);
451443
if (0 > index || index >= total) throw "TensorView::set:index out of data bounds!";
452444
set(index, indices, value);
453445
return self;
@@ -488,8 +480,6 @@ function TensorView(data, o, _)
488480
var array = new (ArrayClass || Array)(length), index = 0;
489481
self.forEach(function(di/*,i*/) {
490482
// put in row-major order
491-
/*for (var j=0,n=ndim-1,ij=0; j<n; ++j) {ij += i[j]; ij *= size[j+1];}
492-
array[ij+i[n]] = di;*/
493483
array[index++] = di;
494484
});
495485
return array;
@@ -570,7 +560,7 @@ function TensorView(data, o, _)
570560
{
571561
self.forEach(function(di) {
572562
// print in 1d slices
573-
str += (str.length ? " " : "") + String(di)/*pad(String(di), max, ' ', false)*/;
563+
str += (str.length ? " " : "") + String(di);
574564
});
575565
}
576566
}
@@ -591,7 +581,6 @@ TensorView[proto] = {
591581
indices: null,
592582
iterator: null,
593583
forEach: null,
594-
indexOf: null,
595584
slice: null,
596585
reshape: null,
597586
concat: null,
@@ -684,10 +673,6 @@ function pad(s, n, z, after)
684673
var p = s.length < n ? (new Array(n-s.length+1)).join(z) : '';
685674
return after ? (s + p) : (p + s);
686675
}
687-
function equ(a, b)
688-
{
689-
return a === b;
690-
}
691676
function add(a, b)
692677
{
693678
return a + b;

0 commit comments

Comments
 (0)