morilib-apl
Version:
an APL Interpreter
3,218 lines • 104 kB
JavaScript
/*
* Morilib APL
*
* Copyright (c) 2019 Yuichiro MORIGUCHI
*
* This software is released under the MIT License.
* http://opensource.org/licenses/mit-license.php
**/
(function(root) {
var undef = void 0;
/*
* Reference:
* http://my.fit.edu/~gabdo/gamma.txt
*/
var GAMMA_COEFFS = [
0.99999999999999709182,
57.156235665862923517,
-59.597960355475491248,
14.136097974741747174,
-0.49191381609762019978,
.33994649984811888699e-4,
.46523628927048575665e-4,
-.98374475304879564677e-4,
.15808870322491248884e-3,
-.21026444172410488319e-3,
.21743961811521264320e-3,
-.16431810653676389022e-3,
.84418223983852743293e-4,
-.26190838401581408670e-4,
.36899182659531622704e-5
];
var LOG_SQRT_2PI = Math.log(2 * Math.PI) / 2;
var monadic = {
"-": function(array) {
return map(array, function(x) { return -x; }, isNumber);
},
"×": function(array) {
return map(array, function(x) {
return x > 0 ? 1 : x < 0 ? -1 : 0;
}, isNumber);
},
"÷": function(array) {
return map(array, function(x) { return 1 / x; }, isNumber);
},
"ι": function(object1) {
if(isNumber(object1)) {
return iota(object1, 1, 1);
} else if(isString(object1)) {
throw new Error("DOMAIN ERROR");
} else {
throw new Error("NOT SUPPORTED");
}
},
"ρ": function(object1) {
return scalarize(rho(object1));
},
"〆": function(object1) {
return transpose(object1);
},
"*": function(array) {
return map(array, function(x) { return Math.exp(x); }, isNumber);
},
"★": function(array) {
return monadic["*"](array);
},
"☆": function(array) {
return map(array, function(x) {
if(x <= 0) {
throw new Error("DOMAIN ERROR");
}
return Math.log(x);
}, isNumber);
},
"|": function(array) {
return map(array, function(x) { return Math.abs(x); }, isNumber);
},
"「": function(array) {
return map(array, function(x) { return Math.ceil(x); }, isNumber);
},
"」": function(array) {
return map(array, function(x) { return Math.floor(x); }, isNumber);
},
"〇": function(array) {
return map(array, function(x) { return Math.PI * x; }, isNumber);
},
"~": function(array) {
return map(array, function(x) { return x === 0 ? 1 : 0; });
},
"~": function(array) {
return monadic["~"](array);
},
",": function(array) {
return toVector(array);
},
"?": function(array) {
return map(array, function(x) {
if(!(isInteger(x) && x >= 1)) {
throw new Error("DOMAIN ERROR");
}
return Math.floor(Math.random() * x + 1);
});
},
"!": function(array) {
return map(array, function(x) { return gamma(x + 1); }, isNumber);
},
"♯": function(vector) {
return sortVector(vector, false);
},
"♭": function(vector) {
return sortVector(vector, true);
},
"※": function(matrix) {
matrixLib.checkDiag(matrix);
return matrixLib.solveGaussJordan(matrix, matrixLib.makeUnit(matrix.length, matrix.length));
},
"◆": function(array) {
return toStringArray(array, null);
}
};
var dyadic = {
"+": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x + y; }, isNumber);
},
"-": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x - y; }, isNumber);
},
"×": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x * y; }, isNumber);
},
"÷": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x / y; }, isNumber);
},
"ι": function(vector1, object2) {
checkVectorByFunction(vector1, function(x) { return true; });
return map(object2, function(x) {
var result = vector1.indexOf(x);
return result < 0 ? vector1.length + 1 : result + 1;
});
},
"ρ": function(vector1, vector2) {
var vec1 = isArray(vector1) ? vector1 : [vector1],
vec2 = isArray(vector2) ? toVector(vector2) : [vector2];
function gendim(index, dim) {
var result = [],
resultValue,
i,
nowIndex = index;
if(dim >= vec1.length) {
return {
value: isArray(vec2) ? vec2[index] : vec2,
index: index + 1
};
} else {
for(i = 0; i < vec1[dim]; i++) {
resultValue = gendim(index, dim + 1);
index = resultValue.index % vec2.length;
result[i] = resultValue.value;
}
return {
value: result,
index: index
};
}
}
checkVectorByFunction(vec1, function(x) {
return isInteger(x) && x >= 0;
});
if(vec2.length === 0) {
return 0;
} else if(vec1.length === 0) {
return vec2[0];
} else {
return gendim(0, 0).value;
}
},
"*": function(object1, object2) {
function pow(x, y) {
var res,
i;
if(isInteger(y)) {
if(y > 0) {
res = x;
for(i = 1; i < y; i++) {
res *= x;
}
return res;
} else if(y === 0) {
return 1;
} else if(y < 0) {
res = 1 / x;
for(i = 1; i < -y; i++) {
res /= x;
}
return res;
}
} else if(y > 0) {
return Math.pow(x, y);
} else {
throw new Error("DOMAIN ERROR");
}
}
return map2Scalar(object1, object2, function(x, y) { return pow(x, y); }, isNumber);
},
"★": function(object1, object2) {
return dyadic["*"](object1, object2);
},
"☆": function(object1, object2) {
function log(x, y) {
if(x <= 0 || y <= 0) {
throw new Error("DOMAIN ERROR");
}
return Math.log(y) / Math.log(x);
}
return map2Scalar(object1, object2, function(x, y) { return log(x, y); }, isNumber);
},
"|": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) {
if(x === 0) {
return y;
} else if(x > 0 && y >= 0) {
return y % x;
} else if(x > 0 && y <= 0) {
return y % x + x;
} else if(x < 0 && y > 0) {
return y % x + x;
} else {
return y % x;
}
}, isNumber);
},
"「": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) {
return x > y ? x : y;
}, isNumber);
},
"」": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) {
return x < y ? x : y;
}, isNumber);
},
"〇": function(object1, object2) {
var fn;
function fn0(x) {
if(x > 1) {
throw new Error("DOMAIN ERROR");
}
return Math.sqrt(1 - x * x);
}
function fnM1(x) {
if(x < -1 || x > 1) {
throw new Error("DOMAIN ERROR");
}
return Math.asin(x);
}
function fnM2(x) {
if(x < -1 || x > 1) {
throw new Error("DOMAIN ERROR");
}
return Math.acos(x);
}
function fnM4(x) {
if(x < 1) {
throw new Error("DOMAIN ERROR");
}
return Math.sqrt(-1 + x * x);
}
function fnM6(x) {
if(x < 1) {
throw new Error("DOMAIN ERROR");
}
return Math.acosh(x);
}
return map2Scalar(object1, object2, function(x, y) {
function getFn(anInt) {
if(!isInteger(anInt)) {
throw new Error("DOMAIN ERROR");
}
switch(anInt) {
case 0: return fn0;
case 1: return Math.sin;
case 2: return Math.cos;
case 3: return Math.tan;
case 4: return function(x) { return Math.sqrt(1 + x * x); };
case 5: return sinh;
case 6: return cosh;
case 7: return tanh;
case -1: return fnM1;
case -2: return fnM2;
case -3: return Math.atan;
case -4: return fnM4;
case -5: return Math.asinh ? Math.asinh : K;
case -6: return Math.acosh ? fnM6 : K;
case -7: return Math.atanh ? Math.atanh : K;
default: return K;
}
}
fn = getFn(x);
return fn(y);
}, isNumber);
},
"=": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x === y ? 1 : 0 });
},
"≠": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x !== y ? 1 : 0 });
},
"<": function(object1, object2) {
return map2Scalar(object1, object2, relCheck(function(x, y) { return x < y }), isNumber);
},
"≦": function(object1, object2) {
return map2Scalar(object1, object2, relCheck(function(x, y) { return x <= y }), isNumber);
},
">": function(object1, object2) {
return map2Scalar(object1, object2, relCheck(function(x, y) { return x > y }), isNumber);
},
"≧": function(object1, object2) {
return map2Scalar(object1, object2, relCheck(function(x, y) { return x >= y }), isNumber);
},
"^": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x && y ? 1 : 0 });
},
"∧": function(object1, object2) {
return dyadic["^"](object1, object2);
},
"v": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return x || y ? 1 : 0 });
},
"∨": function(object1, object2) {
return dyadic["v"](object1, object2);
},
"†": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return !(x && y) ? 1 : 0 });
},
"‡": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) { return !(x || y) ? 1 : 0 });
},
"〆": function(vector1, array1) {
return substituteArray(vector1, array1);
},
"?": function(number1, number2) {
var extracted = [],
i,
value;
if(!isInteger(number1) || !isInteger(number2)) {
throw new Error("DOMAIN ERROR");
} else if(number1 < 0 || number2 < 0 || number1 > number2) {
throw new Error("DOMAIN ERROR");
}
for(i = 0; i < number1; i++) {
value = Math.floor(Math.random() * number2 + 1);
while(extracted.indexOf(value) >= 0) {
value = Math.floor(Math.random() * number2 + 1);
}
extracted.push(value);
}
return extracted;
},
"!": function(object1, object2) {
return map2Scalar(object1, object2, function(x, y) {
return gamma(y + 1) / gamma(x + 1) / gamma(y - x + 1);
}, isNumber);
},
"↑": function(object1, object2) {
return takeArray(object1, object2);
},
"↓": function(object1, object2) {
return dropArray(object1, object2);
},
"ε": function(object1, object2) {
return belongToArray(object1, object2);
},
"∈": function(object1, object2) {
return dyadic["ε"](object1, object2);
},
"⊥": function(object1, object2) {
return decodeArray(object1, object2);
},
"┴": function(object1, object2) {
return dyadic["⊥"](object1, object2);
},
"┬": function(object1, object2) {
return encodeArray(object1, object2);
},
"※": function(vector1, matrix2) {
var rho1 = rho(vector1),
rho2 = rho(matrix2);
matrixLib.checkMatrix(matrix2);
if(rho1.length !== 1) {
throw new Error("RANK ERROR");
} else if(rho2.length !== 2) {
throw new Error("RANK ERROR");
} else if(vector1.length !== matrix2.length) {
throw new Error("LENGTH ERROR");
}
if(matrixLib.isDiag(matrix2)) {
return matrixLib.solve(matrix2, vector1);
} else {
return leastSquare(matrix2, vector1);
}
},
"◆": function(vector1, object2) {
var vec;
if(isArray(vector1) && vector1.length > 2) {
throw new Error("LENGTH ERROR");
}
return toStringArray(object2, vector1);
}
};
var operator = {
".": function(fn1, fn2) {
return function(array1, array2) {
var result = [],
rhoArray1,
rhoArray2,
rhoArray2a;
function generate1(indicesArray1, rhoArray1, indicesArray2, rhoArray2) {
var fold1,
i;
if(rhoArray1.length > 1) {
for(i = 0; i < rhoArray1[0]; i++) {
generate1(indicesArray1.concat([i]), rhoArray1.slice(1), indicesArray2, rhoArray2);
}
} else if(rhoArray2.length > 0) {
for(i = 0; i < rhoArray2[0]; i++) {
generate1(indicesArray1, rhoArray1, indicesArray2.concat([i]), rhoArray2.slice(1));
}
} else {
fold1 = [];
if(rhoArray1[0] !== rhoArray2a) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < rhoArray2a; i++) {
fold1[i] = fn2(getIndex(array1, indicesArray1.concat([i])), getIndex(array2, [i].concat(indicesArray2)));
}
if(indicesArray1.length + indicesArray2.length > 0) {
setIndex(result, indicesArray1.concat(indicesArray2), fold(fold1, fn1));
} else {
result = fold(fold1, fn1);
}
}
}
function generateLeftScalar(scalar, indicesArray2, rhoArray2) {
var fold1,
i;
if(rhoArray2.length > 0) {
for(i = 0; i < rhoArray2[0]; i++) {
generateLeftScalar(scalar, indicesArray2.concat([i]), rhoArray2.slice(1));
}
} else {
fold1 = [];
for(i = 0; i < rhoArray2a; i++) {
fold1[i] = fn2(scalar, getIndex(array2, [i].concat(indicesArray2)));
}
if(indicesArray2.length > 0) {
setIndex(result, indicesArray2, fold(fold1, fn1));
} else {
result = fold(fold1, fn1);
}
}
}
function generateRightScalar(array1, scalar) {
var result = [],
fold1,
i;
if(!isArray(array1[0])) {
fold1 = [];
for(i = 0; i < array1.length; i++) {
fold1[i] = fn2(array1[i], scalar);
}
return fold(fold1, fn1);
} else {
for(i = 0; i < array1.length; i++) {
result[i] = generateRightScalar(array1[i], scalar);
}
return result;
}
}
if(!isArray(array1) && !isArray(array2)) {
return fn2(array1, array2);
} else if(!isArray(array1)) {
if(array1.length === 0) {
return 0;
} else {
rhoArray2 = rho(array2);
rhoArray2a = rhoArray2[0];
generateLeftScalar(array1, [], rhoArray2.slice(1));
return result;
}
} else if(!isArray(array2)) {
if(array2.length === 0) {
return 0;
} else {
return generateRightScalar(array1, array2);
}
} else if(array1.length === 0 && array2.length === 0) {
return 0;
} else if(array1.length === 0 || array2.length === 0) {
throw new Error("LENGTH ERROR");
} else {
rhoArray1 = rho(array1);
rhoArray2 = rho(array2);
rhoArray2a = rhoArray2[0];
generate1([], rhoArray1, [], rhoArray2.slice(1));
return result;
}
};
}
};
var MAP_APL_CHAR = {
"\u00af": " ̄",
"\u2206": "△",
"\u220a": "∈",
"\u2218": "・",
"\u2223": "|",
"\u223c": "~",
"\u2264": "≦",
"\u2265": "≧",
"\u2308": "「",
"\u230a": "」",
"\u22a4": "┬",
"\u22c6": "★",
"\u2339": "※",
"\u233d": "φ",
"\u233f": "/[1]",
"\u2340": "\\[1]",
"\u2349": "〆",
"\u234b": "♯",
"\u234e": "♪",
"\u2352": "♭",
"\u2355": "◆",
"\u2358": "!",
"\u235f": "☆",
"\u2372": "†",
"\u2371": "‡",
"\u2373": "ι",
"\u2374": "ρ"
};
var MAP_FULLWIDTH = {
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7",
"8": "8",
"9": "9",
"0": "0",
"+": "+",
"-": "-"
};
var MAP_ASCII_STR = {
"~": " ̄",
"*": "×",
"/": "÷",
"max": "「",
"min": "」",
"**": "★",
"log": "☆",
"tri": "〇",
">=": "≧",
"<=": "≦",
"!=": "≠",
"and": "∧",
"or": "∨",
"nand": "†",
"nor": "‡",
"outer": "・",
"rho": "ρ",
"take": "↑",
"drop": "↓",
"/-": "/[1]",
"\\-": "\\[1]",
"rotate": "φ",
"rotate1": "φ[1]",
"transpose": "〆",
"iota": "ι",
"in": "∈",
"asc": "♯",
"desc": "♭",
"domino": "※",
"encode": "┬",
"decode": "⊥",
"eval": "♪",
"tostring": "◆",
"<-": "←"
};
function K(x) {
return x;
}
function isObject(anObject) {
return typeof anObject === "object" && anObject !== null;
}
function isNumber(anObject) {
return typeof anObject === "number";
}
function isString(anObject) {
return typeof anObject === "string";
}
function isArray(anObject) {
return Object.prototype.toString.call(anObject) === '[object Array]';
}
function isInteger(anObject) {
return typeof anObject === 'number' && isFinite(anObject) && Math.floor(anObject) === anObject;
}
function charArrayToString(anObject) {
var result = "",
i;
if(!isArray(anObject)) {
throw new Error("DOMAIN ERROR");
}
for(i = 0; i < anObject.length; i++) {
if(isArray(anObject[i])) {
throw new Error("RANK ERROR");
} else if(!isString(anObject[i]) || anObject[i].length !== 1) {
throw new Error("DOMAIN ERROR");
}
result += anObject[i];
}
return result;
}
function stringToCharArray(aString) {
var result = [],
i;
for(i = 0; i < aString.length; i++) {
result[i] = aString.charAt(i);
}
return result;
}
function getNumberExponent(aNumber) {
var matched,
result;
if(!(matched = /(-?[0-9]*(?:\.[0-9]+)?)[eE]([\+\-][0-9]+)$/.exec(aNumber.toExponential()))) {
return NaN;
}
result = matched[2].replace(/^\+/, "");
return [parseFloat(matched[1]), parseInt(result)];
}
function sinh(x) {
var y = Math.exp(x);
return (y - 1 / y) / 2;
}
function cosh(x) {
var y = Math.exp(x);
return (y + 1 / y) / 2;
}
function tanh(x) {
var y;
if(x === Infinity) {
return 1;
} else if(x === -Infinity) {
return -1;
} else {
y = Math.exp(2 * x);
return (y - 1) / (y + 1);
}
}
/*
* Reference:
* http://my.fit.edu/~gabdo/gamma.txt
*/
function lnGamma0(x) {
var g = 607.0 / 128.0,
r = 0,
s = 0,
t,
k;
if(x > 0) {
for(k = GAMMA_COEFFS.length - 1; k > 0; k--) {
s += GAMMA_COEFFS[k] / (x + k);
}
s += GAMMA_COEFFS[0];
t = x + g + 0.5;
r = (x + 0.5) * Math.log(t);
r -= t;
r += LOG_SQRT_2PI;
r += Math.log(s / x);
return r;
} else {
return NaN;
}
}
function gamma(x) {
function frac(n) {
var i,
result = 1;
for(i = 2; i <= n; i++) {
result *= i;
}
return result;
}
function sum(n) {
var i,
result = 0;
for(i = 1; i < n; i++) {
result += i;
}
return result;
}
if(isInteger(x)) {
if(x >= 1) {
return frac(x - 1);
} else if(x === 0) {
return 1;
} else {
return Infinity;
}
} else if(x > 1) {
return Math.exp(lnGamma0(x));
} else if(x > 0 && x < 1) {
return gamma(x + 1) / x;
} else {
return -Math.PI / Math.sin(Math.PI * x) / x / gamma(-x);
}
}
var matrixLib = {
isDiag: function(matrix) {
if(!isArray(matrix) && matrix.length < 2) {
throw new Error("RANK ERROR");
}
for(i = 0; i < matrix.length; i++) {
if(matrix[i].length !== matrix.length) {
return false;
}
}
return true;
},
checkMatrix: function(matrix) {
var length = -1;
if(!isArray(matrix) && matrix.length < 2) {
throw new Error("RANK ERROR");
}
for(i = 0; i < matrix.length; i++) {
checkVectorByFunction(matrix[i], function(x) { return isNumber(x); });
if(length < 0) {
length = matrix[i].length;
} else if(matrix[i].length !== length) {
throw new Error("LENGTH ERROR");
}
}
},
checkDiag: function(matrix) {
if(!isArray(matrix) && matrix.length < 2) {
throw new Error("RANK ERROR");
}
for(i = 0; i < matrix.length; i++) {
checkVectorByFunction(matrix[i], function(x) { return isNumber(x); });
if(matrix[i].length !== matrix.length) {
throw new Error("LENGTH ERROR");
}
}
},
makeZero: function(sizeI, sizeJ) {
var i,
j,
result = [];
for(i = 0; i < sizeI; i++) {
result[i] = [];
for(j = 0; j < sizeJ; j++) {
result[i][j] = 0;
}
}
return result;
},
makeUnit: function(sizeI, sizeJ) {
var i,
j,
result = [];
for(i = 0; i < sizeI; i++) {
result[i] = [];
for(j = 0; j < sizeJ; j++) {
result[i][j] = i === j ? 1 : 0;
}
}
return result;
},
invertPermutation: function(matrix, permutation) {
var result = [],
i;
for(i = 0; i < permutation.length; i++) {
result[permutation[i]] = matrix[i];
}
return result;
},
columnPermutation: function(matrix, permutation) {
var source = deepcopy(matrix),
result = [],
i,
j;
for(i = 0; i < permutation.length; i++) {
result[i] = [];
for(j = 0; j < permutation.length; j++) {
result[i][permutation[j]] = source[i][j];
}
}
return result;
},
factorizeLU: function(matrix) {
var i,
j,
k,
m,
n,
A,
L,
U,
tA,
P = iota(matrix.length, 0, 1);
matrixLib.checkDiag(matrix);
A = deepcopy(matrix);
L = matrixLib.makeZero(matrix.length, matrix.length);
U = matrixLib.makeZero(matrix.length, matrix.length);
for(k = 0; k < A.length; k++) {
if(A[k][k] === 0) {
for(m = 0; m < A.length; m++) {
if(A[k][m] !== 0) {
tmp = P[m]; P[m] = P[k]; P[k] = tmp;
for(n = 0; n < A.length; n++) {
tmp = A[n][m]; A[n][m] = A[n][k]; A[n][k] = tmp;
}
break;
}
}
if(m >= matrix.length) {
throw new Error("DOMAIN ERROR");
}
}
for(i = 0; i < A[0].length; i++) {
if(i < k) {
L[i][k] = U[k][i] = 0;
} else if(i === k) {
L[i][k] = 1;
U[k][i] = A[k][k];
} else {
L[i][k] = A[i][k] / A[k][k];
U[k][i] = A[k][i];
}
}
tA = deepcopy(A);
for(i = 0; i < A.length; i++) {
A[i][k] = A[k][i] = 0;
}
for(i = k + 1; i < A.length; i++) {
for(j = k + 1; j < A[0].length; j++) {
A[i][j] = tA[i][j] - L[i][k] * U[k][j];
}
}
}
return {
P: P,
L: L,
U: U
};
},
solve: function(matrix, vector) {
var i,
j,
lu,
L,
U,
y = [],
V,
result = [];
lu = matrixLib.factorizeLU(matrix);
L = lu.L;
U = lu.U;
V = vector.slice();
for(i = 0; i < matrix.length; i++) {
y[i] = 0;
for(j = 0; j < i; j++) {
y[i] += L[i][j] * y[j];
}
y[i] = (V[i] - y[i]);
}
for(i = matrix.length - 1; i >= 0; i--) {
result[i] = 0;
for(j = i; j < V.length; j++) {
result[i] += U[i][j] * result[j];
}
result[i] = (y[i] - result[i]) / U[i][i];
}
return matrixLib.invertPermutation(result, lu.P);
},
solveGaussJordan: function(matrix, source) {
var i,
j,
k,
val,
elm,
tmp,
permutation = iota(matrix.length, 0, 1),
m = deepcopy(matrix),
v = deepcopy(source);
matrixLib.checkDiag(matrix);
for(i = 0; i < m.length; i++) {
val = m[i][i];
if(val === 0) {
for(j = 0; j < matrix.length; j++) {
if(matrix[permutation[j]][i] !== 0) {
tmp = permutation[j];
permutation[j] = permutation[i];
permutation[i] = tmp;
tmp = m[j];
m[j] = m[i];
m[i] = tmp;
val = m[i][i];
break;
}
}
if(j >= matrix.length) {
throw new Error("DOMAIN ERROR");
}
}
for(j = 0; j < m[i].length; j++) {
if(i !== j) {
elm = m[j][i] / val;
for(k = 0; k < m.length; k++) {
m[j][k] = m[j][k] - (m[i][k] * elm);
}
if(isArray(v[0])) {
for(k = 0; k < v.length; k++) {
v[j][k] = v[j][k] - (v[i][k] * elm);
}
} else {
v[j] = v[j] - (v[i] * elm);
}
}
}
for(j = 0; j < m[i].length; j++) {
if(i === j) {
for(k = 0; k < m.length; k++) {
if(i === k) {
m[j][k] = 1;
} else {
m[j][k] = m[j][k] / val;
}
}
if(isArray(v[0])) {
for(k = 0; k < v.length; k++) {
v[j][k] = v[j][k] / val;
}
} else {
v[j] = v[j] / val;
}
}
}
}
return matrixLib.columnPermutation(v, permutation);
}
};
function leastSquare(matrix, vector) {
var normalMatrix = [],
normalVector = [],
i,
j,
k;
for(i = 0; i < matrix[0].length; i++) {
normalMatrix[i] = [];
for(j = 0; j < matrix[0].length; j++) {
normalMatrix[i][j] = 0;
for(k = 0; k < matrix.length; k++) {
normalMatrix[i][j] += matrix[k][i] * matrix[k][j];
}
}
}
for(i = 0; i < matrix[0].length; i++) {
normalVector[i] = 0;
for(k = 0; k < matrix.length; k++) {
normalVector[i] += matrix[k][i] * vector[k];
}
}
return matrixLib.solve(normalMatrix, normalVector);
}
function deepcopy(anObject) {
var result;
function copyAll() {
var i;
for(i in anObject) {
if(anObject.hasOwnProperty(i)) {
result[i] = deepcopy(anObject[i]);
}
}
}
if(isArray(anObject)) {
result = [];
copyAll();
return result;
} else if(typeof anObject === 'object' && anObject !== null) {
result = {};
copyAll();
return result;
} else {
return anObject;
}
}
function relCheck(f) {
return function(x, y) {
if(isNumber(x) && isNumber(y)) {
return f(x, y) ? 1 : 0;
} else {
throw new Error("DOMAIN ERROR");
}
}
}
function mapHomomorphism(mapping, source) {
var result = "",
match,
i;
for(i = 0; i < source.length; i++) {
if((match = mapping[source.charAt(i)]) !== undef) {
result += match;
} else {
result += source.charAt(i);
}
}
return result;
}
function scalarize(anArray) {
if(anArray.length === 1 && !isArray(anArray[0])) {
return anArray[0];
} else {
return anArray;
}
}
function getIndex(array1, indexVector) {
if(isArray(array1)) {
if(indexVector.length === 0) {
return array1;
} else if(!isInteger(indexVector[0])) {
throw new Error("DOMAIN ERROR");
} else if(indexVector[0] < 0 || indexVector[0] >= array1.length) {
throw new Error("INDEX ERROR");
}
return getIndex(array1[indexVector[0]], indexVector.slice(1));
} else {
return array1;
}
}
function setIndex(array1, indexVector, value) {
if(array1[indexVector[0]] === undef) {
array1[indexVector[0]] = [];
}
if(!isInteger(indexVector[0])) {
throw new Error("DOMAIN ERROR");
} else if(indexVector[0] < 0 || indexVector[0] >= array1.length) {
throw new Error("INDEX ERROR");
}
if(indexVector.length > 1) {
setIndex(array1[indexVector[0]], indexVector.slice(1), value);
} else {
array1[indexVector[0]] = value;
}
}
function checkVectorByFunction(vector0, fn) {
var i;
if(!isArray(vector0)) {
throw new Error("RANK ERROR");
}
for(i = 0; i < vector0.length; i++) {
if(isArray(vector0[i])) {
throw new Error("RANK ERROR");
} else if(!fn(vector0[i])) {
throw new Error("DOMAIN ERROR");
}
}
}
function checkArrayByFunction(array0, errorMsg, fn) {
var i;
if(isArray(array0)) {
for(i = 0; i < array0.length; i++) {
checkArrayByFunction(array0[i], errorMsg, fn);
}
} else {
if(!fn(array0)) {
throw new Error(errorMsg);
}
}
}
function transpose(array1) {
var result = [];
function walk(array1, indexVector) {
var i;
if(isArray(array1)) {
for(i = 0; i < array1.length; i++) {
walk(array1[i], indexVector.concat([i]));
}
} else {
setIndex(result, indexVector.reverse(), array1);
}
}
if(isArray(array1)) {
walk(array1, []);
return result;
} else {
return array1;
}
}
function substituteArray(vector, array1) {
var result = [],
vec = isArray(vector) ? vector : [vector],
rankVector = rho(array1),
inIndices = [],
max;
function checkVector(vector) {
var i,
j,
max = 0;
for(i = 0; i < vector.length; i++) {
if(isArray(vector[i])) {
throw new Error("RANK ERROR");
} else if(!isInteger(vector[i])) {
throw new Error("DOMAIN ERROR");
}
max = max < vector[i] ? vector[i] : max;
}
if(max <= 0 || max > vector.length) {
throw new Error("DOMAIN ERROR");
}
outer: for(i = 1; i <= max; i++) {
for(j = 0; j < vector.length; j++) {
if(vector[j] === i) {
continue outer;
}
}
throw new Error("DOMAIN ERROR");
}
return max;
}
function subst(outIndices) {
var i,
j,
dest;
if(outIndices.length === max) {
setIndex(result, outIndices, getIndex(array1, inIndices));
} else {
dest = vec.indexOf(outIndices.length + 1);
for(i = 0; i < rankVector[dest]; i++) {
for(j = 0; j < vec.length; j++) {
if(vec[j] === outIndices.length + 1) {
inIndices[j] = i;
}
}
subst(outIndices.concat([i]));
}
}
}
max = checkVector(vec);
if(vec.length !== rankVector.length) {
throw new Error("LENGTH ERROR");
} else if(rankVector.length === 0) {
return array1;
}
subst([]);
return result;
}
function foldOperator(operator) {
return function(axis) {
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
}
return function(array1) {
var rhoVector = rho(array1),
destAxis;
function foldop(array0, level) {
var i,
result;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
for(i = 0; i < array0.length; i++) {
if(i > 0) {
result = operator(result, foldop(array0[i], level + 1));
} else {
result = foldop(array0[i], level + 1);
}
}
} else {
result = [];
for(i = 0; i < array0.length; i++) {
result[i] = foldop(array0[i], level + 1);
}
}
return result;
}
if(!isArray(array1)) {
return array1;
} else if(array1.length === 0) {
return 0;
} else {
destAxis = axis === null ? rho(rhoVector)[0] : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return foldop(array1, 1);
}
};
};
}
function scanOperator(operator) {
return function(axis) {
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
}
return function(array1) {
var rhoVector = rho(array1),
destAxis;
function foldop(array0, level) {
var i,
result;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
result = [];
for(i = 0; i < array0.length; i++) {
if(i > 0) {
result[i] = operator(result[i - 1], foldop(array0[i], level + 1));
} else {
result[i] = foldop(array0[i], level + 1);
}
}
} else {
result = [];
for(i = 0; i < array0.length; i++) {
result[i] = foldop(array0[i], level + 1);
}
}
return result;
}
if(!isArray(array1)) {
return array1;
} else if(array1.length === 0) {
return [];
} else {
destAxis = axis === null ? rho(rhoVector)[0] : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return foldop(array1, 1);
}
};
};
}
function compressArray(vector, array1, axis) {
var rhoVector,
destAxis;
function comp(array0, level) {
var result = [],
i;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
if(vector.length !== array0.length) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < vector.length; i++) {
if(vector[i] !== 0) {
result.push(comp(array0[i], level + 1));
}
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = comp(array0[i], level + 1);
}
}
return result;
}
function compScalar(scalar) {
var result = [],
i;
for(i = 0; i < vector.length; i++) {
if(vector[i] !== 0) {
result.push(scalar);
}
}
return result;
}
function replicate(array0, times, level) {
var result = [],
i,
j;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
for(i = 0; i < array0.length; i++) {
for(j = 0; j < times; j++) {
result[i * times + j] = replicate(array0[i], times, level + 1);
}
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = replicate(array0[i], times, level + 1);
}
}
return result;
}
function replicateScalar(scalar, times) {
var result = [],
i;
for(i = 0; i < times; i++) {
result.push(scalar);
}
return result;
}
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
} else if(vector.length === 0 && array1.length === 0) {
return [];
} else if(isNumber(vector)) {
if(!isArray(array1)) {
return replicateScalar(array1, vector);
} else if(array1.length === 0) {
return [];
} else {
rhoVector = rho(array1);
destAxis = axis === null ? rho(rhoVector)[0] : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return replicate(array1, vector, 1);
}
} else {
checkVectorByFunction(vector, function(x) { return true; });
if(!isArray(array1)) {
return compScalar(array1);
} else if(array1.length === 0) {
throw new Error("LENGTH ERROR");
} else {
rhoVector = rho(array1);
destAxis = axis === null ? rho(rhoVector)[0] : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return comp(array1, 1);
}
}
}
function padArray(rhoVector, level, type) {
var result = [],
i;
if(level === rhoVector.length) {
return isNumber(type) ? 0 : " ";
} else {
for(i = 0; i < rhoVector[level]; i++) {
result[i] = padArray(rhoVector, level + 1, type[0]);
}
return result;
}
}
function expandArray(vector, array1, axis) {
var rhoVector,
rank,
destAxis;
function expand(array0, level) {
var result = [],
count = 0,
i;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
for(i = 0; i < vector.length; i++) {
if(vector[i] !== 0) {
result.push(expand(array0[count], level + 1));
count++;
} else {
result.push(padArray(rhoVector, level, array0[0]));
}
}
if(count !== array0.length) {
throw new Error("LENGTH ERROR");
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = expand(array0[i], level + 1);
}
}
return result;
}
function expandScalar(scalar) {
var result = [],
i;
for(i = 0; i < vector.length; i++) {
if(vector[i] !== 0) {
result.push(scalar);
} else if(isNumber(scalar)) {
result.push(0);
} else {
result.push(" ");
}
}
return result;
}
checkVectorByFunction(vector, function(x) { return true; });
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
} else if(!isArray(array1)) {
return expandScalar(array1);
} else if(vector.length === 0 && array1.length === 0) {
return [];
} else if(array1.length === 0) {
throw new Error("LENGTH ERROR");
} else {
rhoVector = rho(array1);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return expand(array1, 1);
}
}
function rotateArray(array1, array2, axis) {
var rhoVector,
rank,
destAxis,
arrayFixed2 = isArray(array2) ? array2 : [array2],
result = [];
function rotate1(indices, rotatedNum) {
var i,
inIndices,
indicesSet,
rotated;
inIndices = indices.slice();
inIndices.splice(destAxis - 1, 0, 0);
rotated = rotatedNum;
if(!isNumber(rotated)) {
throw new Error("DOMAIN ERROR");
}
rotated = rotated < 0 ? (rotated % rhoVector[destAxis - 1]) + rhoVector[destAxis - 1] : rotated;
inIndices[destAxis - 1] = rotated;
if(inIndices[destAxis - 1] >= rhoVector[destAxis - 1]) {
inIndices[destAxis - 1] -= rhoVector[destAxis - 1];
}
indicesSet = indices.slice();
indicesSet.splice(destAxis - 1, 0, 0);
for(i = 0; i < rhoVector[destAxis - 1]; i++) {
indicesSet[destAxis - 1] = i;
setIndex(result, indicesSet, getIndex(arrayFixed2, inIndices));
inIndices[destAxis - 1]++;
if(inIndices[destAxis - 1] >= rhoVector[destAxis - 1]) {
inIndices[destAxis - 1] -= rhoVector[destAxis - 1];
}
}
}
function rotate(indices, level) {
var i;
if(level > rank) {
rotate1(indices, getIndex(array1, indices));
} else if(level === destAxis) {
rotate(indices, level + 1);
} else {
for(i = 0; i < rhoVector[level - 1]; i++) {
rotate(indices.concat([i]), level + 1);
}
}
}
function rotateScalar(indices, level) {
var i,
inIndices,
indicesSet,
rotated;
if(level > rank) {
rotate1(indices, array1);
} else if(level === destAxis) {
rotateScalar(indices, level + 1);
} else {
for(i = 0; i < rhoVector[level - 1]; i++) {
rotateScalar(indices.concat([i]), level + 1);
}
}
}
function checkLength(rhoVector1, rhoVector2, level) {
if(rhoVector1.length === 0) {
return;
} else if(level === destAxis) {
checkLength(rhoVector1, rhoVector2.slice(1), level + 1);
} else if(rhoVector1[0] === rhoVector2[0]) {
checkLength(rhoVector1.slice(1), rhoVector2.slice(1), level + 1);
} else {
throw new Error("LENGTH ERROR");
}
}
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
} else if(!isArray(array1)) {
if(!isArray(array2)) {
return array2;
} else if(array2.length === 0) {
return [];
}
rhoVector = rho(arrayFixed2);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
rotateScalar([], 1);
return result;
} else {
rhoVector = rho(arrayFixed2);
rank = rho(rhoVector)[0];
if(rank !== rho(rho(array1))[0] + 1) {
throw new Error("RANK ERROR");
}
destAxis = axis === null ? rank : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
checkLength(rho(array1), rhoVector, 1);
rotate([], 1);
return result;
}
}
function reverseArray(array1, axis) {
var rhoVector,
rank,
destAxis,
result = [];
function rev(array0, level) {
var result = [],
i;
if(!isArray(array0)) {
return array0;
} else if(level === destAxis) {
for(i = 0; i < array0.length; i++) {
result[array0.length - i - 1] = rev(array0[i], level + 1);
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = rev(array0[i], level + 1);
}
}
return result;
}
if(axis !== null && !isInteger(axis)) {
throw new Error("AXIS ERROR");
} else if(!isArray(array1)) {
return array1;
} else {
rhoVector = rho(array1);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
if(!isInteger(destAxis) || destAxis < 1 || destAxis > rhoVector.length) {
throw new Error("AXIS ERROR");
}
return rev(array1, 1);
}
}
function toVector(array1) {
function toVec(array0) {
var result,
i;
if(isArray(array0)) {
result = [];
for(i = 0; i < array0.length; i++) {
result = result.concat(toVec(array0[i]));
}
return result;
} else {
return [array0];
}
}
return toVec(array1);
}
function concatenateArray(array1, array2, axis) {
var rhoVector,
rank,
destAxis,
result;
function copy(array1) {
var result = [],
i;
if(isArray(array1)) {
for(i = 0; i < array1.length; i++) {
result[i] = copy(array1[i]);
}
return result;
} else {
return array1;
}
}
function concat(array1, array2, level) {
var result = [],
count,
rhoArray1 = rho(array1),
rhoArray2 = rho(array2),
i;
if(level === destAxis) {
if(!isArray(array1)) {
return concatScalar(array1, array2, level);
} else if(!isArray(array2)) {
return concatScalarRight(array1, array2, level);
}
count = 0;
if(rhoArray1.length === rhoArray2.length) {
for(i = 0; i < array1.length; i++, count++) {
result[count] = copy(array1[i]);
}
for(i = 0; i < array2.length; i++, count++) {
result[count] = copy(array2[i]);
}
} else if(rhoArray1.length + 1 === rhoArray2.length) {
result[0] = copy(array1);
for(i = 0; i < array2.length; i++) {
result[i + 1] = copy(array2[i]);
}
} else if(rhoArray1.length === rhoArray2.length + 1) {
for(i = 0; i < array1.length; i++) {
result[i] = copy(array1[i]);
}
result[i] = copy(array2);
} else {
throw new Error("RANK ERROR");
}
} else if(level > destAxis) {
if(rhoArray1.length !== rhoArray2.length) {
throw new Error("RANK ERROR");
} else if(array1.length !== array2.length) {
throw new Error("LENGTH ERROR");
}
result = [copy(array1)].concat([copy(array2)]);
} else {
if(array1.length !== array2.length) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < array2.length; i++) {
result[i] = concat(array1[i], array2[i], level + 1);
}
}
return result;
}
function copyScalar(level, scalar) {
var result = [],
i;
if(level - 1 < rhoVector.length) {
for(i = 0; i < rhoVector[level - 1]; i++) {
result[i] = copyScalar(level + 1, scalar);
}
return result;
} else {
return scalar;
}
}
function concatScalar(scalar, array2, level) {
var result = [],
i;
if(level === destAxis) {
result[0] = copyScalar(level + 1, scalar);
for(i = 0; i < array2.length; i++) {
result[i + 1] = copy(array2[i]);
}
} else if(level > destAxis) {
result = [copyScalar(level, scalar)].concat([copy(array2)]);
} else {
for(i = 0; i < array2.length; i++) {
result[i] = concatScalar(scalar, array2[i], level + 1);
}
}
return result;
}
function concatScalarRight(array1, scalar, level) {
var result = [],
i;
if(level === destAxis) {
for(i = 0; i < array1.length; i++) {
result[i] = copy(array1[i]);
}
result[i] = copyScalar(level + 1, scalar);
} else if(level > destAxis) {
result = [copy(array1)].concat([copyScalar(level, scalar)]);
} else {
for(i = 0; i < array1.length; i++) {
result[i] = concatScalarRight(array1[i], scalar, level + 1);
}
}
return result;
}
if(axis !== null && axis <= 0) {
throw new Error("AXIS ERROR");
} else if(!isArray(array2)) {
if(array1.length === 0) {
return array2;
}
rhoVector = rho(array1);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
result = concatScalarRight(array1, array2, 1);
} else if(!isArray(array1)) {
if(array2.length === 0) {
return array1;
}
rhoVector = rho(array2);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
result = concatScalar(array1, array2, 1);
} else if(array1.length === 0) {
return array2;
} else if(array2.length === 0) {
return array1;
} else {
rhoVector = rho(array2);
rank = rho(rhoVector)[0];
destAxis = axis === null ? rank : axis;
result = isArray(array1) ? concat(array1, array2, 1) : concatScalar(array2, 1);
}
checkProperArray(result);
return result;
}
function pickUpArray(array1, pickUpIndices) {
function arrayIndices(array0, pickupArray, indices) {
var result,
i;
if(!isArray(pickupArray)) {
if(!isInteger(pickupArray) || pickupArray < 1 || pickupArray > array0.length) {
throw new Error("INDEX ERROR");
}
return pickUp(array0[pickupArray - 1], indices);
} else {
result = [];
for(i = 0; i < pickupArray.length; i++) {
result[i] = arrayIndices(array0, pickupArray[i], indices);
}
return result;
}
}
function pickUp(array0, indices) {
var result,
i;
if(!isArray(array0)) {
return array0;
} else if(isNumber(indices[0])) {
if(!isInteger(indices[0]) || indices[0] < 1 || indices[0] > array0.length) {
throw new Error("INDEX ERROR");
}
return pickUp(array0[indices[0] - 1], indices.slice(1));
} else if(indices[0] === null) {
result = [];
for(i = 0; i < array0.length; i++) {
result[i] = pickUp(array0[i], indices.slice(1));
}
return result;
} else if(isArray(indices[0])) {
return arrayIndices(array0, indices[0], indices.slice(1));
} else {
throw new Error("DOMAIN ERROR");
}
}
if(!isArray(array1)) {
return pickUp([array1], pickUpIndices);
} else if(array1.length === 0) {
throw new Error("INDEX ERROR");
} else if(rho(array1).length !== pickUpIndices.length) {
throw new Error("RANK ERROR");
} else {
return pickUp(array1, pickUpIndices);
}
}
function assignArray(array1, lval, rval) {
function assign(leftIndices, lval, rval) {
var lvalue,
i;
if(isArray(lval) && lval.length === 0) {
if(isArray(rval)) {
throw new Error("RANK ERROR");
}
setIndex(array1, leftIndices, rval);
} else if(isNumber(lval[0])) {
lvalue = getIndex(array1, leftIndices);
if(!isArray(lvalue)) {
throw new Error("RANK ERROR");
} else if(!isInteger(lval[0]) || lval[0] < 1 || lval[0] > array1.length) {
throw new Error("INDEX ERROR");
}
return assign(leftIndices.concat([lval[0] - 1]), lval.slice(1), rval);
} else if(lval[0] === null) {
lvalue = getIndex(array1, leftIndices);
if(!isArray(lvalue) || !isArray(rval)) {
throw new Error("RANK ERROR");
} else if(lvalue.length !== rval.length) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < rval.length; i++) {
assign(leftIndices.concat([i]), lval.slice(1), rval[i]);
}
} else if(isArray(lval[0])) {
lvalue = getIndex(array1, leftIndices);
if(!isArray(lvalue) || !isArray(rval)) {
throw new Error("RANK ERROR");
} else if(lval[0].length !== rval.length) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < rval.length; i++) {
assign(leftIndices.concat([lval[0][i] - 1]), lval.slice(1), rval[i]);
}
} else {
throw new Error("DOMAIN ERROR");
}
}
if(!isArray(array1)) {
throw new Error("RANK ERROR");
} else if(array1.length === 0) {
return array1;
} else {
assign([], lval, rval);
return array1;
}
}
function takeArray(vector1, array1) {
var rhoVector,
vectorFixed1 = isArray(vector1) ? vector1 : [vector1],
arrayFixed1 = isArray(array1) ? array1 : [array1];
function pad(type, length) {
var result = [],
i;
if(isArray(type)) {
for(i = 0; i < length; i++) {
result[i] = pad(type[0], length);
}
return result;
} else {
return isNumber(type) ? 0 : " ";
}
}
function take(array0, level) {
function arr(iStart, iEnd) {
var result = [],
i;
for(i = 0; i < iEnd - iStart; i++) {
if(i + iStart >= 0 && i + iStart < array0.length) {
result[i] = take(array0[i + iStart], level + 1);
} else {
result[i] = pad(array0[0], iEnd - iStart);
}
}
return result;
}
if(!isArray(array0)) {
return array0;
} else if(!isInteger(vectorFixed1[level - 1])) {
throw new Error("DOMAIN ERROR");
} else if(level - 1 >= vectorFixed1.length) {
throw new Error("LENGTH ERROR");
} else if(vectorFixed1[level - 1] > 0) {
return arr(0, vectorFixed1[level - 1]);
} else if(vectorFixed1[level - 1] === 0) {
return arr(0, array0.length);
} else {
return arr(array0.length + vectorFixed1[level - 1], array0.length);
}
}
checkVectorByFunction(vectorFixed1, function(x) {
return isInteger(x);
});
if(arrayFixed1.length === 0) {
return [];
} else if(vectorFixed1.length === 0) {
return array1;
} else {
rhoVector = rho(arrayFixed1);
if(vectorFixed1.length !== rhoVector.length) {
throw new Error("LENGTH ERROR");
}
return take(arrayFixed1, 1);
}
}
function dropArray(vector1, array1) {
var vectorFixed1 = isArray(vector1) ? vector1 : [vector1],
arrayFixed1 = isArray(array1) ? array1 : [array1];
function drop(array0, level) {
function arr(iStart, iEnd) {
var result = [],
i;
for(i = 0; i < iEnd - iStart; i++) {
result[i] = drop(array0[i + iStart], level + 1);
if(isArray(result[i]) && result[i].length === 0) {
return [];
}
}
return result;
}
if(!isArray(array0)) {
return array0;
} else if(level - 1 >= vectorFixed1.length) {
throw new Error("LENGTH ERROR");
} else if(!isInteger(vectorFixed1[level - 1])) {
throw new Error("DOMAIN ERROR");
} else if(vectorFixed1[level - 1] >= array0.length) {
return [];
} else if(vectorFixed1[level - 1] > 0) {
return arr(vectorFixed1[level - 1], array0.length);
} else if(vectorFixed1[level - 1] === 0) {
return arr(0, array0.length);
} else {
return arr(0, array0.length + vectorFixed1[level - 1]);
}
}
checkVectorByFunction(vectorFixed1, function(x) {
return isInteger(x);
});
if(arrayFixed1.length === 0) {
return [];
} else if(vectorFixed1.length === 0) {
return array1;
} else {
if(vectorFixed1.length !== rho(arrayFixed1).length) {
throw new Error("LENGTH ERROR");
}
return drop(arrayFixed1, 1);
}
}
function belongToArray(array1, array2) {
function isElement(element) {
function elem(array0) {
var i;
if(isArray(array0)) {
for(i = 0; i < array0.length; i++) {
if(elem(array0[i])) {
return 1;
}
}
return 0;
} else {
return element === array0;
}
}
return elem(array2);
}
if(!isArray(array1)) {
return isElement(array1) ? 1 : 0;
} else {
return map(array1, isElement);
}
}
function sortVector(vector1, desc) {
var sorted,
vector0,
i;
checkVectorByFunction(vector1, function(x) { return true; });
if(!isArray(vector1)) {
return [];
} else {
sorted = vector1.slice().sort(function(x, y) {
var comp = x < y ? -1 : x > y ? 1 : 0;
return desc ? -comp : comp;
});
vector0 = vector1.slice();
for(i = 0; i < sorted.length; i++) {
sorted[i] = vector0.indexOf(sorted[i]) + 1;
vector0[sorted[i] - 1] = null;
}
return sorted;
}
}
function decodeArray(array1, array2) {
var result = [],
rhoArray1,
rhoArray2,
rhoArray2a;
function decode(indicesArray1, rhoArray1, indicesArray2, rhoArray2) {
var fold1,
i,
maxRepeat,
base,
val;
if(rhoArray1.length > 1) {
for(i = 0; i < rhoArray1[0]; i++) {
decode(indicesArray1.concat([i]), rhoArray1.slice(1), indicesArray2, rhoArray2);
}
} else if(rhoArray2.length > 0) {
for(i = 0; i < rhoArray2[0]; i++) {
decode(indicesArray1, rhoArray1, indicesArray2.concat([i]), rhoArray2.slice(1));
}
} else {
fold1 = val = getIndex(array2, [0].concat(indicesArray2));
maxRepeat = Math.max(rhoArray2a, rhoArray1[0]);
for(i = 1; i < maxRepeat; i++) {
if(i < rhoArray1[0]) {
base = getIndex(array1, indicesArray1.concat([i]));
}
if(i < rhoArray2a) {
val = getIndex(array2, [i].concat(indicesArray2));
}
fold1 = fold1 * base + val;
}
if(indicesArray1.length + indicesArray2.length > 0) {
setIndex(result, indicesArray1.concat(indicesArray2), fold1);
} else {
result = fold1;
}
}
}
function decodeScalar(array1, scalar) {
var result = [],
fold,
i;
if(isArray(array1[0])) {
for(i = 0; i < array1.length; i++) {
result[i] = decodeScalar(array1[i], scalar);
}
return result;
} else {
fold = 0;
for(i = 0; i < array1.length; i++) {
fold = scalar + array1[i] * fold;
}
return fold;
}
}
function decodeScalarLeft(scalar, indicesArray2, rhoArray2) {
var fold1,
i,
val;
if(rhoArray2.length > 0) {
for(i = 0; i < rhoArray2[0]; i++) {
decodeScalarLeft(scalar, indicesArray2.concat([i]), rhoArray2.slice(1));
}
} else {
fold1 = val = getIndex(array2, [0].concat(indicesArray2));
for(i = 1; i < rhoArray2a; i++) {
if(i < rhoArray2a) {
val = getIndex(array2, [i].concat(indicesArray2));
}
fold1 = fold1 * scalar + val;
}
if(indicesArray2.length > 0) {
setIndex(result, indicesArray2, fold1);
} else {
result = fold1;
}
}
}
checkArrayByFunction(array1, "DOMAIN ERROR", function(x) { return isNumber(x); });
checkArrayByFunction(array2, "DOMAIN ERROR", function(x) { return isNumber(x); });
if(!isArray(array1) && !isArray(array2)) {
return array2;
} else if(!isArray(array1)) {
if(array2.length === 0) {
return [];
}
rhoArray2 = rho(array2);
rhoArray2a = rhoArray2[0];
decodeScalarLeft(array1, [], rhoArray2.slice(1));
return result;
} else if(isArray(array2)) {
if(array1.length === 0 || array2.length === 0) {
return [];
}
rhoArray1 = rho(array1);
rhoArray2 = rho(array2);
rhoArray2a = rhoArray2[0];
decode([], rhoArray1, [], rhoArray2.slice(1));
return result;
} else {
if(array1.length === 0) {
return [];
}
return decodeScalar(array1, array2);
}
}
function encodeArray(array1, array2) {
var result = [],
arrayFixed2 = isArray(array2) ? array2 : [array2],
rhoArray2 = rho(arrayFixed2);
function encode(array0) {
var result = [],
rhoArray0 = rho(array0),
i;
function inner1(indicesArray0, indicesArray2) {
var i,
enc,
base;
if(indicesArray2.length < rhoArray2.length) {
for(i = 0; i < rhoArray2[indicesArray2.length]; i++) {
inner1(indicesArray0, indicesArray2.concat([i]));
}
} else {
if(rhoArray0[0] !== arrayFixed2.length) {
throw new Error("LENGTH ERROR");
}
enc = getIndex(arrayFixed2, indicesArray2);
for(i = rhoArray0[0] - 1; i >= 0; i--) {
base = getIndex(array0, [i].concat(indicesArray0));
setIndex(result, [i].concat(indicesArray0).concat(indicesArray2), enc % base);
enc = Math.floor(enc / base);
}
}
}
if(!isArray(array0)) {
return encode([array0]);
} else if(!isArray(array0[0])) {
inner1([], []);
} else if(!isArray(array0[0][0])) {
for(i = 0; i < array0[0].length; i++) {
inner1([i], []);
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = encode(array0[i]);
}
}
return result;
}
function encodeScalar(array0) {
var result = [],
i;
if(isArray(array0)) {
for(i = 0; i < array0.length; i++) {
result[i] = encodeScalar(array0[i]);
}
return result;
} else {
return array0 % array1;
}
}
function encodeScalarRight(array0) {
var result = [],
rhoArray0 = rho(array0),
i;
function inner1(indicesArray0, indicesArray2) {
var i,
enc,
base;
enc = array2;
for(i = rhoArray0[0] - 1; i >= 0; i--) {
base = getIndex(array0, [i].concat(indicesArray0));
setIndex(result, [i].concat(indicesArray0), enc % base);
enc = Math.floor(enc / base);
}
}
if(!isArray(array0)) {
throw new Error("Internal error");
} else if(!isArray(array0[0])) {
inner1([]);
} else if(!isArray(array0[0][0])) {
for(i = 0; i < array0[0].length; i++) {
inner1([i]);
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = encodeScalarRight(array0[i]);
}
}
return result;
}
checkArrayByFunction(array1, "DOMAIN ERROR", function(x) { return isNumber(x); });
checkArrayByFunction(arrayFixed2, "DOMAIN ERROR", function(x) { return isNumber(x); });
if(!isArray(array1)) {
return encodeScalar(array2);
} else if(!isArray(array2)) {
return encodeScalarRight(array1);
} else {
return encode(array1);
}
}
function toStringArray(array1, format) {
function toStringStd(array0) {
var result = [],
resultString,
i;
if(!isArray(array0)) {
if(!isNumber(array0)) {
throw new Error("DOMAIN ERROR");
}
resultString = array0.toString();
resultString = resultString.replace(/-/, " ̄");
resultString = resultString.replace(/e\+?/, "E");
return stringToCharArray(resultString);
} else if(!isArray(array0[0])) {
for(i = 0; i < array0.length; i++) {
if(i > 0) {
result = result.concat([" "]);
}
result = result.concat(toStringStd(array0[i]));
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = toStringStd(array0[i]);
}
}
return result;
}
function toStringFix(array0, total, ptr) {
var result = [],
resultString,
resultLength,
exponent,
i;
if(!isArray(array0)) {
if(!isNumber(array0)) {
throw new Error("DOMAIN ERROR");
}
if(ptr < 0) {
exponent = getNumberExponent(array0);
resultString = exponent[0].toPrecision(-ptr) + "E" + exponent[1].toString();
} else {
resultString = array0.toFixed(ptr);
}
if(total < 0) {
resultString = " " + resultString;
} else if(resultString.length > total) {
throw new Error("DOMAIN ERROR");
} else {
resultLength = resultString.length;
for(i = 0; i < total - resultLength; i++) {
resultString = " " + resultString;
}
}
resultString = resultString.replace(/-/, " ̄");
return stringToCharArray(resultString);
} else if(!isArray(array0[0])) {
for(i = 0; i < array0.length; i++) {
result = result.concat(toStringFix(array0[i], total, ptr));
}
} else {
for(i = 0; i < array0.length; i++) {
result[i] = toStringFix(array0[i], total, ptr);
}
}
return result;
}
if(isArray(array1) && array1.length === 0) {
return [];
} else if(format === null) {
return toStringStd(array1);
} else if(!isArray(format)) {
return toStringFix(array1, -1, format);
} else {
if(isArray(format[0]) || isArray(format[1])) {
throw new Error("RANK ERROR");
} else if(!isNumber(format[0]) || !isNumber(format[1])) {
throw new Error("DOMAIN ERROR");
}
return toStringFix(array1, format[0], format[1]);
}
}
function iota(times, start, step) {
var result = [],
val = start,
i;
start = start === undef ? start : 1;
step = step === undef ? step : 1;
for(i = 0; i < times; i++, val += step) {
result[i] = val;
}
return result;
}
function rho(anArray) {
var result = [],
a1 = anArray,
i;
for(i = 0; isArray(a1); i++, a1 = a1[0]) {
result[i] = a1.length;
}
return result;
}
function map(anObject, action, validate) {
var result = [],
i;
if(!isArray(anObject)) {
if(validate && !validate(anObject)) {
throw new Error("DOMAIN ERROR");
}
return action(anObject);
}
for(i = 0; i < anObject.length; i++) {
result[i] = map(anObject[i], action, validate);
}
return result;
}
function map2(array1, array2, action, validate) {
var result = [],
i;
if(!isArray(array1) && !isArray(array2)) {
if(validate && (!validate(array1) || !validate(array2))) {
throw new Error("DOMAIN ERROR");
}
return action(array1, array2);
} else if(!(isArray(array1) && isArray(array2))) {
throw new Error("RANK ERROR");
} else if(array1.length !== array2.length) {
throw new Error("LENGTH ERROR");
}
for(i = 0; i < array1.length; i++) {
result[i] = map2(array1[i], array2[i], action, validate);
}
return result;
}
function map2Scalar(object1, object2, action, validate) {
if(isArray(object1) && !isArray(object2)) {
return map(object1, function(x) {
return action(x, object2);
});
} else if(!isArray(object1) && isArray(object2)) {
return map(object2, function(x) {
return action(object1, x);
});
} else if(!isArray(object1) && !isArray(object2)) {
return action(object1, object2);
} else {
if(rho(rho(object1))[0] !== rho(rho(object2))[0]) {
throw new Error("RANK ERROR");
}
return map2(object1, object2, action, validate);
}
}
function outerProduct(fn) {
return function(array1, array2) {
function walk(array1) {
var result = [],
i;
if(isArray(array1)) {
for(i = 0; i < array1.length; i++) {
result[i] = walk(array1[i]);
}
return result;
} else {
return map2Scalar(array1, array2, fn);
}
}
return walk(array1);
};
}
function mapSingle(vector, action) {
var result = [],
i;
for(i = 0; i < vector.length; i++) {
result[i] = action(vector[i]);
}
return result;
}
function fold(array1, action) {
var result = null,
i;
for(i = 0; i < array1.length; i++) {
result = result === null ? array1[i] : action(result, array1[i]);
}
return result;
}
function convertChar(program) {
var result = program,
PTN_KEYWORD = /('[^'\n]+')|(?:#([^#\n]+)#)/g;
function convertASCII(entire, quote, keyword) {
var result;
if(quote) {
return quote;
} else {
result = MAP_ASCII_STR[keyword];
if(!result) {
throw new Error("Invalid keyword: " + keyword);
}
return result;
}
}
result = result.replace(/ /g, " ");
result = result.trim();
result = mapHomomorphism(MAP_APL_CHAR, result);
result = mapHomomorphism(MAP_FULLWIDTH, result);
result = result.replace(PTN_KEYWORD, convertASCII);
return result;
}
function parseAPL(program, env) {
var NUMBER = /[▲ ̄]?[0-9]+(\.[0-9]+)?(E[0-9]+)?/g,
STRING = /'[^'\n]*'/g,
BLANK = /[ \t]+/g,
VARIABLE = /[\x41-\x5a\u25b3\u3040-\u309f\u30a0-\u30fa\u30fc-\u30fe\u4e00-\u9fff\uff21-\uff3a\uff41-\uff5a\uff66-\uff9f][0-9\x41-\x5a\u25b3\u3040-\u309f\u30a0-\u30fa\u30fc-\u30fe\u4e00-\u9fff\uff10-\uff19\uff21-\uff3a\uff41-\uff5a\uff66-\uff9f]*/g,
ASSIGN = /←/,
OUTERPRODUCT = /・./;
function parseAPLFloat(x) {
var repl = x;
repl = repl.replace(/[▲ ̄]/, "-");
return parseFloat(repl);
}
function getString(aString) {
var result = [],
i;
for(i = 1; i < aString.length - 1; i++) {
result[i - 1] = aString.charAt(i);
}
return result.length !== 1 ? result : result[0];
}
function getVariable(varName) {
return varName;
}
function skipBlankIndex(index) {
var result;
BLANK.lastIndex = index;
result = BLANK.exec(program);
if(result && result.index === index) {
return BLANK.lastIndex;
} else {
return index;
}
}
function skipBlank(index, attr) {
BLANK.lastIndex = index;
result = BLANK.exec(program);
if(result && result.index === index) {
return {
lastIndex: BLANK.lastIndex,
attr: attr
};
} else {
return {
lastIndex: index,
attr: attr
};
}
}
function parseRegex(regex, action, index, attr) {
var result;
regex.lastIndex = index;
result = regex.exec(program);
if(result && result.index === index) {
return skipBlank(regex.lastIndex, action(result[0]));
}
}
function walkOperator(index, attr) {
var op2,
ch;
ch = program.charAt(index);
if(operator[ch]) {
if(index >= program.length || !(op2 = dyadic[program.charAt(index + 1)])) {
throw new Error("SYNTAX ERROR");
}
return walkOperator(skipBlankIndex(index + 2), operator[ch](attr, op2));
} else {
return skipBlank(index, attr);
}
}
function walkFunction(index, attr) {
var result,
resultOp,
resultAxis,
outerOp,
ch;
if(index >= program.length) {
return skipBlank(index, attr);
}
ch = program.charAt(index);
if(ch === ")") {
return skipBlank(skipBlankIndex(index + 1), attr);
} else if(ch === "(") {
return walk(index + 1, []);
} else if(ch === "/") {
resultAxis = walkFoldAxis(skipBlankIndex(index + 1));
result = walk(resultAxis.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [compressArray, attr, result.attr, resultAxis.attr]
}
};
} else if(ch === "\\") {
resultAxis = walkFoldAxis(skipBlankIndex(index + 1));
result = walk(resultAxis.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [expandArray, attr, result.attr, resultAxis.attr]
}
};
} else if(ch === "φ") {
resultAxis = walkFoldAxis(skipBlankIndex(index + 1));
result = walk(resultAxis.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [rotateArray, attr, result.attr, resultAxis.attr]
}
};
} else if(ch === ",") {
resultAxis = walkFoldAxis(skipBlankIndex(index + 1));
result = walk(resultAxis.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [concatenateArray, attr, result.attr, resultAxis.attr]
}
};
} else if(dyadic[ch]) {
resultOp = walkOperator(skipBlankIndex(index + 1), dyadic[ch]);
result = walk(resultOp.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [resultOp.attr, attr, result.attr]
}
};
} else if(OUTERPRODUCT.test(program.substring(index, index + 2))) {
if(!(outerOp = dyadic[program.charAt(index + 2)])) {
throw new Error("SYNTAX ERROR");
}
result = walk(skipBlankIndex(index + 3), []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [outerProduct(outerOp), attr, result.attr]
}
};
} else {
return skipBlank(index, attr);
}
}
function walkAssign(index, attr) {
var result,
rval,
varName;
if(!(result = parseRegex(VARIABLE, K, index, attr))) {
return null;
}
varName = result.attr;
if(!ASSIGN.test(program.charAt(result.lastIndex))) {
return null;
}
rval = walk(skipBlankIndex(result.lastIndex + 1), []);
if(rval) {
return skipBlank(rval.lastIndex, {
assign: {
name: result.attr,
val: rval.attr
}
});
} else {
return null;
}
}
function walkPickUpElement(index) {
var result = [],
result1,
i;
if(program.charAt(index) === ";") {
result.push(null);
result1 = {
lastIndex: index
};
} else if(!!(result1 = walk(index, []))) {
result.push(result1.attr);
} else {
return null;
}
while(program.charAt(result1.lastIndex) === ";") {
result1 = skipBlank(result1.lastIndex, result1.attr);
if(/[;\]]/.test(program.charAt(result1.lastIndex + 1))) {
result.push(null);
result1 = skipBlank(result1.lastIndex + 1, result1.attr);
} else if(!(result1 = walk(skipBlankIndex(result1.lastIndex + 1), []))) {
throw new Error("SYNTAX ERROR");
} else {
result.push(result1.attr);
}
}
for(i = 0; i < result.length; i++) {
result[i] = execInternal(result[i], env);
}
return skipBlank(result1.lastIndex, result);
}
function walkPickUp(index, attr) {
var result,
index1;
if(program.charAt(index) !== "[") {
return null;
}
index1 = skipBlankIndex(index + 1);
if(program.charAt(index1) === "]") {
return {
lastIndex: skipBlankIndex(index1),
attr: attr.length > 1 ? attr : attr[0]
}
}
result = walkPickUpElement(index1, attr);
if(program.charAt(result.lastIndex) !== "]") {
throw new Error("SYNTAX ERROR");
}
return skipBlank(skipBlankIndex(result.lastIndex + 1), {
apply: [pickUpArray, attr.length > 1 ? attr : attr[0], result.attr]
});
}
function walkVariablePickUp(index, attr) {
var result,
resultRval,
varName,
index1;
if(!(result = parseRegex(VARIABLE, K, index, attr))) {
return null;
}
varName = result.attr;
if(program.charAt(result.lastIndex) !== "[") {
return null;
}
result = walkPickUpElement(skipBlankIndex(result.lastIndex + 1), attr);
if(program.charAt(result.lastIndex) !== "]") {
throw new Error("SYNTAX ERROR");
}
index1 = skipBlankIndex(result.lastIndex + 1);
if(ASSIGN.test(program.charAt(index1))) {
index1 = skipBlankIndex(index1 + 1);
resultRval = walk(index1, []);
return skipBlank(result.lastIndex, {
apply: [assignArray, { variable: varName }, result.attr, resultRval.attr]
});
} else {
return skipBlank(index1, {
apply: [pickUpArray, { variable: varName }, result.attr]
});
}
}
function walkAfterMonadic(index, attr) {
var result,
resultConcat,
ch;
ch = program.charAt(index);
if(ch === "(") {
result = walk(skipBlankIndex(index + 1), []);
return walkAfterMonadic(result.lastIndex, attr.concat([result.attr]));
} else if(!!(result = walkAssign(index, attr))) {
return result;
} else if(!!(result = walkPickUp(index, attr))) {
return result;
} else if(!!(result = walkVariablePickUp(index, attr))) {
return result;
} else if(!!(result = parseRegex(NUMBER, parseAPLFloat, index, attr)) ||
!!(result = parseRegex(STRING, getString, index, attr))) {
resultConcat = attr.concat([result.attr]);
return walkAfterMonadic(result.lastIndex, resultConcat);
} else if(!!(result = parseRegex(VARIABLE, getVariable, index, attr))) {
resultConcat = attr.concat([{
variable: result.attr
}]);
return walkAfterMonadic(result.lastIndex, resultConcat);
} else {
if(attr.length === 0) {
throw new Error("SYNTAX ERROR");
}
return walkFunction(index, {
"createArray": attr.length > 1 ? attr : attr[0]
});
}
}
function walkFoldAxis(index) {
var result;
if(program.charAt(index) === "[") {
result = walk(skipBlankIndex(index + 1), []);
if(program.charAt(result.lastIndex) !== "]") {
throw new Error("SYNTAX ERROR");
}
return skipBlank(skipBlankIndex(result.lastIndex + 1), result.attr);
} else {
return skipBlank(index, null);
}
}
function walkFold(index, attr) {
var result;
if(program.charAt(index) === "/") {
result = walkFoldAxis(skipBlankIndex(index + 1));
return {
lastIndex: result.lastIndex,
attr: execInternal({
apply: [foldOperator(attr), result.attr]
}, env)
};
} else if(program.charAt(index) === "\\") {
result = walkFoldAxis(skipBlankIndex(index + 1));
return {
lastIndex: result.lastIndex,
attr: execInternal({
apply: [scanOperator(attr), result.attr]
}, env)
};
} else {
return null;
}
}
function walk(index, attr) {
var result,
resultFold,
resultAxis,
resultEval,
ch,
toEval;
if(index >= program.length) {
return {
lastIndex: index,
attr: attr
};
}
ch = program.charAt(index);
if(dyadic[ch]) {
resultFold = walkFold(skipBlankIndex(index + 1), dyadic[ch]);
if(resultFold) {
result = walk(resultFold.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [resultFold.attr, result.attr]
}
};
}
}
if(monadic[ch]) {
result = walk(skipBlankIndex(index + 1), []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [monadic[ch], result.attr]
}
};
} else if(ch === "φ") {
resultAxis = walkFoldAxis(skipBlankIndex(index + 1));
result = walk(resultAxis.lastIndex, []);
return {
lastIndex: result.lastIndex,
attr: {
apply: [reverseArray, result.attr, resultAxis.attr]
}
};
} else if(ch === "♪") {
result = walk(skipBlankIndex(index + 1), []);
return {
lastIndex: result.lastIndex,
attr: {
eval: result.attr
}
};
} else {
return walkAfterMonadic(index, attr);
}
}
return walk(0, []).attr;
}
function execInternal(internal, env) {
var result,
toApply,
toEval,
i;
if(!isObject(internal) || isArray(internal)) {
return internal;
} else if(internal.apply !== undef) {
toApply = [];
for(i = internal.apply.length - 1; i >= 1; i--) {
toApply[i - 1] = execInternal(internal.apply[i], env);
}
return internal.apply[0].apply(null, toApply);
} else if(internal.variable !== undef) {
if(env[internal.variable] === undef) {
throw new Error("VALUE ERROR");
}
return env[internal.variable];
} else if(internal.createArray !== undef) {
if(isArray(internal.createArray)) {
result = [];
for(i = 0; i < internal.createArray.length; i++) {
result[i] = execInternal(internal.createArray[i], env);
}
} else {
result = execInternal(internal.createArray, env);
}
checkProperArray(result, true);
return result;
} else if(internal.assign !== undef) {
env[internal.assign.name] = execInternal(internal.assign.val, env);
return env[internal.assign.name];
} else if(internal.eval !== undef) {
toEval = convertChar(charArrayToString(execInternal(internal.eval, env)));
result = parseAPL(toEval, env);
return execInternal(result);
} else {
throw new Error("Internal Error");
}
}
function extractString(array0) {
function extract(array0) {
var result = [],
i;
if(isString(array0)) {
if(array0.length > 1) {
return stringToCharArray(array0);
} else if(array0.length === 1) {
return array0;
} else {
return [];
}
} else if(isArray(array0)) {
for(i = 0; i < array0.length; i++) {
result[i] = extract(array0[i]);
}
return result;
} else {
return array0;
}
}
return extract(array0);
}
function checkProperArray(array0, allowEmpty) {
function lengthArray(array0) {
var length = -1,
i;
if(!isArray(array0)) {
return 0;
} else {
if(!allowEmpty && array0.length === 0) {
throw new Error("DOMAIN ERROR");
}
for(i = 0; i < array0.length; i++) {
if(length < 0) {
length = lengthArray(array0[i]);
} else if(lengthArray(array0[i]) !== length) {
throw new Error("LENGTH ERROR");
}
}
return array0.length;
}
}
function notMixedArray(array0) {
var type = null;
function walk(array0) {
var i;
if(isArray(array0)) {
for(i = 0; i < array0.length; i++) {
walk(array0[i]);
}
} else if(type === null) {
type = typeof array0;
} else if(type !== typeof array0) {
throw new Error("DOMAIN ERROR");
}
}
walk(array0);
}
if(isArray(array0)) {
if(!allowEmpty && array0.length === 0) {
throw new Error("DOMAIN ERROR");
}
lengthArray(array0);
notMixedArray(array0);
} else if(!(isNumber(array0) || isString(array0))) {
throw new Error("DOMAIN ERROR");
}
}
function createEnv(env) {
var innerEnv = env ? deepcopy(env) : {},
me;
me = {
put: function(name, anObject) {
var source = extractString(anObject);
checkProperArray(source);
env[name] = source;
},
eval: function(program) {
var converted,
internal;
converted = convertChar(program);
internal = parseAPL(converted, innerEnv);
return execInternal(internal, innerEnv);
}
};
return me;
}
if(typeof module !== "undefined" && module.exports) {
module.exports = createEnv;
} else {
root["KANAPL"] = createEnv;
}
})(this);