UNPKG

4.26 kBJavaScriptView Raw
1const operators = require('./operators.json')
2const staticProps = require('static-props')
3const toData = require('./toData')
4const tensorProduct = require('tensor-product')
5
6/**
7 * Creates a tensor space that is a class representing a tensor.
8 *
9 * @param {Object} Scalar
10 *
11 * @returns {Function} anonymous with signature (indices)
12 */
13
14function TensorSpace (Scalar) {
15 const multiplication = Scalar.multiplication
16
17 /**
18 * @param {Array} indices
19 */
20
21 return function (indices) {
22 // If dim equals 1 it is like a vector of dimension 1, that is a scalar.
23 // Only dim greater than 1, represents a varying index increase order.
24 // A scalar has order 0.
25 // A vector has order 1.
26 // A matrix has order 2.
27 // Order is also called "rank" or "tensor rank", but, to avoid confusion with
28 // "matrix rank" it is better to call it "order".
29 const order = indices.filter((dim) => dim > 1).length
30
31 // TODO if it is a scalar, return the Scalar
32 // which should be a composition algebra
33 // Then add product tensor to composition algebras.
34 // Finally, a tensor i,j,k should be constructed as the
35 // tensor product of a scalar i,j,k times.
36 const isScalar = (order === 0)
37
38 const dimension = indices.reduce((a, b) => a * b, 1)
39
40 if (isScalar) {
41 staticProps(Scalar)({ order })
42
43 return Scalar
44 }
45
46 // TODO create one for square matrices
47 // Create zero.
48 const zero = indices.reduce((result, dim) => {
49 for (var i = 0; i < dim; i++) {
50 result.push(Scalar.zero)
51 }
52
53 return result
54 }, [])
55
56 /**
57 */
58
59 function Tensor (data) {
60 // validate data
61
62 function validate (item) {
63 if (Scalar.notContains(item)) {
64 throw new TypeError('Invalid data = ' + item)
65 }
66 }
67
68 data.forEach(validate)
69
70 const enumerable = true
71 staticProps(this)({ data }, enumerable)
72
73 staticProps(this)({ order })
74 }
75
76 function staticBinary (operator) {
77 Tensor[operator] = function () {
78 var result = []
79
80 for (var i = 0; i < dimension; i++) {
81 var operands = []
82
83 for (var j = 0; j < arguments.length; j++) {
84 operands.push(toData(arguments[j])[i])
85 }
86
87 result.push(Scalar[operator].apply(null, operands))
88 }
89
90 return result
91 }
92 }
93
94 var myBinaryOperators = ['addition', 'subtraction']
95
96 myBinaryOperators.forEach((operator) => {
97 staticBinary(operator)
98
99 Tensor.prototype[operator] = function () {
100 const args = [].slice.call(arguments)
101 const operands = [this.data].concat(args)
102
103 const data = Tensor[operator].apply(null, operands)
104
105 const tensor = new Tensor(data)
106
107 return tensor
108 }
109 })
110
111 function scalarMultiplication (tensor, scalar) {
112 const tensorData = toData(tensor)
113
114 var result = []
115
116 for (var i = 0; i < dimension; i++) {
117 result.push(multiplication(tensorData[i], scalar))
118 }
119
120 return result
121 }
122
123 Tensor.scalarMultiplication = scalarMultiplication
124
125 Tensor.prototype.scalarMultiplication = function (scalar) {
126 const data = scalarMultiplication(this, scalar)
127
128 return new Tensor(data)
129 }
130
131 Tensor.equality = function (tensor1, tensor2) {
132 const tensorData1 = toData(tensor1)
133 const tensorData2 = toData(tensor2)
134
135 for (var i = 0; i < dimension; i++) {
136 if (Scalar.disequality(tensorData1[i], tensorData2[i])) {
137 return false
138 }
139 }
140
141 return true
142 }
143
144 Tensor.prototype.equality = function (tensor2) {
145 return Tensor.equality(this, tensor2)
146 }
147
148 Tensor.product = function (leftData) {
149 return (rightDim) => {
150 return function (rightData) {
151 return tensorProduct(multiplication, indices, rightDim, leftData, rightData)
152 }
153 }
154 }
155
156 staticProps(Tensor)({
157 order,
158 zero
159 })
160
161 const myOperators = operators.group
162
163 myOperators.forEach((operator) => {
164 operators.aliasesOf[operator].forEach((alias) => {
165 Tensor[alias] = Tensor[operator]
166 Tensor.prototype[alias] = Tensor.prototype[operator]
167 })
168 })
169
170 return Tensor
171 }
172}
173
174module.exports = TensorSpace