blob: 62e4b5a8239940245eab68f0dfe2798b971097dd [file] [log] [blame]
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
part of vector_math_lists;
/// Abstract base class for vector lists. See [Vector2List], [Vector3List], and
/// [Vector4List] for implementations of this class.
abstract class VectorList<T extends Vector> {
final int _vectorLength;
final int _offset;
final int _stride;
final int _length;
final Float32List _buffer;
/// The count of vectors in this list.
int get length => _length;
/// The internal storage buffer of this list.
Float32List get buffer => _buffer;
static int _listLength(int offset, int stride, int vectorLength, int length) {
final width = stride == 0 ? vectorLength : stride;
return offset + width * length;
}
/// Create a new vector list with [length] elements that have a size of
/// [vectorLength]. Optionally it is possible to specify an [offset] in the
/// [buffer] and a [stride] between each vector.
VectorList(int length, int vectorLength, [int offset = 0, int stride = 0])
: _vectorLength = vectorLength,
_offset = offset,
_stride = stride == 0 ? vectorLength : stride,
_length = length,
_buffer = Float32List(
VectorList._listLength(offset, stride, vectorLength, length)) {
if (_stride < _vectorLength) {
throw ArgumentError('Stride cannot be smaller than the vector size.');
}
}
/// Create a new vector list from a list of vectors that have a size of
/// [vectorLength]. Optionally it is possible to specify an [offset] in the
/// [buffer] and a [stride] between each vector.
VectorList.fromList(List<T> list, int vectorLength,
[int offset = 0, int stride = 0])
: _vectorLength = vectorLength,
_offset = offset,
_stride = stride == 0 ? vectorLength : stride,
_length = list.length,
_buffer = Float32List(
offset + list.length * (stride == 0 ? vectorLength : stride)) {
if (_stride < _vectorLength) {
throw ArgumentError('Stride cannot be smaller than the vector size.');
}
for (var i = 0; i < _length; i++) {
store(i, list[i]);
}
}
/// Create a new vector list as a view of [buffer] for vectors that have a
/// size of [vectorLength]. Optionally it is possible to specify an [offset]
/// in the [buffer] and a [stride] between each vector.
VectorList.view(Float32List buffer, int vectorLength,
[int offset = 0, int stride = 0])
: _vectorLength = vectorLength,
_offset = offset,
_stride = stride == 0 ? vectorLength : stride,
_length = (buffer.length - math.max(0, offset - stride)) ~/
(stride == 0 ? vectorLength : stride),
_buffer = buffer {
if (_stride < _vectorLength) {
throw ArgumentError('Stride cannot be smaller than the vector size.');
}
}
int _vectorIndexToBufferIndex(int index) => _offset + _stride * index;
/// Create a new instance of [T].
T newVector();
/// Retrieves the vector at [index] and stores it in [vector].
void load(int index, T vector);
/// Store [vector] in the list at [index].
void store(int index, T vector);
/// Copy a range of [count] vectors beginning at [srcOffset] from [src] into
/// this list starting at [offset].
void copy(VectorList<T> src,
{int srcOffset = 0, int offset = 0, int count = 0}) {
if (count == 0) {
count = math.min(length - offset, src.length - srcOffset);
}
final minVectorLength = math.min(_vectorLength, src._vectorLength);
for (var i = 0; i < count; i++) {
var index = _vectorIndexToBufferIndex(i + offset);
var srcIndex = src._vectorIndexToBufferIndex(i + srcOffset);
for (var j = 0; j < minVectorLength; j++) {
_buffer[index++] = src._buffer[srcIndex++];
}
}
}
/// Retrieves the vector at [index].
T operator [](int index) {
final r = newVector();
load(index, r);
return r;
}
/// Store [v] in the list at [index].
void operator []=(int index, T v) {
store(index, v);
}
}