Warning, file /education/kmplot/kmplot/function.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KmPlot - a math. function plotter for the KDE-Desktop 0003 0004 SPDX-FileCopyrightText: 1998, 1999, 2000, 2002 Klaus-Dieter Möller <kd.moeller@t-online.de> 0005 SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org> 0006 0007 This file is part of the KDE Project. 0008 KmPlot is part of the KDE-EDU Project. 0009 0010 SPDX-License-Identifier: GPL-2.0-or-later 0011 0012 */ 0013 0014 #ifndef FUNCTION_H 0015 #define FUNCTION_H 0016 0017 #include "vector.h" 0018 0019 #include <QByteArray> 0020 #include <QColor> 0021 #include <QFlags> 0022 #include <QGradient> 0023 #include <QVector> 0024 0025 class Equation; 0026 class Function; 0027 class Plot; 0028 0029 /** 0030 * Maximum number of plus-minus-s; each added one doubles the number of combinations 0031 * which quickly grows. So put a bound on the number allowed. 0032 */ 0033 extern int MAX_PM; 0034 0035 /** 0036 * This stores a string which evaluates directly to a number (i.e. without any 0037 * input variables such as x). 0038 */ 0039 class Value 0040 { 0041 public: 0042 /** 0043 * Initializes Value with \p expression. 0044 * This will have the value 0 if \p expression is empty or unparsable. 0045 */ 0046 Value(const QString &expression = QString()); 0047 /** 0048 * Converts \p value to a string (see Parser::number) and initializes 0049 * this with the \p value. 0050 */ 0051 explicit Value(double value); 0052 0053 /** 0054 * @return The value of the current expression. 0055 */ 0056 double value() const 0057 { 0058 return m_value; 0059 } 0060 /** 0061 * @return The current expression. 0062 */ 0063 QString expression() const 0064 { 0065 return m_expression; 0066 } 0067 /** 0068 * Sets the current expression. If the expression could be evaluated 0069 * (i.e. no errors), then value is updated, the expression is saved and 0070 * true is returned. Otherwise, just returns false. 0071 */ 0072 bool updateExpression(const QString &expression); 0073 /** 0074 * Converts \p value to a string (see Parser::number) and uses it for 0075 * the current expression. 0076 */ 0077 void updateExpression(double value); 0078 /** 0079 * This checks if the expression strings (and hence values) are 0080 * identical. 0081 */ 0082 bool operator==(const Value &other) const; 0083 /** 0084 * Checks for inequality. 0085 */ 0086 bool operator!=(const Value &other) const 0087 { 0088 return !((*this) == other); 0089 } 0090 0091 protected: 0092 QString m_expression; 0093 double m_value; 0094 }; 0095 0096 /** 0097 * Stores details of the appearance of a plot of a function (e.g. its 0098 * derivative or integral). 0099 */ 0100 class PlotAppearance 0101 { 0102 public: 0103 PlotAppearance(); 0104 0105 // NOTE: When adding more members to this class, remember to update 0106 // the function PlotAppearance::operator!= and the functions in 0107 // KmPlotIO for saving / loading the plot appearance 0108 0109 double lineWidth; ///< line width in mm 0110 QColor color; ///< color that the plot will be drawn in 0111 Qt::PenStyle style; ///< pen style (e.g. dolif, dashes, dotted, etc) 0112 QGradient gradient; ///< the gradient if useGradient is true 0113 bool useGradient : 1; ///< for plots with parameters, whether to use gradient instead of color 0114 bool showExtrema : 1; ///< for cartesian functions, whether to show the extreme values of the function 0115 bool showTangentField : 1; ///< whether to draw the tangent field (for differential equations 0116 bool visible : 1; ///< whether to display this plot 0117 bool showPlotName : 1; ///< whether to show the name of the plot on the graph 0118 0119 bool operator!=(const PlotAppearance &other) const; 0120 0121 /** 0122 * Converts a pen style to a string (for non-displaying uses such as 0123 * saving to file). 0124 */ 0125 static QString penStyleToString(Qt::PenStyle style); 0126 /** 0127 * Converts a string (as returned by penStyleTostring) to a pen style. 0128 */ 0129 static Qt::PenStyle stringToPenStyle(const QString &style); 0130 }; 0131 0132 /** 0133 * Used in differential equations; contains the initial conditions and the 0134 * currently calculated value (used as a cache). 0135 */ 0136 class DifferentialState 0137 { 0138 public: 0139 DifferentialState(); 0140 explicit DifferentialState(int order); 0141 0142 /** 0143 * Resizes y, y0. Also calls resetToInitial. 0144 */ 0145 void setOrder(int order); 0146 /** 0147 * Sets y=y0, x=x0. 0148 */ 0149 void resetToInitial(); 0150 0151 Value x0; ///< the initial x-value 0152 QVector<Value> y0; ///< the value of ( f, f', f'', ...., f^(n) ) at x0 0153 double x; ///< the current x value 0154 Vector y; ///< the value of ( f, f', f'', ...., f^(n) ) at x 0155 0156 /** 0157 * Whether the initial conditions and current state are the same. 0158 */ 0159 bool operator==(const DifferentialState &other) const; 0160 }; 0161 0162 class DifferentialStates 0163 { 0164 public: 0165 DifferentialStates(); 0166 0167 /** 0168 * For Cartesian equations, can only have one state (for integrals). 0169 */ 0170 void setUniqueState(bool unique); 0171 /** 0172 * \see order() 0173 */ 0174 void setOrder(int order); 0175 /** 0176 * Creates a differential state. If this is for a Cartesian equation 0177 * and there is already a differential state, then that will be 0178 * returned instead, since a Cartesian equation can only have one 0179 * differential state. 0180 */ 0181 DifferentialState *add(); 0182 /** 0183 * The order of the differential equations, e.g. "f''(x) = -f" is of 0184 * order 2. 0185 */ 0186 int order() const 0187 { 0188 return m_order; 0189 } 0190 /** 0191 * The number of differential states. 0192 */ 0193 int size() const 0194 { 0195 return m_data.size(); 0196 } 0197 /** 0198 * Calls DifferentialState::resetToInitial for each state; i.e. resets 0199 * the cached information about the state of the differential equation. 0200 */ 0201 void resetToInitial(); 0202 /** 0203 * The maximum step-size (and hence minimum precision) used in the RK4 0204 * method (see XParser::differential). Of course, a smaller step size 0205 * may be used in the visible section of a differential plot. 0206 */ 0207 Value step() const 0208 { 0209 return m_step; 0210 } 0211 /** 0212 * \see maximumStep(); 0213 * \return whether could successfully set the step, i.e. that it is 0214 * strictly positive. 0215 */ 0216 bool setStep(const Value &step); 0217 0218 bool operator==(const DifferentialStates &other) const 0219 { 0220 return (m_data == other.m_data) && (m_step == other.m_step); 0221 } 0222 bool operator!=(const DifferentialStates &other) const 0223 { 0224 return !(*this == other); 0225 } 0226 DifferentialState &operator[](int i) 0227 { 0228 return m_data[i]; 0229 } 0230 const DifferentialState &operator[](int i) const 0231 { 0232 return m_data[i]; 0233 } 0234 void remove(int i) 0235 { 0236 m_data.remove(i); 0237 } 0238 void remove(int i, int count) 0239 { 0240 m_data.remove(i, count); 0241 } 0242 void removeAll() 0243 { 0244 m_data.clear(); 0245 } 0246 0247 protected: 0248 QVector<DifferentialState> m_data; 0249 int m_order; 0250 bool m_uniqueState; 0251 Value m_step; 0252 }; 0253 0254 /** 0255 * This is the non-visual mathematical expression. 0256 * \note when adding new member variables, make sure to update operator != 0257 * and operator =. 0258 */ 0259 class Equation 0260 { 0261 public: 0262 enum Type { 0263 Constant, 0264 Cartesian, 0265 ParametricX, 0266 ParametricY, 0267 Polar, 0268 Implicit, 0269 Differential, 0270 }; 0271 0272 Equation(Type type, Function *parent); 0273 ~Equation(); 0274 0275 /// The type of function 0276 Type type() const 0277 { 0278 return m_type; 0279 } 0280 /** 0281 * \return whether this Equation has different user-entered values to 0282 * the \p other equation. 0283 */ 0284 bool operator!=(const Equation &other); 0285 /** 0286 * Assigns the value in \p other to this equation. 0287 */ 0288 Equation &operator=(const Equation &other); 0289 /** 0290 * Pointer to the allocated memory for the tokens. 0291 */ 0292 QByteArray mem; 0293 /** 0294 * Array index to the token. 0295 */ 0296 char *mptr; 0297 /** 0298 * @return a pointer to Function parent of this Equation. 0299 */ 0300 Function *parent() const 0301 { 0302 return m_parent; 0303 } 0304 /** 0305 * @return the name of the function, e.g. for the cartesian function 0306 * f(x)=x^2, this would return "f". 0307 */ 0308 QString name(bool removePrimes = true) const; 0309 /** 0310 * \return a list of variables, e.g. {x} for "f(x)=y", and {x,y,k} for 0311 * "f(x,y,k)=(x+k)(y+k)". 0312 */ 0313 QStringList variables() const 0314 { 0315 return m_variables; 0316 } 0317 /** 0318 * \return whether the function accepts a parameter in addition to the x 0319 * (and possibly y) variables. 0320 */ 0321 bool usesParameter() const 0322 { 0323 return m_usesParameter; 0324 } 0325 /** 0326 * \return the name of the parameter variable (or a blank string if a 0327 * parameter is not used). 0328 */ 0329 QString parameterName() const; 0330 /** 0331 * The full function expression, e.g. "f(x,k)=(x+k)(x-k)". 0332 */ 0333 QString fstr() const 0334 { 0335 return m_fstr; 0336 } 0337 /** 0338 * @see fstr() 0339 * @param string the equation 0340 * @param error if non-null, then will be set to the parser error (or 0341 * success). 0342 * @param errorPosition the error position 0343 * @param force Update the internal equation string even if it could not 0344 * be parsed correctly. Used in opening old files, for example, in case 0345 * something internal to kmplot has changed that results in the equation 0346 * no longer being parsable. 0347 * @return whether \p fstr could be parsed correctly. Note that if it 0348 * was not parsed correctly, then this will return false and this class 0349 * will not be updated. 0350 */ 0351 bool setFstr(const QString &string, int *error = 0, int *errorPosition = 0, bool force = false); 0352 /** 0353 * \return true if the fstr looks like "f(x) = ..." 0354 * \return false if the fstr looks like "y = ..." (note that this 0355 * depends on the type of equation, so if this is a Cartesian equation 0356 * and the fstr looks like "a = ..." (not y) then it'll be considered a 0357 * function, even if it isn't a very useful one. 0358 */ 0359 bool looksLikeFunction() const; 0360 /** 0361 * \return the order of the differential equations. 0362 */ 0363 int order() const; 0364 /** 0365 * \return the number of plus-minus symbols in the equation. 0366 */ 0367 int pmCount() const; 0368 0369 /// For differential equations, all the states 0370 DifferentialStates differentialStates; 0371 0372 /** 0373 * The current plus-minus signature (true for plus, false for minus). 0374 */ 0375 QVector<bool> pmSignature() const 0376 { 0377 return m_pmSignature; 0378 } 0379 /** 0380 * \see pmSignature. 0381 */ 0382 void setPMSignature(QVector<bool> pmSignature); 0383 0384 protected: 0385 /** 0386 * Updates m_variables. 0387 */ 0388 void updateVariables(); 0389 0390 bool m_usesParameter; 0391 const Type m_type; 0392 QString m_fstr; 0393 Function *m_parent; 0394 QVector<bool> m_pmSignature; 0395 /** 0396 * Cached list of variables. Updated when setFstr is called. 0397 */ 0398 QStringList m_variables; 0399 }; 0400 0401 /** 0402 * Which parameters to use and how. 0403 */ 0404 class ParameterSettings 0405 { 0406 public: 0407 ParameterSettings(); 0408 0409 bool operator==(const ParameterSettings &other) const; 0410 bool operator!=(const ParameterSettings &other) const 0411 { 0412 return !((*this) == other); 0413 } 0414 0415 bool animating; ///< if true, then useSlider and useList are ignored, parameter value is assumed to be updated 0416 bool useSlider; 0417 int sliderID; 0418 bool useList; 0419 QList<Value> list; 0420 }; 0421 0422 /** 0423 * Uniquely identifies a parameter (which could be from the list of Values 0424 * stored in a Function or from a Slider. 0425 */ 0426 class Parameter 0427 { 0428 public: 0429 enum Type { 0430 Unknown, 0431 Animated, 0432 Slider, 0433 List, 0434 }; 0435 explicit Parameter(Type type = Unknown); 0436 0437 Type type() const 0438 { 0439 return m_type; 0440 } 0441 /** 0442 * The slider ID specifies which slider to use (e.g. "2" specifies the 0443 * third slider). 0444 */ 0445 void setSliderID(int id) 0446 { 0447 m_sliderID = id; 0448 } 0449 /** 0450 * The list pos specifies which parameter to use in the list 0451 * ParameterSettings::list. 0452 */ 0453 void setListPos(int pos) 0454 { 0455 m_listPos = pos; 0456 } 0457 /** 0458 * \see setSliderID 0459 */ 0460 int sliderID() const 0461 { 0462 return m_sliderID; 0463 } 0464 /** 0465 * \see setListPos 0466 */ 0467 int listPos() const 0468 { 0469 return m_listPos; 0470 } 0471 /** 0472 * \return Whether the parameter referred to is the same. 0473 */ 0474 bool operator==(const Parameter &other) const; 0475 0476 protected: 0477 Type m_type; 0478 int m_sliderID; 0479 int m_listPos; 0480 }; 0481 0482 /** Here are all attributes for a function. */ 0483 class Function 0484 { 0485 public: 0486 enum PMode { 0487 Derivative0, 0488 Derivative1, 0489 Derivative2, 0490 Derivative3, 0491 Integral, 0492 }; 0493 0494 enum Type { 0495 Cartesian, 0496 Parametric, 0497 Polar, 0498 Implicit, 0499 Differential, 0500 }; 0501 0502 explicit Function(Type type); 0503 ~Function(); 0504 0505 /** 0506 * \return the type of function. 0507 */ 0508 Type type() const 0509 { 0510 return m_type; 0511 } 0512 0513 enum PlotCombination { 0514 DifferentParameters = 0x1, ///< For all the different parameters 0515 DifferentDerivatives = 0x2, ///< Derivatives of the function 0516 DifferentPMSignatures = 0x4, ///< Plus-minus combinations 0517 DifferentInitialStates = 0x8, ///< For differential equations; different states 0518 AllCombinations = 0x20 - 1 0519 }; 0520 typedef QFlags<PlotCombination> PlotCombinations; 0521 0522 /** 0523 * \return a list of plots for this function, 0524 */ 0525 QList<Plot> plots(PlotCombinations combinations = AllCombinations) const; 0526 /** 0527 * \return A string for displaying to the user that identifies this 0528 * function. For identifying plots uniquely, see Plot::name() 0529 */ 0530 QString name() const; 0531 /** 0532 * Converts the type to a string (which is used in save files). 0533 */ 0534 static QString typeToString(Type type); 0535 /** 0536 * Converts the string to a type (used when loading files). 0537 */ 0538 static Type stringToType(const QString &type); 0539 /** 0540 * Sets the current working parameter (which is used in calculations). 0541 */ 0542 void setParameter(double p) 0543 { 0544 k = p; 0545 } 0546 /** 0547 * The function parameter, as set by e.g. a slider. 0548 */ 0549 double k; 0550 /** 0551 * Clears the list of functions that this function depends on. 0552 */ 0553 void clearFunctionDependencies() 0554 { 0555 m_dependencies.clear(); 0556 } 0557 /** 0558 * Adds \p function to the list of functions that this function depends 0559 * on. For example, if this function is "f(x) = 1 + g(x)", then this 0560 * function depends on the function g(x). 0561 */ 0562 void addFunctionDependency(Function *function); 0563 /** 0564 * \return whether this function or any of the functions that this 0565 * function depend on, etc, depend on \p function. 0566 */ 0567 bool dependsOn(Function *function) const; 0568 /** 0569 * Copies data members across, while avoiding id, mem, mptr type 0570 * variables. 0571 * @return whether any values have changed. 0572 */ 0573 bool copyFrom(const Function &function); 0574 /** 0575 * \return the function ID, used to identify it from the parser. 0576 */ 0577 uint id() const 0578 { 0579 return m_id; 0580 } 0581 /** 0582 * \see id() 0583 */ 0584 void setId(uint id) 0585 { 0586 m_id = id; 0587 } 0588 QVector<Equation *> eq; 0589 /** 0590 * \return A reference to the appearance of the given plot type. 0591 */ 0592 PlotAppearance &plotAppearance(PMode plot); 0593 /** 0594 * \return The appearance of the given plot type. 0595 */ 0596 PlotAppearance plotAppearance(PMode plot) const; 0597 /** 0598 * \returns true if all plots are hidden (i.e. plotAppearance().visible 0599 * is false for all plot types). 0600 * \returns false otherwise. 0601 */ 0602 bool allPlotsAreHidden() const; 0603 /** 0604 * Custom plot range, lower boundary. 0605 */ 0606 Value dmin; 0607 /** 0608 * Custom plot range, upper boundary. 0609 */ 0610 Value dmax; 0611 0612 ParameterSettings m_parameters; 0613 0614 bool usecustomxmin : 1; 0615 bool usecustomxmax : 1; 0616 // TODO double slider_min, slider_max; ///< extreme values of the slider 0617 0618 /** 0619 * For use with implicit functions, when either x or y is held fixed. 0620 */ 0621 enum ImplicitMode { 0622 FixedX, 0623 FixedY, 0624 UnfixedXY, 0625 0626 }; 0627 ImplicitMode m_implicitMode; 0628 /** 0629 * The value of x when this is an implicit function and x is fixed. 0630 */ 0631 double x; 0632 /** 0633 * The value of y when this is an implicit function and y is fixed. 0634 */ 0635 double y; 0636 0637 /** 0638 * A list with all functions that this function depends on. 0639 */ 0640 QList<int> m_dependencies; 0641 0642 protected: 0643 uint m_id; 0644 const Type m_type; 0645 0646 PlotAppearance f0; ///< The actual function - the "zero'th derivative" 0647 PlotAppearance f1; ///< First derivative 0648 PlotAppearance f2; ///< Second derivative 0649 PlotAppearance f3; ///< Third derivative 0650 PlotAppearance integral; ///< integral 0651 }; 0652 0653 /** 0654 * Uniquely identifies a single plot (i.e. a single curvy line in the View). 0655 */ 0656 class Plot 0657 { 0658 public: 0659 Plot(); 0660 0661 bool operator==(const Plot &other) const; 0662 0663 void setFunctionID(int id); 0664 /** 0665 * Changes the plotMode equivalent to differentiating. 0666 */ 0667 void differentiate(); 0668 /** 0669 * Changes the plotMode equivalent to integrating. 0670 */ 0671 void integrate(); 0672 int functionID() const 0673 { 0674 return m_functionID; 0675 } 0676 /** 0677 * \return a pointer to the function with ID as set by setFunctionID 0678 */ 0679 Function *function() const 0680 { 0681 return m_function; 0682 } 0683 /** 0684 * \return the value of the parameter associated with this plot. 0685 */ 0686 double parameterValue() const; 0687 /** 0688 * Generates a name appropriate for distinguishing the plot from others. 0689 */ 0690 QString name() const; 0691 /** 0692 * The color that the plot should be drawn with. 0693 */ 0694 QColor color() const; 0695 /** 0696 * Parameter in use. 0697 */ 0698 Parameter parameter; 0699 /** 0700 * Which derivative. 0701 */ 0702 Function::PMode plotMode; 0703 /** 0704 * Converts the plotMode to the derivative number, e.g. 0705 * Function::Derivative1 -> 1, and Function::Integral -> -1 0706 */ 0707 int derivativeNumber() const; 0708 /** 0709 * Assigned when Function::allPlots() is called. The plots for each 0710 * plotMode are numbered 0 to *. 0711 */ 0712 int plotNumber; 0713 /** 0714 * The total number of plots of the same plotMode as this. 0715 */ 0716 int plotNumberCount; 0717 /** 0718 * Updates the current working parameter value in the function that 0719 * this plot is for and the plus-minus signature for the function's 0720 * equations. 0721 */ 0722 void updateFunction() const; 0723 /** 0724 * For differential equations, which state to draw. It's probably 0725 * easier to use the function differentialState(), however. 0726 */ 0727 int stateNumber; 0728 /** 0729 * \return the differential state for the plot (or 0 if no state). 0730 */ 0731 DifferentialState *state() const; 0732 /** 0733 * For equations containing a plus-minus symbols, this indicates 0734 * whether to take the plus or the minus for each one. The list is for 0735 * each equation of the function (so typically, the list will only be 0736 * of size one, but parametric functions will have two). 0737 */ 0738 QList<QVector<bool>> pmSignature; 0739 0740 protected: 0741 void updateCached(); 0742 0743 int m_functionID; ///< ID of function 0744 Function *m_function; ///< Cached pointer to function 0745 }; 0746 0747 #endif // FUNCTION_H