File indexing completed on 2024-04-28 11:20:30

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2016 Ivan Lakhtanov <ivan.lakhtanov@gmail.com>
0004 */
0005 #include "juliaextensions.h"
0006 
0007 #include <QDebug>
0008 #include <KLocalizedString>
0009 
0010 #include "settings.h"
0011 
0012 #include "juliascriptloading.h"
0013 
0014 #define JULIA_EXT_CDTOR(name) Julia##name##Extension::Julia##name##Extension(QObject *parent) : name##Extension(parent) {} \
0015                               Julia##name##Extension::~Julia##name##Extension() {}
0016 
0017 
0018 JULIA_EXT_CDTOR(LinearAlgebra)
0019 
0020 QString JuliaLinearAlgebraExtension::createVector(
0021     const QStringList &entries,
0022     Cantor::LinearAlgebraExtension::VectorType type)
0023 {
0024     QString command;
0025     command += QLatin1String("[");
0026 
0027     QString separator = QLatin1String(type == ColumnVector ? ", " : " ");
0028 
0029     for (const QString &entry : entries) {
0030         command += entry + separator;
0031     }
0032 
0033     command.chop(separator.size());
0034     command += QLatin1String("]\n");
0035 
0036     return command;
0037 }
0038 
0039 QString JuliaLinearAlgebraExtension::createMatrix(
0040     const Cantor::LinearAlgebraExtension::Matrix &matrix)
0041 {
0042     QString command;
0043     command += QLatin1String("[");
0044 
0045     for (const QStringList row : matrix) {
0046         for (const QString entry : row) {
0047             command += entry;
0048             command += QLatin1String(" ");
0049         }
0050         command.chop(1);
0051         command += QLatin1String("; ");
0052     }
0053 
0054     command.chop(2);
0055     command += QLatin1String("]");
0056 
0057     return command;
0058 }
0059 
0060 QString JuliaLinearAlgebraExtension::eigenValues(const QString &matrix)
0061 {
0062     return QString::fromLatin1("eig(%1)[1]").arg(matrix);
0063 }
0064 
0065 QString JuliaLinearAlgebraExtension::eigenVectors(const QString &matrix)
0066 {
0067     return QString::fromLatin1("eig(%1)[2]").arg(matrix);
0068 }
0069 
0070 QString JuliaLinearAlgebraExtension::identityMatrix(int size)
0071 {
0072     return QString::fromLatin1("eye(%1)").arg(size);
0073 }
0074 
0075 QString JuliaLinearAlgebraExtension::invertMatrix(const QString &matrix)
0076 {
0077     return QString::fromLatin1("inv(%1)").arg(matrix);
0078 }
0079 
0080 QString JuliaLinearAlgebraExtension::nullMatrix(int rows, int columns)
0081 {
0082     return QString::fromLatin1("zeros(%1, %2)").arg(rows).arg(columns);
0083 }
0084 
0085 QString JuliaLinearAlgebraExtension::nullVector(
0086     int size,
0087     Cantor::LinearAlgebraExtension::VectorType type)
0088 {
0089     switch (type) {
0090         case ColumnVector:
0091             return QString::fromLatin1("zeros(%1)").arg(size);
0092         case RowVector:
0093             return QString::fromLatin1("zeros(%1, %2)").arg(1).arg(size);
0094         default:
0095             return Cantor::LinearAlgebraExtension::nullVector(size, type);
0096     }
0097 }
0098 
0099 QString JuliaLinearAlgebraExtension::rank(const QString &matrix)
0100 {
0101     return QString::fromLatin1("rank(%1)").arg(matrix);
0102 }
0103 
0104 QString JuliaLinearAlgebraExtension::charPoly(const QString &matrix)
0105 {
0106     return QString::fromLatin1("poly(%1)").arg(matrix);
0107 }
0108 
0109 
0110 JULIA_EXT_CDTOR(Packaging)
0111 
0112 QString JuliaPackagingExtension::importPackage(const QString &package)
0113 {
0114     return QString::fromLatin1("import %1").arg(package);
0115 }
0116 
0117 
0118 JULIA_EXT_CDTOR(Plot)
0119 
0120 QString JuliaPlotExtension::plotFunction2d(
0121     const QString &function,
0122     const QString &variable,
0123     const QString &left,
0124     const QString &right)
0125 {
0126     QString command;
0127     QString limits;
0128 
0129     switch(JuliaSettings::plotExtenstionGraphicPackage())
0130     {
0131         case JuliaSettings::EnumPlotExtenstionGraphicPackage::gr:
0132         {
0133             if (!left.isEmpty() && !right.isEmpty())
0134                 limits = QString::fromLatin1("GR.xlim((%1, %2))\n").arg(left).arg(right);
0135 
0136             command = QString::fromLatin1(
0137                 "import GR\n"
0138                 "\n"
0139                 "%3"
0140                 "GR.plot(%1, %2)"
0141             ).arg(variable).arg(function).arg(limits);
0142             break;
0143         }
0144 
0145         case JuliaSettings::EnumPlotExtenstionGraphicPackage::plots:
0146             if (!left.isEmpty() && !right.isEmpty())
0147                 limits = QString::fromLatin1(", xlims = (%1, %2)").arg(left).arg(right);
0148 
0149             command = QString::fromLatin1(
0150                 "import Plots\n"
0151                 "\n"
0152                 "Plots.plot(%1, %2%3)"
0153             ).arg(variable, function, limits);
0154             break;
0155 
0156         case JuliaSettings::EnumPlotExtenstionGraphicPackage::pyplot:
0157             if (!left.isEmpty() && !right.isEmpty())
0158                 limits = QString::fromLatin1("PyPlot.xlim(%1, %2)\n").arg(left).arg(right);
0159 
0160             command = QString::fromLatin1(
0161                 "import PyPlot\n"
0162                 "\n"
0163                 "%3"
0164                 "PyPlot.plot(%1, %2)"
0165             ).arg(variable, function, limits);
0166             break;
0167 
0168         case JuliaSettings::EnumPlotExtenstionGraphicPackage::gadfly:
0169             if (!left.isEmpty() && !right.isEmpty())
0170                 limits = QString::fromLatin1(", Gadfly.Scale.x_continuous(minvalue=%1, maxvalue=%2)").arg(left).arg(right);
0171 
0172             command = QString::fromLatin1(
0173                 "import Gadfly\n"
0174                 "\n"
0175                 "Gadfly.plot(x=%1, y=%2%3)"
0176             ).arg(variable, function, limits);
0177             break;
0178     }
0179 
0180     return command;
0181 }
0182 
0183 QString JuliaPlotExtension::plotFunction3d(
0184     const QString &function,
0185     const VariableParameter& var1,
0186     const VariableParameter& var2)
0187 {
0188     QString command;
0189 
0190     const Interval& interval1 = var1.second;
0191     const Interval& interval2 = var2.second;
0192 
0193     QString interval1Limits;
0194     QString interval2Limits;
0195 
0196     switch(JuliaSettings::plotExtenstionGraphicPackage())
0197     {
0198         case JuliaSettings::EnumPlotExtenstionGraphicPackage::gr:
0199         {
0200             if (!interval1.first.isEmpty() && !interval1.second.isEmpty())
0201                 interval1Limits = QString::fromLatin1("GR.xlim((%1, %2))\n").arg(interval1.first).arg(interval1.second);
0202 
0203             if (!interval2.first.isEmpty() && !interval2.second.isEmpty())
0204                 interval1Limits = QString::fromLatin1("GR.ylim((%1, %2))\n").arg(interval2.first).arg(interval2.second);
0205 
0206             command = QString::fromLatin1(
0207                 "import GR\n"
0208                 "\n"
0209                 "%4%5"
0210                 "GR.plot3(%1, %2, %3)"
0211             ).arg(interval1.first, interval2.first, function, interval1Limits, interval2Limits);
0212             break;
0213         }
0214 
0215         case JuliaSettings::EnumPlotExtenstionGraphicPackage::plots:
0216             if (!interval1.first.isEmpty() && !interval1.second.isEmpty())
0217                 interval1Limits = QString::fromLatin1(", xlims = (%1, %2)").arg(interval1.first).arg(interval1.second);
0218 
0219             if (!interval2.first.isEmpty() && !interval2.second.isEmpty())
0220                 interval1Limits = QString::fromLatin1(", ylims = (%1, %2)").arg(interval2.first).arg(interval2.second);
0221 
0222             command = QString::fromLatin1(
0223                 "import Plots\n"
0224                 "\n"
0225                 "%4%5"
0226                 "GR.plot3d(%1, %2, %3)"
0227             ).arg(interval1.first, interval2.first, function, interval1Limits, interval2Limits);
0228             break;
0229 
0230         case JuliaSettings::EnumPlotExtenstionGraphicPackage::pyplot:
0231             if (!interval1.first.isEmpty() && !interval1.second.isEmpty())
0232                 interval1Limits = QString::fromLatin1("GR.xlim((%1, %2))\n").arg(interval1.first).arg(interval1.second);
0233 
0234             if (!interval2.first.isEmpty() && !interval2.second.isEmpty())
0235                 interval1Limits = QString::fromLatin1("GR.ylim((%1, %2))\n").arg(interval2.first).arg(interval2.second);
0236 
0237             command = QString::fromLatin1(
0238                 "import GR\n"
0239                 "\n"
0240                 "%4%5"
0241                 "PyPlot.plot3D(%1, %2, %3)"
0242             ).arg(interval1.first, interval2.first, function, interval1Limits, interval2Limits);
0243             break;
0244 
0245         case JuliaSettings::EnumPlotExtenstionGraphicPackage::gadfly:
0246             command = i18n("# Sorry, but Gadfly don't support 3d plots");
0247             break;
0248     }
0249 
0250     return command;
0251 }
0252 
0253 
0254 JULIA_EXT_CDTOR(Script)
0255 
0256 QString JuliaScriptExtension::runExternalScript(const QString &path)
0257 {
0258     return QString::fromLatin1("include(\"%1\")").arg(path);
0259 }
0260 
0261 QString JuliaScriptExtension::scriptFileFilter()
0262 {
0263     return i18n("Julia script file (*.jl)");
0264 }
0265 
0266 QString JuliaScriptExtension::highlightingMode()
0267 {
0268     return QLatin1String("julia");
0269 }
0270 
0271 
0272 JULIA_EXT_CDTOR(VariableManagement)
0273 
0274 const QString JuliaVariableManagementExtension::REMOVED_VARIABLE_MARKER =
0275     QLatin1String("__REM__");
0276 
0277 QString JuliaVariableManagementExtension::addVariable(
0278     const QString &name,
0279     const QString &value)
0280 {
0281     return setValue(name, value);
0282 }
0283 
0284 QString JuliaVariableManagementExtension::setValue(
0285     const QString &name,
0286     const QString &value)
0287 {
0288     return QString::fromLatin1("%1 = %2").arg(name).arg(value);
0289 }
0290 
0291 QString JuliaVariableManagementExtension::removeVariable(const QString &name)
0292 {
0293     // There is no way to completely delete object from scope:
0294     // https://docs.julialang.org/en/v1/manual/faq/#How-do-I-delete-an-object-in-memory?-1
0295     return QString::fromLatin1("%1 = \"%2\"")
0296         .arg(name).arg(REMOVED_VARIABLE_MARKER);
0297 }
0298 
0299 QString JuliaVariableManagementExtension::clearVariables()
0300 {
0301     return loadScript(QLatin1String("variables_cleaner"))
0302         .arg(REMOVED_VARIABLE_MARKER);
0303 }
0304 
0305 QString JuliaVariableManagementExtension::saveVariables(const QString &fileName)
0306 {
0307     return loadScript(QLatin1String("variables_saver")).arg(fileName);
0308 }
0309 
0310 QString JuliaVariableManagementExtension::loadVariables(const QString &fileName)
0311 {
0312     return loadScript(QLatin1String("variables_loader")).arg(fileName);
0313 }