|
7 | 7 | */
|
8 | 8 |
|
9 | 9 | 'use strict';
|
| 10 | +var b64 = require('base64-arraybuffer'); |
| 11 | +var isPlainObject = require('./is_plain_object'); |
10 | 12 |
|
11 | 13 | var isArray = Array.isArray;
|
12 | 14 |
|
@@ -63,6 +65,112 @@ exports.ensureArray = function(out, n) {
|
63 | 65 | return out;
|
64 | 66 | };
|
65 | 67 |
|
| 68 | +var typedArrays = { |
| 69 | + int8: typeof Int8Array !== 'undefined' ? Int8Array : null, |
| 70 | + uint8: typeof Uint8Array !== 'undefined' ? Uint8Array : null, |
| 71 | + uint8clamped: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : null, |
| 72 | + int16: typeof Int16Array !== 'undefined' ? Int16Array : null, |
| 73 | + uint16: typeof Uint16Array !== 'undefined' ? Uint16Array : null, |
| 74 | + int32: typeof Int32Array !== 'undefined' ? Int32Array : null, |
| 75 | + uint32: typeof Uint32Array !== 'undefined' ? Uint32Array : null, |
| 76 | + float32: typeof Float32Array !== 'undefined' ? Float32Array : null, |
| 77 | + float64: typeof Float64Array !== 'undefined' ? Float64Array : null, |
| 78 | +}; |
| 79 | +exports.typedArrays = typedArrays; |
| 80 | + |
| 81 | + |
| 82 | +exports.decodeTypedArraySpec = function(v) { |
| 83 | + // Assume processed by coerceTypedArraySpec |
| 84 | + v = coerceTypedArraySpec(v); |
| 85 | + var T = typedArrays[v.dtype]; |
| 86 | + var buffer; |
| 87 | + if(v.bvals.constructor === ArrayBuffer) { |
| 88 | + // Already an ArrayBuffer |
| 89 | + buffer = v.bvals; |
| 90 | + } else { |
| 91 | + // Decode, assuming a string |
| 92 | + buffer = b64.decode(v.bvals); |
| 93 | + } |
| 94 | + |
| 95 | + // Check if 1d shape. If so, we're done |
| 96 | + if(v.ndims === 1) { |
| 97 | + // Construct single Typed array over entire buffer |
| 98 | + return new T(buffer); |
| 99 | + } else { |
| 100 | + // Reshape into nested plain arrays with innermost |
| 101 | + // level containing typed arrays |
| 102 | + // We could eventually adopt an ndarray library |
| 103 | + |
| 104 | + // Build cumulative product of dimensions |
| 105 | + var cumulativeShape = v.shape.map(function(a, i) { |
| 106 | + return a * (v.shape[i - 1] || 1); |
| 107 | + }); |
| 108 | + |
| 109 | + // Loop of dimensions in reverse order |
| 110 | + var nestedArray = []; |
| 111 | + for(var dimInd = v.ndims - 1; dimInd > 0; dimInd--) { |
| 112 | + var subArrayLength = v.shape[dimInd]; |
| 113 | + var numSubArrays = cumulativeShape[dimInd - 1]; |
| 114 | + var nextArray = []; |
| 115 | + |
| 116 | + if(dimInd === v.ndims - 1) { |
| 117 | + // First time through, we build the |
| 118 | + // inner most typed arrays |
| 119 | + for(var typedInd = 0; typedInd < numSubArrays; typedInd++) { |
| 120 | + var typedOffset = typedInd * subArrayLength; |
| 121 | + nextArray.push( |
| 122 | + new T(buffer, typedOffset * T.BYTES_PER_ELEMENT, subArrayLength) |
| 123 | + ); |
| 124 | + } |
| 125 | + } else { |
| 126 | + // Following times through, build |
| 127 | + // next layer of nested arrays |
| 128 | + for(var i = 0; i < numSubArrays; i++) { |
| 129 | + var offset = i * subArrayLength; |
| 130 | + nextArray.push(nextArray.slice(offset, offset + subArrayLength - 1)); |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + // Update nested array with next nesting level |
| 135 | + nestedArray = nextArray; |
| 136 | + } |
| 137 | + |
| 138 | + return nestedArray; |
| 139 | + } |
| 140 | +}; |
| 141 | + |
| 142 | +function isTypedArraySpec(v) { |
| 143 | + // Assume v has not passed through |
| 144 | + return isPlainObject(v) && typedArrays[v.dtype] && v.bvals && ( |
| 145 | + Number.isInteger(v.shape) || |
| 146 | + (isArrayOrTypedArray(v.shape) && |
| 147 | + v.shape.length > 0 && |
| 148 | + v.shape.every(function(d) { return Number.isInteger(d); })) |
| 149 | + ); |
| 150 | +} |
| 151 | +exports.isTypedArraySpec = isTypedArraySpec; |
| 152 | + |
| 153 | +function coerceTypedArraySpec(v) { |
| 154 | + // Assume isTypedArraySpec passed |
| 155 | + var coerced = {dtype: v.dtype, bvals: v.bvals}; |
| 156 | + |
| 157 | + // Normalize shape to a list |
| 158 | + if(Number.isInteger(v.shape)) { |
| 159 | + coerced.shape = [v.shape]; |
| 160 | + } else { |
| 161 | + coerced.shape = v.shape; |
| 162 | + } |
| 163 | + |
| 164 | + // Add length property |
| 165 | + coerced.length = v.shape.reduce(function(a, b) { return a * b; }); |
| 166 | + |
| 167 | + // Add ndims |
| 168 | + coerced.ndims = v.shape.length; |
| 169 | + |
| 170 | + return coerced; |
| 171 | +} |
| 172 | +exports.coerceTypedArraySpec = coerceTypedArraySpec; |
| 173 | + |
66 | 174 | /*
|
67 | 175 | * TypedArray-compatible concatenation of n arrays
|
68 | 176 | * if all arrays are the same type it will preserve that type,
|
|
0 commit comments