Skip to content

Commit 2ff113d

Browse files
committed
v.1.1.0
* better formatted toString() output
1 parent 60f31c9 commit 2ff113d

7 files changed

Lines changed: 107 additions & 77 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ View one-dimensional array data, typed array data and/or multi-dimensional array
44

55
![TensorView](/tensorview.jpg)
66

7-
version: **1.0.0** (9.5 kB minified)
7+
version: **1.1.0** (9.7 kB minified)
88

99
`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.
1010

src/TensorView.js

Lines changed: 95 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* TensorView
33
* View array data as multidimensional tensors of various shapes efficiently
4-
* @VERSION 1.0.0
4+
* @VERSION 1.1.0
55
* https://github.com/foo123/TensorView
66
*
77
**/
@@ -18,7 +18,9 @@ else
1818
}('undefined' !== typeof self ? self : this, 'TensorView', function(undef) {
1919
"use strict";
2020

21-
var proto = 'prototype', stdMath = Math;
21+
var proto = 'prototype',
22+
stdMath = Math,
23+
TypedArray = "undefined" !== typeof Float32Array ? Object.getPrototypeOf(Float32Array) : null;
2224

2325
function TensorView(data, o, _)
2426
{
@@ -517,75 +519,12 @@ function TensorView(data, o, _)
517519
return ndarray;
518520
};
519521
self.toString = function(maxsize) {
520-
var str = '', max = -Infinity, rows = null,
521-
rem = '', maxsize2, oversize, inlimits;
522-
if (null != maxsize)
523-
{
524-
maxsize2 = maxsize >>> 1;
525-
if (2 <= ndim)
526-
{
527-
oversize = size.map(function(size) {return maxsize < size;});
528-
inlimits = function(i, j) {
529-
return !oversize[j] || (j <= ndim-3 && (i < maxsize2 || i > size[j]-1-maxsize2)) || (j > ndim-3 && (i <= maxsize2 || i >= size[j]-1-maxsize2));
530-
};
531-
rows = (new Array(oversize[size.length-2] ? maxsize+1 : size[size.length-2])).fill(null).map(function(_) {return new Array(oversize[size.length-1] ? maxsize+1 : size[size.length-1]);});
532-
self.forEach(function(di, i) {if (i.length === i.filter(inlimits).length) max = stdMath.max(String(di).length, max);});
533-
self.forEach(function(di, i) {
534-
// print in 2d slices
535-
if (i.length === i.filter(inlimits).length)
536-
{
537-
var i1 = i[ndim-2], i2 = i[ndim-1];
538-
if (oversize[ndim-2] && i1 > maxsize2) i1 = maxsize - (size[ndim-2]-1-i1);
539-
if (oversize[ndim-1] && i2 > maxsize2) i2 = maxsize - (size[ndim-1]-1-i2);
540-
rows[i1][i2] = pad(String(di), max, ' ', false);
541-
if (size[ndim-1] === 1+i[ndim-1] && size[ndim-2] === 1+i[ndim-2])
542-
{
543-
str += rem + rows.map(function(row, j) {
544-
if (oversize[ndim-2] && maxsize2 === j) row = new Array(row.length).fill(pad(':', max, ' ', false));
545-
if (oversize[ndim-1]) row[maxsize2] = pad('..', max, ' ', false);
546-
return row.join(' ');
547-
}).join("\n");
548-
var j = ndim-3, o = -1;
549-
while (0 <= j ) {o = (-1 === o) && oversize[j] && (i[j]+1 === maxsize2) ? j : o; --j;}
550-
rem = -1 === o ? "\n-\n" : "\n-\n"+pad(':', max, ' ', false)+' '+(new Array((oversize[ndim-1] ? maxsize+1 : size[ndim-1])-2)).fill(pad('..', max, ' ', false)).join(' ')+' '+pad(':', max, ' ', false)+"\n-\n";
551-
}
552-
}
553-
});
554-
}
555-
else
556-
{
557-
// print in 1d slices
558-
str = maxsize >= size[0] ? self.toString() : (self.slice([{start:0,stop:maxsize2+1}]).toString() + ' .. ' + self.slice([{start:size[0]-1-maxsize2,stop:size[0]-1}]).toString());
559-
}
560-
}
561-
else
562-
{
563-
if (2 <= ndim)
564-
{
565-
rows = (new Array(size[size.length-2])).fill(null).map(function(_) {return new Array(size[size.length-1]);});
566-
self.forEach(function(di) {max = stdMath.max(String(di).length, max);});
567-
self.forEach(function(di, i) {
568-
// print in 2d slices
569-
rows[i[ndim-2]][i[ndim-1]] = pad(String(di), max, ' ', false);
570-
if (size[ndim-1] === 1+i[ndim-1] && size[ndim-2] === 1+i[ndim-2])
571-
{
572-
str += rem + rows.map(function(row) {return row.join(' ');}).join("\n");
573-
rem = "\n-\n";
574-
}
575-
});
576-
}
577-
else
578-
{
579-
self.forEach(function(di) {
580-
// print in 1d slices
581-
str += (str.length ? " " : "") + String(di);
582-
});
583-
}
584-
}
585-
return str;
522+
if (null == maxsize) maxsize = Infinity;
523+
var ndarray = self.toNDArray();
524+
return 2 < ndim ? str_nd(ndarray, maxsize) : (2 === ndim ? str_2d(ndarray, maxsize) : str_1d(ndarray, maxsize));
586525
};
587526
}
588-
TensorView.VERSION = '1.0.0';
527+
TensorView.VERSION = '1.1.0';
589528
TensorView[proto] = {
590529
constructor: TensorView,
591530
dispose: null,
@@ -679,8 +618,18 @@ function is_function(x)
679618
function is_array(x)
680619
{
681620
if (Array.isArray(x)) return true;
682-
else if (("undefined" !== typeof Float32Array) && (x instanceof Object.getPrototypeOf(Float32Array))) return true;
683-
return false;
621+
return TypedArray ? (x instanceof TypedArray) : false;
622+
}
623+
function array(n, v)
624+
{
625+
n = stdMath.max(0, stdMath.round(n));
626+
var i, arr = new Array(n);
627+
for (i=0; i<n; ++i) arr[i] = is_function(v) ? v(i, arr) : v;
628+
return arr;
629+
}
630+
function size(x)
631+
{
632+
return is_array(x) ? ([x.length]).concat(size(x[0])) : [];
684633
}
685634
function pad(s, n, z, after)
686635
{
@@ -703,6 +652,81 @@ function product(array)
703652
{
704653
return array.reduce(mul, 1);
705654
}
655+
function str_1d(x, MAXPRINTSIZE)
656+
{
657+
if (x.length > MAXPRINTSIZE)
658+
{
659+
x = x.slice(0, stdMath.round(MAXPRINTSIZE/2)).concat(['..']).concat(x.slice(-stdMath.round(MAXPRINTSIZE/2)+1));
660+
}
661+
return '[' + x.map(function(xi) {return String(xi);}).join(' ') + ']';
662+
}
663+
function str_2d(x, MAXPRINTSIZE)
664+
{
665+
var use_ddots = false;
666+
if (x[0].length > MAXPRINTSIZE)
667+
{
668+
x = x.map(function(row) {
669+
return row.slice(0, stdMath.round(MAXPRINTSIZE/2)).concat('..').concat(row.slice(-stdMath.round(MAXPRINTSIZE/2)+1));
670+
});
671+
use_ddots = true;
672+
}
673+
if (x.length > MAXPRINTSIZE)
674+
{
675+
x = x.slice(0, stdMath.round(MAXPRINTSIZE/2)).concat([array(x[0].length, function(i) {return stdMath.round(MAXPRINTSIZE/2) === i ? (use_ddots ? ':.' : ':') : ':';})]).concat(x.slice(-stdMath.round(MAXPRINTSIZE/2)+1));
676+
}
677+
var ln = array(x[0].length, function(col) {
678+
return x.map(function(row) {return row[col];}).reduce(function(l, xi) {
679+
return stdMath.max(l, String(xi).length);
680+
}, 0);
681+
});
682+
return x.map(function(row, i) {
683+
return '[' + row.map(function(xij, j) {
684+
return pad(String(xij), ln[j], ' ');
685+
}).join(' ') + ']';
686+
}).join('\n');
687+
}
688+
function str_nd(x, MAXPRINTSIZE, indices)
689+
{
690+
if (null == indices) indices = [];
691+
var str = '', i, n = x.length, lim = stdMath.min(n, stdMath.round(MAXPRINTSIZE/2));
692+
for (i=0; i<lim; ++i)
693+
{
694+
if (is_array(x[i]) && is_array(x[i][0]))
695+
{
696+
if (is_array(x[i][0][0]))
697+
{
698+
if (str.length) str += "\n";
699+
str += str_nd(x[i], MAXPRINTSIZE, indices.concat(i));
700+
}
701+
else
702+
{
703+
if (str.length) str += "\n";
704+
str += 'array(' + indices.concat([i, ':', ':']).map(String).join(',') + ') ->' + "\n" + str_2d(x[i], MAXPRINTSIZE);
705+
}
706+
}
707+
}
708+
if (lim < n)
709+
{
710+
if (str.length) str += "\n" + indices.concat(array(size(x).length, function() {return ':';})).map(String).join(' ');
711+
for (i=n-lim; i<n; ++i)
712+
{
713+
if (is_array(x[i]) && is_array(x[i][0]))
714+
{
715+
if (is_array(x[i][0][0]))
716+
{
717+
if (str.length) str += "\n";
718+
str += str_nd(x[i], MAXPRINTSIZE, indices.concat(i));
719+
}
720+
else
721+
{
722+
if (str.length) str += "\n";
723+
str += 'array(' + indices.concat([i, ':', ':']).map(String).join(',') + ') ->' + "\n" + str_2d(x[i], MAXPRINTSIZE);
724+
}
725+
}
726+
}
727+
}
728+
return str;
729+
}
706730

707731
// export it
708732
return TensorView;

src/TensorView.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tensorview.jpg

1 Byte
Loading

test/demo.txt

842 Bytes
Binary file not shown.

test/out.txt

6.91 KB
Binary file not shown.

test/test.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ console.log(R2.toNDArray());
2323
console.log(R2.toArray());
2424
console.log(R2.shape());
2525
for (let [di, i] of t) console.log([di, i.slice()]);
26-
T.forEach((di, i) => console.log([di, i.slice()]))
26+
T.forEach((di, i) => console.log([di, i.slice()]));
2727

2828
const add = (a, b) => a + b;
2929
const mul = (a, b) => a * b;
@@ -47,6 +47,7 @@ const view12S = view12.slice([[2,0,-2],[0,2,2]]);
4747
const view12T = view12S.transpose();
4848
const sum = view1.op(add, view1);
4949
const viewB = TensorView(bigdata, {shape:[5,2,10]});
50+
const viewBB = TensorView(bigdata, {shape:[5,2,5,2]});
5051

5152
console.log(view1.toString());
5253
console.log(view1.toNDArray());
@@ -104,6 +105,11 @@ console.log(view5.toString());
104105
console.log(view5.toNDArray());
105106
console.log(view5.toArray());
106107
console.log('---');
107-
/*console.log(viewB.toString());
108+
console.log(viewB.toString());
109+
console.log('---');
108110
console.log(viewB.toString(4));
109-
console.log('---');*/
111+
console.log('---');
112+
console.log(viewBB.toString());
113+
console.log('---');
114+
console.log(viewBB.toString(4));
115+
console.log('---');

0 commit comments

Comments
 (0)