realSymetric.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createRealSymmetric = createRealSymmetric;
  6. var _object = require("../../../utils/object.js");
  7. function createRealSymmetric(_ref) {
  8. var config = _ref.config,
  9. addScalar = _ref.addScalar,
  10. subtract = _ref.subtract,
  11. abs = _ref.abs,
  12. atan = _ref.atan,
  13. cos = _ref.cos,
  14. sin = _ref.sin,
  15. multiplyScalar = _ref.multiplyScalar,
  16. inv = _ref.inv,
  17. bignumber = _ref.bignumber,
  18. multiply = _ref.multiply,
  19. add = _ref.add;
  20. /**
  21. * @param {number[] | BigNumber[]} arr
  22. * @param {number} N
  23. * @param {number} prec
  24. * @param {'number' | 'BigNumber'} type
  25. */
  26. function main(arr, N) {
  27. var prec = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : config.epsilon;
  28. var type = arguments.length > 3 ? arguments[3] : undefined;
  29. if (type === 'number') {
  30. return diag(arr, prec);
  31. }
  32. if (type === 'BigNumber') {
  33. return diagBig(arr, prec);
  34. }
  35. throw TypeError('Unsupported data type: ' + type);
  36. }
  37. // diagonalization implementation for number (efficient)
  38. function diag(x, precision) {
  39. var N = x.length;
  40. var e0 = Math.abs(precision / N);
  41. var psi;
  42. var Sij = new Array(N);
  43. // Sij is Identity Matrix
  44. for (var i = 0; i < N; i++) {
  45. Sij[i] = createArray(N, 0);
  46. Sij[i][i] = 1.0;
  47. }
  48. // initial error
  49. var Vab = getAij(x);
  50. while (Math.abs(Vab[1]) >= Math.abs(e0)) {
  51. var _i = Vab[0][0];
  52. var j = Vab[0][1];
  53. psi = getTheta(x[_i][_i], x[j][j], x[_i][j]);
  54. x = x1(x, psi, _i, j);
  55. Sij = Sij1(Sij, psi, _i, j);
  56. Vab = getAij(x);
  57. }
  58. var Ei = createArray(N, 0); // eigenvalues
  59. for (var _i2 = 0; _i2 < N; _i2++) {
  60. Ei[_i2] = x[_i2][_i2];
  61. }
  62. return sorting((0, _object.clone)(Ei), (0, _object.clone)(Sij));
  63. }
  64. // diagonalization implementation for bigNumber
  65. function diagBig(x, precision) {
  66. var N = x.length;
  67. var e0 = abs(precision / N);
  68. var psi;
  69. var Sij = new Array(N);
  70. // Sij is Identity Matrix
  71. for (var i = 0; i < N; i++) {
  72. Sij[i] = createArray(N, 0);
  73. Sij[i][i] = 1.0;
  74. }
  75. // initial error
  76. var Vab = getAijBig(x);
  77. while (abs(Vab[1]) >= abs(e0)) {
  78. var _i3 = Vab[0][0];
  79. var j = Vab[0][1];
  80. psi = getThetaBig(x[_i3][_i3], x[j][j], x[_i3][j]);
  81. x = x1Big(x, psi, _i3, j);
  82. Sij = Sij1Big(Sij, psi, _i3, j);
  83. Vab = getAijBig(x);
  84. }
  85. var Ei = createArray(N, 0); // eigenvalues
  86. for (var _i4 = 0; _i4 < N; _i4++) {
  87. Ei[_i4] = x[_i4][_i4];
  88. }
  89. // return [clone(Ei), clone(Sij)]
  90. return sorting((0, _object.clone)(Ei), (0, _object.clone)(Sij));
  91. }
  92. // get angle
  93. function getTheta(aii, ajj, aij) {
  94. var denom = ajj - aii;
  95. if (Math.abs(denom) <= config.epsilon) {
  96. return Math.PI / 4.0;
  97. } else {
  98. return 0.5 * Math.atan(2.0 * aij / (ajj - aii));
  99. }
  100. }
  101. // get angle
  102. function getThetaBig(aii, ajj, aij) {
  103. var denom = subtract(ajj, aii);
  104. if (abs(denom) <= config.epsilon) {
  105. return bignumber(-1).acos().div(4);
  106. } else {
  107. return multiplyScalar(0.5, atan(multiply(2.0, aij, inv(denom))));
  108. }
  109. }
  110. // update eigvec
  111. function Sij1(Sij, theta, i, j) {
  112. var N = Sij.length;
  113. var c = Math.cos(theta);
  114. var s = Math.sin(theta);
  115. var Ski = createArray(N, 0);
  116. var Skj = createArray(N, 0);
  117. for (var k = 0; k < N; k++) {
  118. Ski[k] = c * Sij[k][i] - s * Sij[k][j];
  119. Skj[k] = s * Sij[k][i] + c * Sij[k][j];
  120. }
  121. for (var _k = 0; _k < N; _k++) {
  122. Sij[_k][i] = Ski[_k];
  123. Sij[_k][j] = Skj[_k];
  124. }
  125. return Sij;
  126. }
  127. // update eigvec for overlap
  128. function Sij1Big(Sij, theta, i, j) {
  129. var N = Sij.length;
  130. var c = cos(theta);
  131. var s = sin(theta);
  132. var Ski = createArray(N, bignumber(0));
  133. var Skj = createArray(N, bignumber(0));
  134. for (var k = 0; k < N; k++) {
  135. Ski[k] = subtract(multiplyScalar(c, Sij[k][i]), multiplyScalar(s, Sij[k][j]));
  136. Skj[k] = addScalar(multiplyScalar(s, Sij[k][i]), multiplyScalar(c, Sij[k][j]));
  137. }
  138. for (var _k2 = 0; _k2 < N; _k2++) {
  139. Sij[_k2][i] = Ski[_k2];
  140. Sij[_k2][j] = Skj[_k2];
  141. }
  142. return Sij;
  143. }
  144. // update matrix
  145. function x1Big(Hij, theta, i, j) {
  146. var N = Hij.length;
  147. var c = bignumber(cos(theta));
  148. var s = bignumber(sin(theta));
  149. var c2 = multiplyScalar(c, c);
  150. var s2 = multiplyScalar(s, s);
  151. var Aki = createArray(N, bignumber(0));
  152. var Akj = createArray(N, bignumber(0));
  153. // 2cs Hij
  154. var csHij = multiply(bignumber(2), c, s, Hij[i][j]);
  155. // Aii
  156. var Aii = addScalar(subtract(multiplyScalar(c2, Hij[i][i]), csHij), multiplyScalar(s2, Hij[j][j]));
  157. var Ajj = add(multiplyScalar(s2, Hij[i][i]), csHij, multiplyScalar(c2, Hij[j][j]));
  158. // 0 to i
  159. for (var k = 0; k < N; k++) {
  160. Aki[k] = subtract(multiplyScalar(c, Hij[i][k]), multiplyScalar(s, Hij[j][k]));
  161. Akj[k] = addScalar(multiplyScalar(s, Hij[i][k]), multiplyScalar(c, Hij[j][k]));
  162. }
  163. // Modify Hij
  164. Hij[i][i] = Aii;
  165. Hij[j][j] = Ajj;
  166. Hij[i][j] = bignumber(0);
  167. Hij[j][i] = bignumber(0);
  168. // 0 to i
  169. for (var _k3 = 0; _k3 < N; _k3++) {
  170. if (_k3 !== i && _k3 !== j) {
  171. Hij[i][_k3] = Aki[_k3];
  172. Hij[_k3][i] = Aki[_k3];
  173. Hij[j][_k3] = Akj[_k3];
  174. Hij[_k3][j] = Akj[_k3];
  175. }
  176. }
  177. return Hij;
  178. }
  179. // update matrix
  180. function x1(Hij, theta, i, j) {
  181. var N = Hij.length;
  182. var c = Math.cos(theta);
  183. var s = Math.sin(theta);
  184. var c2 = c * c;
  185. var s2 = s * s;
  186. var Aki = createArray(N, 0);
  187. var Akj = createArray(N, 0);
  188. // Aii
  189. var Aii = c2 * Hij[i][i] - 2 * c * s * Hij[i][j] + s2 * Hij[j][j];
  190. var Ajj = s2 * Hij[i][i] + 2 * c * s * Hij[i][j] + c2 * Hij[j][j];
  191. // 0 to i
  192. for (var k = 0; k < N; k++) {
  193. Aki[k] = c * Hij[i][k] - s * Hij[j][k];
  194. Akj[k] = s * Hij[i][k] + c * Hij[j][k];
  195. }
  196. // Modify Hij
  197. Hij[i][i] = Aii;
  198. Hij[j][j] = Ajj;
  199. Hij[i][j] = 0;
  200. Hij[j][i] = 0;
  201. // 0 to i
  202. for (var _k4 = 0; _k4 < N; _k4++) {
  203. if (_k4 !== i && _k4 !== j) {
  204. Hij[i][_k4] = Aki[_k4];
  205. Hij[_k4][i] = Aki[_k4];
  206. Hij[j][_k4] = Akj[_k4];
  207. Hij[_k4][j] = Akj[_k4];
  208. }
  209. }
  210. return Hij;
  211. }
  212. // get max off-diagonal value from Upper Diagonal
  213. function getAij(Mij) {
  214. var N = Mij.length;
  215. var maxMij = 0;
  216. var maxIJ = [0, 1];
  217. for (var i = 0; i < N; i++) {
  218. for (var j = i + 1; j < N; j++) {
  219. if (Math.abs(maxMij) < Math.abs(Mij[i][j])) {
  220. maxMij = Math.abs(Mij[i][j]);
  221. maxIJ = [i, j];
  222. }
  223. }
  224. }
  225. return [maxIJ, maxMij];
  226. }
  227. // get max off-diagonal value from Upper Diagonal
  228. function getAijBig(Mij) {
  229. var N = Mij.length;
  230. var maxMij = 0;
  231. var maxIJ = [0, 1];
  232. for (var i = 0; i < N; i++) {
  233. for (var j = i + 1; j < N; j++) {
  234. if (abs(maxMij) < abs(Mij[i][j])) {
  235. maxMij = abs(Mij[i][j]);
  236. maxIJ = [i, j];
  237. }
  238. }
  239. }
  240. return [maxIJ, maxMij];
  241. }
  242. // sort results
  243. function sorting(E, S) {
  244. var N = E.length;
  245. var values = Array(N);
  246. var vectors = Array(N);
  247. for (var k = 0; k < N; k++) {
  248. vectors[k] = Array(N);
  249. }
  250. for (var i = 0; i < N; i++) {
  251. var minID = 0;
  252. var minE = E[0];
  253. for (var j = 0; j < E.length; j++) {
  254. if (abs(E[j]) < abs(minE)) {
  255. minID = j;
  256. minE = E[minID];
  257. }
  258. }
  259. values[i] = E.splice(minID, 1)[0];
  260. for (var _k5 = 0; _k5 < N; _k5++) {
  261. vectors[_k5][i] = S[_k5][minID];
  262. S[_k5].splice(minID, 1);
  263. }
  264. }
  265. return {
  266. values: values,
  267. vectors: vectors
  268. };
  269. }
  270. /**
  271. * Create an array of a certain size and fill all items with an initial value
  272. * @param {number} size
  273. * @param {number} value
  274. * @return {number[]}
  275. */
  276. function createArray(size, value) {
  277. // TODO: as soon as all browsers support Array.fill, use that instead (IE doesn't support it)
  278. var array = new Array(size);
  279. for (var i = 0; i < size; i++) {
  280. array[i] = value;
  281. }
  282. return array;
  283. }
  284. return main;
  285. }