/// <summary> /// Given <paramref name="_base"/> value raised to power <paramref name="_expo"/> /// </summary> /// <param name="_base">Base value</param> /// <param name="_expo">Exponential value</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPExpo(Token _base, Token _expo, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { if (_expo.tknType != TokenType.NUMBER) { _expo.val = !CheckMatrixAndUpdateVal(_expo, matDict, mode, true) ? throw new Exception(CompilerMessage.EXPO_NOT_SCALAR) : !((MatrisBase <dynamic>)_expo.val).IsScalar() ? throw new Exception(CompilerMessage.MAT_SHOULD_BE_SCALAR) : ((MatrisBase <dynamic>)_expo.val)[0, 0]; } if (CheckMatrixAndUpdateVal(_base, matDict, mode, true)) // base matrix { AssertNotNull(_base); _expo.val = ((MatrisBase <object>)_base.val).Power((dynamic)_expo.val); _expo.tknType = TokenType.MATRIS; Validations.CheckModeAndMatrixReference(mode, _expo.val); } else // base is number { AssertNotNull(_base); AssertNotNull(_expo); _expo.val = CompilerUtils.PowerMethod(double.Parse(_base.val.ToString()), double.Parse(_expo.val.ToString())); _expo.tknType = TokenType.NUMBER; } }
/// <summary> /// Validate given <paramref name="mat"/> match with given compiler <paramref name="mode"/> /// </summary> /// <param name="mode">Compiler mode</param> /// <param name="mat">Matrix to check</param> public static void CheckModeAndReturnType(CompilerDictionaryMode mode, string returntype) { switch (returntype) { case "Matris": { if (mode == CompilerDictionaryMode.Dataframe) { throw new Exception(CompilerMessage.COMPILER_RETURNTYPE_MISMATCH(mode, returntype)); } break; } case "Veri Tablosu": { if (mode == CompilerDictionaryMode.Matrix) { throw new Exception(CompilerMessage.COMPILER_RETURNTYPE_MISMATCH(mode, returntype)); } break; } default: { return; } } }
/// <summary> /// Given <paramref name="_base"/> value in mode <paramref name="_expo"/> /// </summary> /// <param name="_base">Base value</param> /// <param name="_expo">Mode value</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPModulo(Token _base, Token _mode, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { if (_mode.tknType == TokenType.NUMBER) // dynamic % number { CheckMatrixAndUpdateVal(_base, matDict, mode, true); _mode.val = _base.val % (dynamic)(float)_mode.val; _mode.tknType = _base.tknType; } else if (CheckMatrixAndUpdateVal(_mode, matDict, mode, true)) // matris % matris { // base _mode // term to get mod of _baseshould be matrix _mode.val = CheckMatrixAndUpdateVal(_base, matDict, mode, true) || ((MatrisBase <dynamic>)_mode.val).IsScalar() ? _base.val % _mode.val : throw new Exception(CompilerMessage.MOD_MAT_THEN_BASE_MAT); } else { throw new Exception(CompilerMessage.MODULO_FORMATS); } }
/// <summary> /// Detailed documentation about the matrix/dataframe compiler /// </summary> /// <param name="mode">Compiler mode, adds limitation information to the end of returned string depending on this mode</param> /// <returns>Detailed multi-line string explaining rules of the compiler</returns> public static string COMPILER_HELP(CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { return(_compilerHelp + (mode == CompilerDictionaryMode.Matrix ? MAT_LIMITS_HELP : mode == CompilerDictionaryMode.Dataframe ? DF_LIMITS_HELP : MAT_LIMITS_HELP + "\n\n" + DF_LIMITS_HELP)); }
/// <summary> /// Matrix multiplication of given <paramref name="_base"/> with itself <paramref name="_expo"/> times /// </summary> /// <param name="_base">Matrix to use</param> /// <param name="_expo">Exponential to use</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPMatMulByExpo(Token _base, Token _expo, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { if (_expo.tknType != TokenType.NUMBER) { _expo.val = !CheckMatrixAndUpdateVal(_expo, matDict, mode, true) ? throw new Exception(CompilerMessage.EXPO_NOT_SCALAR) : !((MatrisBase <dynamic>)_expo.val).IsScalar() ? throw new Exception(CompilerMessage.MAT_SHOULD_BE_SCALAR) : float.Parse(((MatrisBase <object>)_expo.val)[0, 0].ToString()); if (!(_expo.val is int) && !(_expo.val is float) && !(_expo.val is double)) { throw new Exception(CompilerMessage.EXPO_NOT_SCALAR); } } if (_expo.val < 0) { throw new Exception(CompilerMessage.SPECOP_MATPOWER_EXPO); } else if (_expo.val == 0) { _expo.val = 1; _expo.tknType = TokenType.NUMBER; return; } if (CheckMatrixAndUpdateVal(_base, matDict, mode, true)) { if (!_base.val.IsSquare()) { throw new Exception(CompilerMessage.SPECOP_MATPOWER_SQUARE); } MatrisBase <dynamic> res = _base.val.Copy(); using MatrisBase <dynamic> mat = res is Dataframe ? ((Dataframe)res.Copy()) : res.Copy(); AssertNotNull(_expo); for (int i = 1; i < _expo.val; i++) { res = MatrisMul(res, mat); } _expo.val = res; _expo.tknType = TokenType.MATRIS; } else { throw new Exception(CompilerMessage.SPECOP_MATPOWER_BASE); } Validations.CheckModeAndMatrixReference(mode, _expo.val); }
/// <summary> /// Addition, subtraction, multiplication or division between <paramref name="LHS"/> and <paramref name="RHS"/> /// </summary> /// <param name="symbol">One of : "+", "-", "*", "/"</param> /// <param name="LHS">Left hand side</param> /// <param name="RHS">Right hand side</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPBasic(string symbol, Token LHS, Token RHS, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { CheckMatrixAndUpdateVal(RHS, matDict, mode, true); CheckMatrixAndUpdateVal(LHS, matDict, mode, true); if (RHS.tknType == TokenType.MATRIS) { Validations.CheckModeAndMatrixReference(mode, RHS.val); } if (LHS.tknType == TokenType.MATRIS) { Validations.CheckModeAndMatrixReference(mode, LHS.val); } RHS.tknType = LHS.tknType == TokenType.MATRIS ? TokenType.MATRIS : RHS.tknType; switch (symbol) { case "+": { RHS.val = LHS.val + RHS.val; break; } case "-": { RHS.val = LHS.val - RHS.val; break; } case "*": { RHS.val = LHS.val * RHS.val; break; } case "/": { RHS.val = LHS.val / RHS.val; break; } default: throw new Exception(CompilerMessage.OP_INVALID(symbol)); } }
/// <summary> /// Matrix multiplication of <paramref name="LHS"/> and inversed <paramref name="RHS"/> /// </summary> /// <param name="LHS">Left matrix</param> /// <param name="RHS">Right matrix, inverse of this will be used</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPMatMulWithInverse(Token LHS, Token RHS, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { MatrisBase <dynamic> mat1, mat2; mat1 = CheckMatrixAndUpdateVal(RHS, matDict, mode, true) ? (MatrisBase <dynamic>)RHS.val : throw new Exception(CompilerMessage.OP_BETWEEN_("./", "matrisler")); mat2 = CheckMatrixAndUpdateVal(LHS, matDict, mode, true) ? (MatrisBase <dynamic>)LHS.val : throw new Exception(CompilerMessage.OP_BETWEEN_("./", "matrisler")); RHS.val = MatrisMul <object>(mat2, new MatrisArithmeticService().Inverse(mat1)); Validations.CheckModeAndMatrixReference(mode, RHS.val); }
/// <summary> /// Matrix multiplication of given tokens /// </summary> /// <param name="LHS">Left matrix</param> /// <param name="RHS">Right matrix</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPMatMul(Token LHS, Token RHS, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { MatrisBase <dynamic> matRHS, matLHS; matRHS = CheckMatrixAndUpdateVal(RHS, matDict, mode, true) ? (MatrisBase <dynamic>)RHS.val : throw new Exception(CompilerMessage.OP_BETWEEN_(".*", "matrisler")); matLHS = CheckMatrixAndUpdateVal(LHS, matDict, mode, true) ? (MatrisBase <dynamic>)LHS.val : throw new Exception(CompilerMessage.OP_BETWEEN_(".*", "matrisler")); RHS.val = MatrisMul(matLHS, matRHS); Validations.CheckModeAndMatrixReference(mode, RHS.val); }
/// <summary> /// Given mode was not valid for returning return <paramref name="type"/> /// </summary> /// <param name="mode">Compiler mode</param> /// <param name="type">Return type</param> /// <returns>Message telling user can't use functions which has <paramref name="type"/> return type using this <paramref name="mode"/></returns> public static string COMPILER_RETURNTYPE_MISMATCH(CompilerDictionaryMode mode, string type) { switch (mode) { case CompilerDictionaryMode.Matrix: { return($"Matris derleyici modu {type} tipi dönen fonksiyonlara izin vermez!"); } case CompilerDictionaryMode.Dataframe: { return($"Veri tablosu derleyici modu {type} tipi dönen fonksiyonlara izin vermez!"); } default: { return($"Derleyici modunda bir hata oluştu!"); } } }
/// <summary> /// Given mode was not valid to reference a value /// </summary> /// <param name="mode">Compiler mode</param> /// <returns>Message telling user can't reference to some values using this <paramref name="mode"/></returns> public static string COMPILER_MODE_MISMATCH(CompilerDictionaryMode mode) { switch (mode) { case CompilerDictionaryMode.Matrix: { return($"Matris derleyici modu yalnızca matris referanslarına izin verir!"); } case CompilerDictionaryMode.Dataframe: { return($"Veri tablosu derleyici modu yalnızca veri tablosu referanslarına izin verir!"); } default: { return($"Derleyici modunda bir hata oluştu!"); } } }
/// <summary> /// Validate given <paramref name="mat"/> match with given compiler <paramref name="mode"/> /// </summary> /// <param name="mode">Compiler mode</param> /// <param name="mat">Matrix to check</param> /// <param name="disposeIfInvalid">True if given matrix needs to be disposed after an unsuccessful validation</param> public static void CheckModeAndMatrixReference(CompilerDictionaryMode mode, dynamic mat, bool disposeIfInvalid = false) { if (mode == CompilerDictionaryMode.Dataframe && !(mat is Dataframe)) { if (disposeIfInvalid) { ((Dataframe)mat).Dispose(); } throw new Exception(CompilerMessage.COMPILER_MODE_MISMATCH(mode)); } else if (mode == CompilerDictionaryMode.Matrix && mat is Dataframe dataframe) { if (disposeIfInvalid) { dataframe.Dispose(); } throw new Exception(CompilerMessage.COMPILER_MODE_MISMATCH(mode)); } }
/// <summary> /// Check if given token <paramref name="tkn"/> is a <see cref="MatrisBase{object}"/> and update it's value if needed /// </summary> /// <param name="tkn">Token to check</param> /// <param name="matDict">Matrix dictionary to reference to</param> /// <param name="mode">Compiler mode</param> /// <param name="assertNonNull">Wheter to assert token's value to be non-null after checks and updates</param> /// <returns>True if given token holds a <see cref="MatrisBase{object}"/></returns> public static bool CheckMatrixAndUpdateVal(Token tkn, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix, bool assertNonNull = false) { switch (tkn.tknType) { case TokenType.MATRIS: if (matDict.ContainsKey(tkn.name)) { Validations.CheckModeAndMatrixReference(mode, (dynamic)matDict[tkn.name]); tkn.val = matDict[tkn.name]; } else if (!(tkn.val is MatrisBase <object>)) { throw new Exception(CompilerMessage.NOT_SAVED_MATRIX(tkn.name)); } else { Validations.CheckModeAndMatrixReference(mode, tkn.val); } if (assertNonNull) { AssertNotNull(tkn); } return(true); default: if (assertNonNull) { AssertNotNull(tkn); } return(false); } }
/// <summary> /// Assign <paramref name="RHS"/> matrix or scalar to item named <paramref name="LHS"/> /// </summary> /// <param name="LHS">Left hand side, name will be picked from this</param> /// <param name="RHS">Right hand side, value will be picked from this</param> /// <param name="matDict">Matrix dictionary to refer to if needed</param> public static void OPAssignment(Token LHS, Token RHS, Dictionary <string, MatrisBase <dynamic> > matDict, CompilerDictionaryMode mode = CompilerDictionaryMode.Matrix) { if (LHS.tknType != TokenType.MATRIS) // LHS should just be a valid name for a matrix { throw new Exception(CompilerMessage.EQ_FORMAT); } else { switch (RHS.tknType) { case TokenType.NUMBER: // RHS is scalar { RHS.val = new MatrisBase <dynamic>(1, 1, RHS.val); break; } case TokenType.MATRIS: // RHS is possibly a matrix { if (matDict.ContainsKey(RHS.name)) { Validations.CheckModeAndMatrixReference(mode, (dynamic)matDict[RHS.name]); RHS.val = (dynamic)matDict[RHS.name]; } else if (RHS.val is MatrisBase <object> ) { Validations.CheckModeAndMatrixReference(mode, RHS.val); } else { throw new Exception(CompilerMessage.NOT_SAVED_MATRIX(RHS.name)); } break; } default: { if (!(RHS.val is MatrisBase <object>)) // If RHS is not even a matrix, throw { throw new Exception(CompilerMessage.EQ_FAILED); } Validations.CheckModeAndMatrixReference(mode, RHS.val); break; } } // Update the matrix table accordingly if (matDict.ContainsKey(LHS.name)) { Validations.CheckModeAndMatrixReference(mode, matDict[LHS.name]); /* // THIS PART UPDATES EXISTING MATRIX'S VALUES IN PLACE * if (matDict[LHS.name] is Dataframe && !(RHS.val is Dataframe)) * { * matDict[LHS.name] = new Dataframe(((MatrisBase<object>)RHS.val).GetValues()); * } * else if (RHS.val is Dataframe dataframe && !(matDict[LHS.name] is Dataframe)) * { * matDict[LHS.name] = new MatrisBase<object>(dataframe.GetValues()); * } * else * { * matDict[LHS.name] = RHS.val; * } */ matDict[LHS.name] = RHS.val; } else if (Validations.ValidMatrixName(LHS.name)) { int dfcount = 0; foreach (string name in matDict.Keys) { if (matDict[name] is Dataframe) { dfcount++; } } if (RHS.val is Dataframe) { if (dfcount < (int)DataframeLimits.forDataframeCount) { Validations.CheckModeAndMatrixReference(mode, RHS.val); matDict.Add(LHS.name, RHS.val); } else { throw new Exception(CompilerMessage.DF_LIMIT); } } else if (matDict.Count - dfcount < (int)MatrisLimits.forMatrisCount) { Validations.CheckModeAndMatrixReference(mode, RHS.val); AssertNotNull(RHS); matDict.Add(LHS.name, RHS.val); } else { throw new Exception(CompilerMessage.MAT_LIMIT); } } else // LHS was invalid { if (string.IsNullOrEmpty(LHS.name)) { throw new Exception(CompilerMessage.EQ_FORMAT); } else { throw new Exception(CompilerMessage.MAT_NAME_INVALID); } } } }