Skip to content

Commit 6be6b40

Browse files
committed
v.2.1.0
* map()/filter() methods * select() method * toTex() method * correct slice() method bypassing some cases * update tests
1 parent 837c64d commit 6be6b40

4 files changed

Lines changed: 58 additions & 25 deletions

File tree

README.md

Lines changed: 9 additions & 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: **2.1.0 in progress** (11 kB minified)
7+
version: **2.1.0** (13 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

@@ -175,6 +175,14 @@ view.forEach(function(item, index, data, view) {/*..*/}, dir=1);
175175
// similar as iterator protocol
176176
for (let [item, index] of view) {/*..*/}
177177

178+
// map method (forward or reverse direction based on `dir` 1 or -1)
179+
// returns view of same shape
180+
otherview = view.map(function(item, index, data, view) {/*..*/}, dir=1);
181+
182+
// filter method (forward or reverse direction based on `dir` 1 or -1)
183+
// returns single dimensional view
184+
otherview = view.filter(function(item, index, data, view) {/*..*/}, dir=1);
185+
178186
// creating an actual copy and not share data is easy to do in various ways, eg:
179187
const viewcopy = TensorView(view.toArray(), {shape: view.shape()});
180188

src/TensorView.js

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ function TensorView(data, o, _)
129129
else
130130
{
131131
is_value = null != data;
132+
if (is_value && (!shape || !shape.length)) shape = [1];
132133
computed_total = total = product(shape);
133134
}
134135

@@ -142,7 +143,7 @@ function TensorView(data, o, _)
142143

143144
if (nd_shape)
144145
{
145-
same_shape = (nd_shape.length === shape.length) && (nd_shape.length === shape.filter(function(dim, axis) {return dim === nd_shape[axis];}).length);
146+
same_shape = (nd_shape === shape) || ((nd_shape.length === shape.length) && (nd_shape.length === shape.filter(function(dim, axis) {return dim === nd_shape[axis];}).length));
146147
if (!same_shape) aux_indices = new Array(nd_shape.length);
147148
}
148149

@@ -367,16 +368,32 @@ function TensorView(data, o, _)
367368
var selfiter = self.iterator("setter", 1),
368369
otheriter = other.iterator("getter", 1),
369370
selfnext, othernext,
370-
index, indices, value;
371+
index, indices, value,
372+
items = 0;
371373
for (;;)
372374
{
373375
othernext = otheriter.next();
374376
if (!othernext || othernext.done)
375377
{
376-
// rewind and continue
377-
otheriter = other.iterator();
378-
othernext = otheriter.next();
378+
if (0 === items)
379+
{
380+
// empty
381+
break;
382+
}
383+
else if (items < total)
384+
{
385+
// rewind and continue
386+
otheriter = other.iterator();
387+
othernext = otheriter.next();
388+
//if (!othernext || othernext.done) break;
389+
}
390+
else
391+
{
392+
// done
393+
break;
394+
}
379395
}
396+
++items;
380397
selfnext = selfiter.next(othernext.value[0]);
381398
if (!selfnext || selfnext.done)
382399
{
@@ -400,6 +417,9 @@ function TensorView(data, o, _)
400417
return permutation.length === permutation.filter(function(pi, i) {return pi === i;}).length ? self /*identity*/ : new TensorView(self, {
401418
shape: permute(shape, permutation)
402419
}, {
420+
select: selector ? function(indices) {
421+
return selector(permute(indices, ipermutation));
422+
} : null,
403423
get: function(indices) {
404424
if (indices.length < ndim) throw "TensorView::get indices do not match shape dimension!";
405425
return self.get(permute(indices, ipermutation));
@@ -439,7 +459,7 @@ function TensorView(data, o, _)
439459
return new TensorView((new TensorView(self.permute(new_in_order), {shape: permute(shape, invperm(new_out_order))})).permute(new_out_order), {shape: shape.slice()});
440460
};
441461
self.slice = function(/*slices*/) {
442-
var slices = compute_slices(is_array(arguments[0], true) ? arguments[0] : ([].slice.call(arguments)), shape),
462+
var slices = compute_slices((1 === arguments.length) && is_array(arguments[0], true) && (arguments[0].length === shape.length) ? arguments[0] : ([].slice.call(arguments)), shape),
443463
new_shape = slices.map(function(slice, axis) {
444464
return compute_slice_length(shape[axis], slice);
445465
}),
@@ -449,9 +469,12 @@ function TensorView(data, o, _)
449469
});
450470
}
451471
;
452-
return shape.length === shape.filter(function(dim, axis) {return dim === new_shape[axis];}).length ? self /*idempotent*/ : new TensorView(self, {
472+
return new TensorView(self, {
453473
shape: new_shape
454474
}, {
475+
select: selector ? function(indices) {
476+
return selector(adjust_indices(indices));
477+
} : null,
455478
get: function(indices) {
456479
if (indices.length < ndim) throw "TensorView::get indices do not match shape dimension!";
457480
return self.get(adjust_indices(indices));
@@ -469,7 +492,7 @@ function TensorView(data, o, _)
469492
}
470493
else
471494
{
472-
return !is_function(selection) && !is_array(selection) ? self : new TensorView(self, {
495+
return !is_function(selection) && !is_array(selection) ? self : new TensorView(selector ? ref : self, {
473496
shape: shape.slice()
474497
}, {
475498
select: is_function(selection) ? function(indices) {
@@ -621,17 +644,19 @@ TensorView[proto] = {
621644
});
622645
return ndarray;
623646
},
624-
toString: function(maxsize, stringify) {
647+
toString: function(maxsize, stringify, i0) {
648+
i0 = i0 || 0;
625649
if (!is_function(stringify)) stringify = to_string;
626650
if (!is_num(maxsize, true)) maxsize = Infinity;
627651
var self = this, shape = self.shape(), ndim = shape.length, ndarray = self.toNDArray();
628-
return 2 < ndim ? str_nd(ndarray, shape, maxsize, stringify) : (2 === ndim ? str_2d(ndarray, shape, maxsize, stringify) : str_1d(ndarray, shape, maxsize, stringify));
652+
return 2 < ndim ? str_nd(ndarray, shape, maxsize, stringify, i0) : (2 === ndim ? str_2d(ndarray, shape, maxsize, stringify) : str_1d(ndarray, shape, maxsize, stringify));
629653
},
630-
toTex: function(maxsize, texify) {
654+
toTex: function(maxsize, texify, i0) {
655+
i0 = i0 || 0;
631656
if (!is_function(texify)) texify = to_string;
632657
if (!is_num(maxsize, true)) maxsize = Infinity;
633658
var self = this, shape = self.shape(), ndim = shape.length, ndarray = self.toNDArray();
634-
return 2 < ndim ? tex_nd(ndarray, shape, maxsize, texify) : (2 === ndim ? tex_2d(ndarray, shape, maxsize, texify) : tex_1d(ndarray, shape, maxsize, texify));
659+
return 2 < ndim ? '\\displaylines{'+tex_nd(ndarray, shape, maxsize, texify, i0)+'}' : (2 === ndim ? tex_2d(ndarray, shape, maxsize, texify) : tex_1d(ndarray, shape, maxsize, texify));
635660
}
636661
};
637662
if (('undefined' !== typeof Symbol) && ('undefined' !== typeof Symbol.iterator))
@@ -949,14 +974,14 @@ function str_2d(x, shape, MAXPRINTSIZE, stringify)
949974
}).join(' ') + ']';
950975
}).join('\n');
951976
}
952-
function str_nd(x, shape, MAXPRINTSIZE, stringify, indices)
977+
function str_nd(x, shape, MAXPRINTSIZE, stringify, i0, indices)
953978
{
954979
if (null == indices) indices = [];
955980
var str = '', ind, i, n, lim;
956981
if (shape.length === 2 + indices.length)
957982
{
958983
ind = [':', ':'].concat(indices);
959-
str += 'array(' + ind.map(String).join(',') + ') ->' + "\n" + str_2d(project(x, ind), shape, MAXPRINTSIZE, stringify);
984+
str += 'array(' + ind.map(function(i) {return is_string(i) ? i : String(i + i0);}).join(',') + ')' + "\n" + str_2d(project(x, ind), shape, MAXPRINTSIZE, stringify);
960985
}
961986
else
962987
{
@@ -965,15 +990,15 @@ function str_nd(x, shape, MAXPRINTSIZE, stringify, indices)
965990
for (i=0; i<lim; ++i)
966991
{
967992
if (str.length) str += "\n";
968-
str += str_nd(x, shape, MAXPRINTSIZE, stringify, indices.concat(i));
993+
str += str_nd(x, shape, MAXPRINTSIZE, stringify, i0, indices.concat(i));
969994
}
970995
if (lim < n)
971996
{
972997
if (str.length) str += "\n:";
973998
for (i=n-lim; i<n; ++i)
974999
{
9751000
if (str.length) str += "\n";
976-
str += str_nd(x, shape, MAXPRINTSIZE, stringify, indices.concat(i));
1001+
str += str_nd(x, shape, MAXPRINTSIZE, stringify, i0, indices.concat(i));
9771002
}
9781003
}
9791004
}
@@ -1003,31 +1028,31 @@ function tex_2d(x, shape, MAXPRINTSIZE, texify)
10031028
}
10041029
return '\\begin{bmatrix}'+ x.map(function(xi) {return xi.map(texify).join(' & \\hskip 1em ');}).join(' \\\\ ') + '\\end{bmatrix}';
10051030
}
1006-
function tex_nd(x, shape, MAXPRINTSIZE, texify, indices)
1031+
function tex_nd(x, shape, MAXPRINTSIZE, texify, i0, indices)
10071032
{
10081033
if (null == indices) indices = [];
10091034
var tex = '', ind, i, n, lim;
10101035
if (shape.length === 2 + indices.length)
10111036
{
10121037
ind = [':', ':'].concat(indices);
1013-
tex += '\\text{array(' + ind.map(String).join(',') + ')}' + " \\\\ " + tex_2d(project(x, ind), shape, MAXPRINTSIZE, texify);
1038+
tex += '\\text{array}(' + ind.map(function(i) {return is_string(i) ? i : String(i + i0);}).join(',') + ')' + " \\\\ " + tex_2d(project(x, ind), shape, MAXPRINTSIZE, texify);
10141039
}
10151040
else
10161041
{
10171042
n = shape[2+indices.length];
10181043
lim = stdMath.min(n, stdMath.round(MAXPRINTSIZE/2));
10191044
for (i=0; i<lim; ++i)
10201045
{
1021-
if (tex.length) tex += " \\\\ ";
1022-
tex += tex_nd(x, shape, MAXPRINTSIZE, texify, indices.concat(i));
1046+
if (tex.length) tex += "\\\\";
1047+
tex += tex_nd(x, shape, MAXPRINTSIZE, texify, i0, indices.concat(i));
10231048
}
10241049
if (lim < n)
10251050
{
10261051
if (tex.length) tex += "\\\\ \\vdots";
10271052
for (i=n-lim; i<n; ++i)
10281053
{
1029-
if (tex.length) tex += " \\\\ ";
1030-
tex += tex_nd(x, shape, MAXPRINTSIZE, texify, indices.concat(i));
1054+
if (tex.length) tex += "\\\\";
1055+
tex += tex_nd(x, shape, MAXPRINTSIZE, texify, i0, indices.concat(i));
10311056
}
10321057
}
10331058
}

0 commit comments

Comments
 (0)