From 4f6e9ef11743ddd0d847781ee011c068da0c131b Mon Sep 17 00:00:00 2001 From: Nkondog Anselme Date: Sun, 14 Nov 2021 08:12:46 +0100 Subject: [PATCH] Transfer trade signals to CSignalGrid class --- .gitignore | 8 +- Experts/Nkanven/Framework EA/Grid/GridEA.ex5 | Bin 130602 -> 130934 bytes Experts/Nkanven/Framework EA/Grid/GridEA.mq5 | 2 + Include/A_EntriesManagement.mqh | Bin 19010 -> 0 bytes Include/A_HistoryChecker.mqh | Bin 4692 -> 0 bytes Include/A_LotSizeCal.mqh | 62 - Include/A_Parameters.mqh | 213 - Include/A_PositionsManager.mqh | 123 - Include/A_TradeManager.mqh | 23 - Include/A_TradingHour.mqh | 27 - Include/Arrays/Array.mqh | 182 - Include/Arrays/ArrayChar.mqh | 771 - Include/Arrays/ArrayDouble.mqh | 777 - Include/Arrays/ArrayFloat.mqh | 778 - Include/Arrays/ArrayInt.mqh | 770 - Include/Arrays/ArrayLong.mqh | 770 - Include/Arrays/ArrayObj.mqh | 759 - Include/Arrays/ArrayShort.mqh | 770 - Include/Arrays/ArrayString.mqh | 780 - Include/Arrays/List.mqh | 657 - Include/Arrays/Tree.mqh | 415 - Include/Arrays/TreeNode.mqh | 174 - Include/Canvas/Canvas.mqh | 4846 ---- Include/Canvas/Canvas3D.mqh | Bin 34652 -> 0 bytes Include/Canvas/Charts/ChartCanvas.mqh | 1041 - Include/Canvas/Charts/HistogramChart.mqh | 347 - Include/Canvas/Charts/LineChart.mqh | 383 - Include/Canvas/Charts/PieChart.mqh | 414 - Include/Canvas/DX/DXBox.mqh | 77 - Include/Canvas/DX/DXBuffers.mqh | 92 - Include/Canvas/DX/DXData.mqh | Bin 4048 -> 0 bytes Include/Canvas/DX/DXDispatcher.mqh | 373 - Include/Canvas/DX/DXHandle.mqh | Bin 8568 -> 0 bytes Include/Canvas/DX/DXInput.mqh | Bin 4968 -> 0 bytes Include/Canvas/DX/DXMath.mqh | 3352 --- Include/Canvas/DX/DXMesh.mqh | 375 - Include/Canvas/DX/DXObject.mqh | Bin 1744 -> 0 bytes Include/Canvas/DX/DXObjectBase.mqh | Bin 2106 -> 0 bytes Include/Canvas/DX/DXShader.mqh | Bin 16984 -> 0 bytes Include/Canvas/DX/DXSurface.mqh | 162 - Include/Canvas/DX/DXTexture.mqh | Bin 6904 -> 0 bytes Include/Canvas/DX/DXUtils.mqh | 942 - .../Canvas/DX/Shaders/DefaultShaderPixel.hlsl | 71 - .../DX/Shaders/DefaultShaderVertex.hlsl | 72 - Include/Canvas/FlameCanvas.mqh | 751 - Include/ChartObjects/ChartObject.mqh | 1000 - Include/ChartObjects/ChartObjectPanel.mqh | 205 - Include/ChartObjects/ChartObjectSubChart.mqh | 398 - Include/ChartObjects/ChartObjectsArrows.mqh | 479 - .../ChartObjects/ChartObjectsBmpControls.mqh | 512 - Include/ChartObjects/ChartObjectsChannels.mqh | 246 - Include/ChartObjects/ChartObjectsElliott.mqh | 201 - Include/ChartObjects/ChartObjectsFibo.mqh | 365 - Include/ChartObjects/ChartObjectsGann.mqh | 390 - Include/ChartObjects/ChartObjectsLines.mqh | 335 - Include/ChartObjects/ChartObjectsShapes.mqh | 142 - .../ChartObjects/ChartObjectsTxtControls.mqh | 895 - Include/Charts/Chart.mqh | 1549 -- Include/Controls/BmpButton.mqh | 268 - Include/Controls/Button.mqh | 146 - Include/Controls/CheckBox.mqh | 183 - Include/Controls/CheckGroup.mqh | 377 - Include/Controls/ComboBox.mqh | 324 - Include/Controls/DateDropList.mqh | 413 - Include/Controls/DatePicker.mqh | 264 - Include/Controls/Defines.mqh | 190 - Include/Controls/Dialog.mqh | 971 - Include/Controls/Edit.mqh | 188 - Include/Controls/Label.mqh | 93 - Include/Controls/ListView.mqh | 544 - Include/Controls/Panel.mqh | 124 - Include/Controls/Picture.mqh | 125 - Include/Controls/RadioButton.mqh | 160 - Include/Controls/RadioGroup.mqh | 361 - Include/Controls/Rect.mqh | 279 - Include/Controls/Scrolls.mqh | 675 - Include/Controls/SpinEdit.mqh | 265 - Include/Controls/Wnd.mqh | 755 - Include/Controls/WndClient.mqh | 308 - Include/Controls/WndContainer.mqh | 473 - Include/Controls/WndObj.mqh | 262 - Include/Controls/res/CheckBoxOff.bmp | Bin 576 -> 0 bytes Include/Controls/res/CheckBoxOn.bmp | Bin 576 -> 0 bytes Include/Controls/res/Close.bmp | Bin 1080 -> 0 bytes Include/Controls/res/DateDropOff.bmp | Bin 2104 -> 0 bytes Include/Controls/res/DateDropOn.bmp | Bin 2104 -> 0 bytes Include/Controls/res/Down.bmp | Bin 824 -> 0 bytes Include/Controls/res/DownTransp.bmp | Bin 1080 -> 0 bytes Include/Controls/res/DropOff.bmp | Bin 1080 -> 0 bytes Include/Controls/res/DropOn.bmp | Bin 1080 -> 0 bytes Include/Controls/res/Left.bmp | Bin 824 -> 0 bytes Include/Controls/res/LeftTransp.bmp | Bin 1080 -> 0 bytes Include/Controls/res/RadioButtonOff.bmp | Bin 632 -> 0 bytes Include/Controls/res/RadioButtonOn.bmp | Bin 632 -> 0 bytes Include/Controls/res/Restore.bmp | Bin 1080 -> 0 bytes Include/Controls/res/Right.bmp | Bin 824 -> 0 bytes Include/Controls/res/RightTransp.bmp | Bin 1080 -> 0 bytes Include/Controls/res/SpinDec.bmp | Bin 568 -> 0 bytes Include/Controls/res/SpinInc.bmp | Bin 568 -> 0 bytes Include/Controls/res/ThumbHor.bmp | Bin 1144 -> 0 bytes Include/Controls/res/ThumbVert.bmp | Bin 1112 -> 0 bytes Include/Controls/res/Turn.bmp | Bin 1080 -> 0 bytes Include/Controls/res/Up.bmp | Bin 824 -> 0 bytes Include/Controls/res/UpTransp.bmp | Bin 1080 -> 0 bytes Include/DL_CheckHistory.mqh | Bin 5140 -> 0 bytes Include/DL_CheckOperationHours.mqh | 46 - Include/DL_ClosePositions.mqh | 67 - Include/DL_EntriesManagement.mqh | Bin 17430 -> 0 bytes Include/DL_ErrorHandling.mqh | 97 - Include/DL_InitMQL4.mqh | 65 - Include/DL_LotSizeCal.mqh | 54 - Include/DL_Parameters.mqh | 175 - Include/DL_PreChecks.mqh | 62 - Include/DL_ScanPositions.mqh | 49 - Include/DL_TradeManagement.mqh | 20 - Include/DL_TradingBoundaries.mqh | 112 - Include/E_CheckHistory.mqh | Bin 4886 -> 0 bytes Include/E_ClosePositions.mqh | 81 - Include/E_EntriesManagement.mqh | Bin 20382 -> 0 bytes Include/E_Parameters.mqh | Bin 20632 -> 0 bytes Include/E_ScanPositions.mqh | 49 - Include/E_TradeManagement.mqh | 57 - Include/Expert/Expert.mqh | Bin 122604 -> 0 bytes Include/Expert/ExpertBase.mqh | 715 - Include/Expert/ExpertMoney.mqh | 124 - Include/Expert/ExpertSignal.mqh | 464 - Include/Expert/ExpertTrade.mqh | 171 - Include/Expert/ExpertTrailing.mqh | 33 - Include/Expert/Money/MoneyFixedLot.mqh | 73 - Include/Expert/Money/MoneyFixedMargin.mqh | 76 - Include/Expert/Money/MoneyFixedRisk.mqh | 109 - Include/Expert/Money/MoneyNone.mqh | 71 - Include/Expert/Money/MoneySizeOptimized.mqh | 155 - Include/Expert/Signal/SignalAC.mqh | 173 - Include/Expert/Signal/SignalAMA.mqh | 265 - Include/Expert/Signal/SignalAO.mqh | 339 - Include/Expert/Signal/SignalBearsPower.mqh | 289 - Include/Expert/Signal/SignalBullsPower.mqh | 289 - Include/Expert/Signal/SignalCCI.mqh | 382 - Include/Expert/Signal/SignalDEMA.mqh | 257 - Include/Expert/Signal/SignalDeMarker.mqh | 378 - Include/Expert/Signal/SignalEnvelopes.mqh | 193 - Include/Expert/Signal/SignalFrAMA.mqh | 257 - Include/Expert/Signal/SignalITF.mqh | 91 - Include/Expert/Signal/SignalMA.mqh | 261 - Include/Expert/Signal/SignalMACD.mqh | 408 - Include/Expert/Signal/SignalRSI.mqh | 400 - Include/Expert/Signal/SignalRVI.mqh | 180 - Include/Expert/Signal/SignalSAR.mqh | 168 - Include/Expert/Signal/SignalStoch.mqh | 426 - Include/Expert/Signal/SignalTEMA.mqh | 257 - Include/Expert/Signal/SignalTRIX.mqh | 395 - Include/Expert/Signal/SignalWPR.mqh | 371 - Include/Expert/Trailing/TrailingFixedPips.mqh | 132 - Include/Expert/Trailing/TrailingMA.mqh | 157 - Include/Expert/Trailing/TrailingNone.mqh | 40 - .../Expert/Trailing/TrailingParabolicSAR.mqh | 123 - Include/ExpertBase.mqh | 380 - Include/Framework.mqh | 21 - Include/Generic/ArrayList.mqh | Bin 50304 -> 0 bytes Include/Generic/HashMap.mqh | 617 - Include/Generic/HashSet.mqh | 972 - Include/Generic/Interfaces/ICollection.mqh | 24 - Include/Generic/Interfaces/IComparable.mqh | 19 - Include/Generic/Interfaces/IComparer.mqh | 17 - .../Interfaces/IEqualityComparable.mqh | 19 - .../Generic/Interfaces/IEqualityComparer.mqh | 19 - Include/Generic/Interfaces/IList.mqh | 26 - Include/Generic/Interfaces/IMap.mqh | 27 - Include/Generic/Interfaces/ISet.mqh | 37 - Include/Generic/Internal/ArrayFunction.mqh | 135 - Include/Generic/Internal/CompareFunction.mqh | 209 - Include/Generic/Internal/DefaultComparer.mqh | 22 - .../Internal/DefaultEqualityComparer.mqh | 25 - Include/Generic/Internal/EqualFunction.mqh | 26 - Include/Generic/Internal/HashFunction.mqh | 176 - Include/Generic/Internal/Introsort.mqh | 251 - Include/Generic/Internal/PrimeGenerator.mqh | 79 - Include/Generic/LinkedList.mqh | 563 - Include/Generic/Queue.mqh | Bin 23370 -> 0 bytes Include/Generic/RedBlackTree.mqh | Bin 74814 -> 0 bytes Include/Generic/SortedMap.mqh | 341 - Include/Generic/SortedSet.mqh | 673 - Include/Generic/Stack.mqh | 227 - Include/Graphics/Axis.mqh | 260 - Include/Graphics/ColorGenerator.mqh | 74 - Include/Graphics/Curve.mqh | 700 - Include/Graphics/Graphic.mqh | Bin 172800 -> 0 bytes Include/Math/Alglib/alglib.mqh | 23023 ---------------- Include/Math/Alglib/alglibinternal.mqh | 9732 ------- Include/Math/Alglib/alglibmisc.mqh | 1493 - Include/Math/Alglib/ap.mqh | 2175 -- Include/Math/Alglib/arrayresize.mqh | 156 - Include/Math/Alglib/bitconvert.mqh | 531 - Include/Math/Alglib/complex.mqh | 358 - Include/Math/Alglib/dataanalysis.mqh | 15237 ---------- Include/Math/Alglib/delegatefunctions.mqh | 412 - Include/Math/Alglib/diffequations.mqh | 928 - Include/Math/Alglib/fasttransforms.mqh | 2418 -- Include/Math/Alglib/integration.mqh | Bin 249418 -> 0 bytes Include/Math/Alglib/interpolation.mqh | 13407 --------- Include/Math/Alglib/linalg.mqh | 20339 -------------- Include/Math/Alglib/matrix.mqh | 629 - Include/Math/Alglib/optimization.mqh | 12279 --------- Include/Math/Alglib/solvers.mqh | 3829 --- Include/Math/Alglib/specialfunctions.mqh | 6599 ----- Include/Math/Alglib/statistics.mqh | 13972 ---------- Include/Math/Fuzzy/dictionary.mqh | 197 - Include/Math/Fuzzy/fuzzyrule.mqh | 371 - Include/Math/Fuzzy/fuzzyterm.mqh | 69 - Include/Math/Fuzzy/fuzzyvariable.mqh | 113 - Include/Math/Fuzzy/genericfuzzysystem.mqh | 333 - Include/Math/Fuzzy/helper.mqh | 158 - Include/Math/Fuzzy/inferencemethod.mqh | 125 - Include/Math/Fuzzy/mamdanifuzzysystem.mqh | 552 - Include/Math/Fuzzy/membershipfunction.mqh | 1008 - Include/Math/Fuzzy/ruleparser.mqh | 1019 - Include/Math/Fuzzy/sugenofuzzysystem.mqh | 327 - Include/Math/Fuzzy/sugenovariable.mqh | 254 - Include/Math/Stat/Beta.mqh | 772 - Include/Math/Stat/Binomial.mqh | 874 - Include/Math/Stat/Cauchy.mqh | 539 - Include/Math/Stat/ChiSquare.mqh | 531 - Include/Math/Stat/Exponential.mqh | 520 - Include/Math/Stat/F.mqh | 563 - Include/Math/Stat/Gamma.mqh | 764 - Include/Math/Stat/Geometric.mqh | 567 - Include/Math/Stat/Hypergeometric.mqh | 754 - Include/Math/Stat/Logistic.mqh | 592 - Include/Math/Stat/Lognormal.mqh | 635 - Include/Math/Stat/Math.mqh | Bin 432856 -> 0 bytes Include/Math/Stat/NegativeBinomial.mqh | 643 - Include/Math/Stat/NoncentralBeta.mqh | 955 - Include/Math/Stat/NoncentralChiSquare.mqh | 912 - Include/Math/Stat/NoncentralF.mqh | 790 - Include/Math/Stat/NoncentralT.mqh | 1192 - Include/Math/Stat/Normal.mqh | 914 - Include/Math/Stat/Poisson.mqh | 791 - Include/Math/Stat/Stat.mqh | 27 - Include/Math/Stat/T.mqh | 654 - Include/Math/Stat/Uniform.mqh | 539 - Include/Math/Stat/Weibull.mqh | 574 - Include/MovingAverages.mqh | 317 - .../Extensions/Signals/SignalGrid.mqh | 139 + .../Nkanven/Frameworks/GridEA/ExpertBase.mqh | 63 +- Include/Object.mqh | 33 - Include/OpenCL/OpenCL.mqh | 453 - Include/StdLibErr.mqh | 10 - Include/Strings/String.mqh | 377 - Include/Tools/DateTime.mqh | 581 - Include/Trade/AccountInfo.mqh | 397 - Include/Trade/DealInfo.mqh | 430 - Include/Trade/HistoryOrderInfo.mqh | 472 - Include/Trade/OrderInfo.mqh | 553 - Include/Trade/PositionInfo.mqh | 364 - Include/Trade/SymbolInfo.mqh | 789 - Include/Trade/TerminalInfo.mqh | 225 - Include/Trade/Trade.mqh | 1710 -- Include/VirtualKeys.mqh | 200 - Include/WinAPI/errhandlingapi.mqh | 28 - Include/WinAPI/fileapi.mqh | 146 - Include/WinAPI/handleapi.mqh | 21 - Include/WinAPI/libloaderapi.mqh | 47 - Include/WinAPI/memoryapi.mqh | 85 - Include/WinAPI/processenv.mqh | 27 - Include/WinAPI/processthreadsapi.mqh | 202 - Include/WinAPI/securitybaseapi.mqh | 119 - Include/WinAPI/sysinfoapi.mqh | 95 - Include/WinAPI/winapi.mqh | 21 - Include/WinAPI/winbase.mqh | 814 - Include/WinAPI/windef.mqh | 325 - Include/WinAPI/wingdi.mqh | 2080 -- Include/WinAPI/winnt.mqh | 3642 --- Include/WinAPI/winreg.mqh | 77 - Include/WinAPI/winuser.mqh | 1825 -- Include/logger.mqh | Bin 25540 -> 0 bytes Include/stderror.mqh | 99 - 277 files changed, 172 insertions(+), 214658 deletions(-) delete mode 100644 Include/A_EntriesManagement.mqh delete mode 100644 Include/A_HistoryChecker.mqh delete mode 100644 Include/A_LotSizeCal.mqh delete mode 100644 Include/A_Parameters.mqh delete mode 100644 Include/A_PositionsManager.mqh delete mode 100644 Include/A_TradeManager.mqh delete mode 100644 Include/A_TradingHour.mqh delete mode 100644 Include/Arrays/Array.mqh delete mode 100644 Include/Arrays/ArrayChar.mqh delete mode 100644 Include/Arrays/ArrayDouble.mqh delete mode 100644 Include/Arrays/ArrayFloat.mqh delete mode 100644 Include/Arrays/ArrayInt.mqh delete mode 100644 Include/Arrays/ArrayLong.mqh delete mode 100644 Include/Arrays/ArrayObj.mqh delete mode 100644 Include/Arrays/ArrayShort.mqh delete mode 100644 Include/Arrays/ArrayString.mqh delete mode 100644 Include/Arrays/List.mqh delete mode 100644 Include/Arrays/Tree.mqh delete mode 100644 Include/Arrays/TreeNode.mqh delete mode 100644 Include/Canvas/Canvas.mqh delete mode 100644 Include/Canvas/Canvas3D.mqh delete mode 100644 Include/Canvas/Charts/ChartCanvas.mqh delete mode 100644 Include/Canvas/Charts/HistogramChart.mqh delete mode 100644 Include/Canvas/Charts/LineChart.mqh delete mode 100644 Include/Canvas/Charts/PieChart.mqh delete mode 100644 Include/Canvas/DX/DXBox.mqh delete mode 100644 Include/Canvas/DX/DXBuffers.mqh delete mode 100644 Include/Canvas/DX/DXData.mqh delete mode 100644 Include/Canvas/DX/DXDispatcher.mqh delete mode 100644 Include/Canvas/DX/DXHandle.mqh delete mode 100644 Include/Canvas/DX/DXInput.mqh delete mode 100644 Include/Canvas/DX/DXMath.mqh delete mode 100644 Include/Canvas/DX/DXMesh.mqh delete mode 100644 Include/Canvas/DX/DXObject.mqh delete mode 100644 Include/Canvas/DX/DXObjectBase.mqh delete mode 100644 Include/Canvas/DX/DXShader.mqh delete mode 100644 Include/Canvas/DX/DXSurface.mqh delete mode 100644 Include/Canvas/DX/DXTexture.mqh delete mode 100644 Include/Canvas/DX/DXUtils.mqh delete mode 100644 Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl delete mode 100644 Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl delete mode 100644 Include/Canvas/FlameCanvas.mqh delete mode 100644 Include/ChartObjects/ChartObject.mqh delete mode 100644 Include/ChartObjects/ChartObjectPanel.mqh delete mode 100644 Include/ChartObjects/ChartObjectSubChart.mqh delete mode 100644 Include/ChartObjects/ChartObjectsArrows.mqh delete mode 100644 Include/ChartObjects/ChartObjectsBmpControls.mqh delete mode 100644 Include/ChartObjects/ChartObjectsChannels.mqh delete mode 100644 Include/ChartObjects/ChartObjectsElliott.mqh delete mode 100644 Include/ChartObjects/ChartObjectsFibo.mqh delete mode 100644 Include/ChartObjects/ChartObjectsGann.mqh delete mode 100644 Include/ChartObjects/ChartObjectsLines.mqh delete mode 100644 Include/ChartObjects/ChartObjectsShapes.mqh delete mode 100644 Include/ChartObjects/ChartObjectsTxtControls.mqh delete mode 100644 Include/Charts/Chart.mqh delete mode 100644 Include/Controls/BmpButton.mqh delete mode 100644 Include/Controls/Button.mqh delete mode 100644 Include/Controls/CheckBox.mqh delete mode 100644 Include/Controls/CheckGroup.mqh delete mode 100644 Include/Controls/ComboBox.mqh delete mode 100644 Include/Controls/DateDropList.mqh delete mode 100644 Include/Controls/DatePicker.mqh delete mode 100644 Include/Controls/Defines.mqh delete mode 100644 Include/Controls/Dialog.mqh delete mode 100644 Include/Controls/Edit.mqh delete mode 100644 Include/Controls/Label.mqh delete mode 100644 Include/Controls/ListView.mqh delete mode 100644 Include/Controls/Panel.mqh delete mode 100644 Include/Controls/Picture.mqh delete mode 100644 Include/Controls/RadioButton.mqh delete mode 100644 Include/Controls/RadioGroup.mqh delete mode 100644 Include/Controls/Rect.mqh delete mode 100644 Include/Controls/Scrolls.mqh delete mode 100644 Include/Controls/SpinEdit.mqh delete mode 100644 Include/Controls/Wnd.mqh delete mode 100644 Include/Controls/WndClient.mqh delete mode 100644 Include/Controls/WndContainer.mqh delete mode 100644 Include/Controls/WndObj.mqh delete mode 100644 Include/Controls/res/CheckBoxOff.bmp delete mode 100644 Include/Controls/res/CheckBoxOn.bmp delete mode 100644 Include/Controls/res/Close.bmp delete mode 100644 Include/Controls/res/DateDropOff.bmp delete mode 100644 Include/Controls/res/DateDropOn.bmp delete mode 100644 Include/Controls/res/Down.bmp delete mode 100644 Include/Controls/res/DownTransp.bmp delete mode 100644 Include/Controls/res/DropOff.bmp delete mode 100644 Include/Controls/res/DropOn.bmp delete mode 100644 Include/Controls/res/Left.bmp delete mode 100644 Include/Controls/res/LeftTransp.bmp delete mode 100644 Include/Controls/res/RadioButtonOff.bmp delete mode 100644 Include/Controls/res/RadioButtonOn.bmp delete mode 100644 Include/Controls/res/Restore.bmp delete mode 100644 Include/Controls/res/Right.bmp delete mode 100644 Include/Controls/res/RightTransp.bmp delete mode 100644 Include/Controls/res/SpinDec.bmp delete mode 100644 Include/Controls/res/SpinInc.bmp delete mode 100644 Include/Controls/res/ThumbHor.bmp delete mode 100644 Include/Controls/res/ThumbVert.bmp delete mode 100644 Include/Controls/res/Turn.bmp delete mode 100644 Include/Controls/res/Up.bmp delete mode 100644 Include/Controls/res/UpTransp.bmp delete mode 100644 Include/DL_CheckHistory.mqh delete mode 100644 Include/DL_CheckOperationHours.mqh delete mode 100644 Include/DL_ClosePositions.mqh delete mode 100644 Include/DL_EntriesManagement.mqh delete mode 100644 Include/DL_ErrorHandling.mqh delete mode 100644 Include/DL_InitMQL4.mqh delete mode 100644 Include/DL_LotSizeCal.mqh delete mode 100644 Include/DL_Parameters.mqh delete mode 100644 Include/DL_PreChecks.mqh delete mode 100644 Include/DL_ScanPositions.mqh delete mode 100644 Include/DL_TradeManagement.mqh delete mode 100644 Include/DL_TradingBoundaries.mqh delete mode 100644 Include/E_CheckHistory.mqh delete mode 100644 Include/E_ClosePositions.mqh delete mode 100644 Include/E_EntriesManagement.mqh delete mode 100644 Include/E_Parameters.mqh delete mode 100644 Include/E_ScanPositions.mqh delete mode 100644 Include/E_TradeManagement.mqh delete mode 100644 Include/Expert/Expert.mqh delete mode 100644 Include/Expert/ExpertBase.mqh delete mode 100644 Include/Expert/ExpertMoney.mqh delete mode 100644 Include/Expert/ExpertSignal.mqh delete mode 100644 Include/Expert/ExpertTrade.mqh delete mode 100644 Include/Expert/ExpertTrailing.mqh delete mode 100644 Include/Expert/Money/MoneyFixedLot.mqh delete mode 100644 Include/Expert/Money/MoneyFixedMargin.mqh delete mode 100644 Include/Expert/Money/MoneyFixedRisk.mqh delete mode 100644 Include/Expert/Money/MoneyNone.mqh delete mode 100644 Include/Expert/Money/MoneySizeOptimized.mqh delete mode 100644 Include/Expert/Signal/SignalAC.mqh delete mode 100644 Include/Expert/Signal/SignalAMA.mqh delete mode 100644 Include/Expert/Signal/SignalAO.mqh delete mode 100644 Include/Expert/Signal/SignalBearsPower.mqh delete mode 100644 Include/Expert/Signal/SignalBullsPower.mqh delete mode 100644 Include/Expert/Signal/SignalCCI.mqh delete mode 100644 Include/Expert/Signal/SignalDEMA.mqh delete mode 100644 Include/Expert/Signal/SignalDeMarker.mqh delete mode 100644 Include/Expert/Signal/SignalEnvelopes.mqh delete mode 100644 Include/Expert/Signal/SignalFrAMA.mqh delete mode 100644 Include/Expert/Signal/SignalITF.mqh delete mode 100644 Include/Expert/Signal/SignalMA.mqh delete mode 100644 Include/Expert/Signal/SignalMACD.mqh delete mode 100644 Include/Expert/Signal/SignalRSI.mqh delete mode 100644 Include/Expert/Signal/SignalRVI.mqh delete mode 100644 Include/Expert/Signal/SignalSAR.mqh delete mode 100644 Include/Expert/Signal/SignalStoch.mqh delete mode 100644 Include/Expert/Signal/SignalTEMA.mqh delete mode 100644 Include/Expert/Signal/SignalTRIX.mqh delete mode 100644 Include/Expert/Signal/SignalWPR.mqh delete mode 100644 Include/Expert/Trailing/TrailingFixedPips.mqh delete mode 100644 Include/Expert/Trailing/TrailingMA.mqh delete mode 100644 Include/Expert/Trailing/TrailingNone.mqh delete mode 100644 Include/Expert/Trailing/TrailingParabolicSAR.mqh delete mode 100644 Include/ExpertBase.mqh delete mode 100644 Include/Framework.mqh delete mode 100644 Include/Generic/ArrayList.mqh delete mode 100644 Include/Generic/HashMap.mqh delete mode 100644 Include/Generic/HashSet.mqh delete mode 100644 Include/Generic/Interfaces/ICollection.mqh delete mode 100644 Include/Generic/Interfaces/IComparable.mqh delete mode 100644 Include/Generic/Interfaces/IComparer.mqh delete mode 100644 Include/Generic/Interfaces/IEqualityComparable.mqh delete mode 100644 Include/Generic/Interfaces/IEqualityComparer.mqh delete mode 100644 Include/Generic/Interfaces/IList.mqh delete mode 100644 Include/Generic/Interfaces/IMap.mqh delete mode 100644 Include/Generic/Interfaces/ISet.mqh delete mode 100644 Include/Generic/Internal/ArrayFunction.mqh delete mode 100644 Include/Generic/Internal/CompareFunction.mqh delete mode 100644 Include/Generic/Internal/DefaultComparer.mqh delete mode 100644 Include/Generic/Internal/DefaultEqualityComparer.mqh delete mode 100644 Include/Generic/Internal/EqualFunction.mqh delete mode 100644 Include/Generic/Internal/HashFunction.mqh delete mode 100644 Include/Generic/Internal/Introsort.mqh delete mode 100644 Include/Generic/Internal/PrimeGenerator.mqh delete mode 100644 Include/Generic/LinkedList.mqh delete mode 100644 Include/Generic/Queue.mqh delete mode 100644 Include/Generic/RedBlackTree.mqh delete mode 100644 Include/Generic/SortedMap.mqh delete mode 100644 Include/Generic/SortedSet.mqh delete mode 100644 Include/Generic/Stack.mqh delete mode 100644 Include/Graphics/Axis.mqh delete mode 100644 Include/Graphics/ColorGenerator.mqh delete mode 100644 Include/Graphics/Curve.mqh delete mode 100644 Include/Graphics/Graphic.mqh delete mode 100644 Include/Math/Alglib/alglib.mqh delete mode 100644 Include/Math/Alglib/alglibinternal.mqh delete mode 100644 Include/Math/Alglib/alglibmisc.mqh delete mode 100644 Include/Math/Alglib/ap.mqh delete mode 100644 Include/Math/Alglib/arrayresize.mqh delete mode 100644 Include/Math/Alglib/bitconvert.mqh delete mode 100644 Include/Math/Alglib/complex.mqh delete mode 100644 Include/Math/Alglib/dataanalysis.mqh delete mode 100644 Include/Math/Alglib/delegatefunctions.mqh delete mode 100644 Include/Math/Alglib/diffequations.mqh delete mode 100644 Include/Math/Alglib/fasttransforms.mqh delete mode 100644 Include/Math/Alglib/integration.mqh delete mode 100644 Include/Math/Alglib/interpolation.mqh delete mode 100644 Include/Math/Alglib/linalg.mqh delete mode 100644 Include/Math/Alglib/matrix.mqh delete mode 100644 Include/Math/Alglib/optimization.mqh delete mode 100644 Include/Math/Alglib/solvers.mqh delete mode 100644 Include/Math/Alglib/specialfunctions.mqh delete mode 100644 Include/Math/Alglib/statistics.mqh delete mode 100644 Include/Math/Fuzzy/dictionary.mqh delete mode 100644 Include/Math/Fuzzy/fuzzyrule.mqh delete mode 100644 Include/Math/Fuzzy/fuzzyterm.mqh delete mode 100644 Include/Math/Fuzzy/fuzzyvariable.mqh delete mode 100644 Include/Math/Fuzzy/genericfuzzysystem.mqh delete mode 100644 Include/Math/Fuzzy/helper.mqh delete mode 100644 Include/Math/Fuzzy/inferencemethod.mqh delete mode 100644 Include/Math/Fuzzy/mamdanifuzzysystem.mqh delete mode 100644 Include/Math/Fuzzy/membershipfunction.mqh delete mode 100644 Include/Math/Fuzzy/ruleparser.mqh delete mode 100644 Include/Math/Fuzzy/sugenofuzzysystem.mqh delete mode 100644 Include/Math/Fuzzy/sugenovariable.mqh delete mode 100644 Include/Math/Stat/Beta.mqh delete mode 100644 Include/Math/Stat/Binomial.mqh delete mode 100644 Include/Math/Stat/Cauchy.mqh delete mode 100644 Include/Math/Stat/ChiSquare.mqh delete mode 100644 Include/Math/Stat/Exponential.mqh delete mode 100644 Include/Math/Stat/F.mqh delete mode 100644 Include/Math/Stat/Gamma.mqh delete mode 100644 Include/Math/Stat/Geometric.mqh delete mode 100644 Include/Math/Stat/Hypergeometric.mqh delete mode 100644 Include/Math/Stat/Logistic.mqh delete mode 100644 Include/Math/Stat/Lognormal.mqh delete mode 100644 Include/Math/Stat/Math.mqh delete mode 100644 Include/Math/Stat/NegativeBinomial.mqh delete mode 100644 Include/Math/Stat/NoncentralBeta.mqh delete mode 100644 Include/Math/Stat/NoncentralChiSquare.mqh delete mode 100644 Include/Math/Stat/NoncentralF.mqh delete mode 100644 Include/Math/Stat/NoncentralT.mqh delete mode 100644 Include/Math/Stat/Normal.mqh delete mode 100644 Include/Math/Stat/Poisson.mqh delete mode 100644 Include/Math/Stat/Stat.mqh delete mode 100644 Include/Math/Stat/T.mqh delete mode 100644 Include/Math/Stat/Uniform.mqh delete mode 100644 Include/Math/Stat/Weibull.mqh delete mode 100644 Include/MovingAverages.mqh delete mode 100644 Include/Object.mqh delete mode 100644 Include/OpenCL/OpenCL.mqh delete mode 100644 Include/StdLibErr.mqh delete mode 100644 Include/Strings/String.mqh delete mode 100644 Include/Tools/DateTime.mqh delete mode 100644 Include/Trade/AccountInfo.mqh delete mode 100644 Include/Trade/DealInfo.mqh delete mode 100644 Include/Trade/HistoryOrderInfo.mqh delete mode 100644 Include/Trade/OrderInfo.mqh delete mode 100644 Include/Trade/PositionInfo.mqh delete mode 100644 Include/Trade/SymbolInfo.mqh delete mode 100644 Include/Trade/TerminalInfo.mqh delete mode 100644 Include/Trade/Trade.mqh delete mode 100644 Include/VirtualKeys.mqh delete mode 100644 Include/WinAPI/errhandlingapi.mqh delete mode 100644 Include/WinAPI/fileapi.mqh delete mode 100644 Include/WinAPI/handleapi.mqh delete mode 100644 Include/WinAPI/libloaderapi.mqh delete mode 100644 Include/WinAPI/memoryapi.mqh delete mode 100644 Include/WinAPI/processenv.mqh delete mode 100644 Include/WinAPI/processthreadsapi.mqh delete mode 100644 Include/WinAPI/securitybaseapi.mqh delete mode 100644 Include/WinAPI/sysinfoapi.mqh delete mode 100644 Include/WinAPI/winapi.mqh delete mode 100644 Include/WinAPI/winbase.mqh delete mode 100644 Include/WinAPI/windef.mqh delete mode 100644 Include/WinAPI/wingdi.mqh delete mode 100644 Include/WinAPI/winnt.mqh delete mode 100644 Include/WinAPI/winreg.mqh delete mode 100644 Include/WinAPI/winuser.mqh delete mode 100644 Include/logger.mqh delete mode 100644 Include/stderror.mqh diff --git a/.gitignore b/.gitignore index 2f01155..904b243 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ Indicators/ Librairies/ Logs/ Presets/ -/Profiles -/Scripts -/Services -/Shared Projets +Profiles/ +Scripts/ +Services/ +Shared Projets/ diff --git a/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 b/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 index 72df996339e1cd99853d8540a1ae10948821bfa5..68f797d2fa1eaa67e7de08c28efb9498eea99054 100644 GIT binary patch literal 130934 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

EI0PCO8o8j(}1SyV9z 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%0AFYD?*^TgpfNE?> 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ⅈ zn5MEJ+;0^{fV*5#(Tz`Ha|pmIK9dPYdmQCwu*n;;g7L(2Tq|Jpr$`I<-|Z2lrqgyNbl4 zOU2YUkmme`z>mjwoT^#5Z zK=5C9O%!O(+T~Lbe*<&*CdrkS%a!pT{x-L1O;e*$sH*UGH^Nq5ECh|5e5bpmIk7zY*qc-iF_T2#i00O)mjAD?d$MLI14d-{b4k zt1ZUihh0p`ADhX&X{Ax_BYh*Q#HcbEYR~PiE-e~l@iZV2ZJkbhS|Ba|y`auv zRNPVyU{CaU!)%nE7{p;J=#`l=X*%{!GXduYPa>S1iOvPNQvit`kT z8vG2md%^=U8RaxOnQHvEmoM}2;pVH;zJxZ;fKw>e9-2a*HCfGwmO5$SUG6T3!-8HL z8f^h8^G}uA%Ns8V5RLvw96<|wL-kJ}N+G&I`I#j<&#rmLcW+$`y!y+ra(kZMq&*~< zDk!!=daA+*N2>HjW1kOvBjS|KC1J~`=AHIx){UmI`%L344qLkefbMNJsB$PU0Fhgb zYf*%%XK%kz3*I*%V0q%?X4+g<#q+~+J_>{pCXBm*ZsLxa#}z6KCHXRWTZa^{4g-?| z1AyHNhrgAC!kU!;O)LK+<*P|~V5hGaJ4!1^;aRN+(PTz$=RnhVaMzSnpqnc_!fY}7 zcEz7bnfCLe^ChVqT{C3htjYK#)tQ_CTlseU zriFcC9vE!Xy^D$o+@-P7@oHacX32g`6pkybg`sjem%?k(j+ZpOh4Fl@H6_X_;n?8Hc zpP*T1Zz$iO-j)om`1bkMX?WX`d_*kqWC$|FQUKu&~MzCE)WzT_RAQ@MI>DQ1-iin>n1_GOXnPzT(bSbg z=j-{*{<>A{zs>i?T4|@vV`4-?l6t1+(SANvSo8Syw5*q(T|wvx2~G$r_~-ZzFpVV_ z=62arzKU!Br2eq9L<0Kvan~@C6a3?XqlbYxKX%G+%sMmR!iX6tS!Zo(F!VMXrNj~Ja^JSN+V(767 z=OCa3Ip`>4zh_7kH6s}msD~ttb+k^LaVW~A#OTKzQI42o7aeUcoU_ zaP67MdZsJtrKY|&k=Myq4~mph8O_5+Z61(9@5opSe;}=N_1e88qzRBOn!P07u~^G( z&;hSG!eU){Da$F3IqK%^q}d(q7dedJiLkVsu_O;?2naP1?6QVx`;g@=k&(ifZJtUX z!v7xOXdrdpa9RlxmIc7 zj`fs@>$d3lB+am*q;ttu3bqRicBb)4#KA}BJ^7@^i){@;S#)wrZ(Ii4};nLo9b8w-J_>nMlQWXdXBG<=o#w?xe;IYbXl= ztziuO#(W8A0@yLcGOC$fC^K9{qHXedmVcG~U`kn*#*mb~vc}f) zr&$X~$Kdr&-oWE|)2B_Ia9QlQ1Y^OawkOio73M5)TXt_oMR{z*thPI@fKtd|wuTSP zG{8$}&?`&hgbW-Y=IiIfCl*>3#7wI+Vid|tn6cWv&i&+5&RwTb70g}fr>~BS0D$?0 z>i1p;CoD8JCgKJ#W@xI=irE|_R~+8)l^k-@ZUU_6u#}{Yim@@#pgAqHvn-Ok@@HAR zcCR-f3Qv*>B^3fOrnfM8D3n%}eA&hkO@}*!moq$%1p7}!0-KKXGx2_d8(d^bX3l5( zT&WNeC$>q>?&!9hOU9Pbml$2BkSd#DcjK)5@gz&xkyJMC-<9tAb7nY2OF)o}`*eq9 z?+6$U8Hyv@eF&Y@3%o(9N#cSBWhMCzna$$nZ{<|cSEUwjXPL@qDw!%y?S}NtT(Z8{Ei=HBD>+=w*$2RuohEf#W^P^qJ zWAl*x`3+dh>J(XOiX9$I)gZJ$|9xt*IgToIUHU^LSRVN?Noo8ujilV_7|j{qXJ*>@ znZ801uems(TfaOCoP8+^V?Ud37ejMRe$^MMP)W2&=fD&K^&H-mKQkWkHRFiK@Wo%x zd=nphW&+<53@d?}jP3hRC<&Xh{}v8+%E#CHX-)KLID%Q1Kpu_pWa&HE%2)lqt<%H7 zxX~PTO>RpWaV2HjZ2Y^UmE5tDPC~ssL=8S(p;dQmf*N$;qy&)qyhr`=L1Z@&Hv2TM zA;_mj9%nRHsoi;X?rKj|zp0 zZNqDOY-dzKXPe^uGQhnom0~l%16N1EE`^ZPM08yO*E;G*$=W%xE zL)WmzP!XL4PketzHP0}0Z8JiwvH=(lf$k(kyvp$-mn!J{w`Y}QIFI~q?s}ri_8-lR zYcl{CxU#`%5q7DO9v?X~$+V3X@V9PcjOQjTm{5&4*ydzJ+AS3(=b_b z{mL|8uc4auE++<@!Et5hCnrcOn6RT|4okQvi_vJ2E?Ei4ZXL@e0XGHj+r;aJl^#HxGtfrhd@=SXMuh_Z0U4|l9GJA-g~AN*qJHnfJWu1$p{k-EM})n^T4jn;B{38s@c!t7t78dK zHr$Xh|vs=e?4mza9h*C$Sb}JF2yQo8jey)C%bCb!)c$XIgteP{@_SPH)*1<27BQ3^wQ1mpe(=t^BGsNO z9!9MlUp?`U11XxmOt~|N1}ELQRWEfjI)%KW><6`SaME1jNN)^=?IzIu9&C4>nhxKtJH9Pv9A~uT6&`edm>^eXDhMKVMXJnM-#&T(`r@UPWsN-Rl z1dBVCl#=*M8sR3Ym7hAqe;eZ$EEqqaMis-f8E^m30wL1!(i)0+!2zLtnE@#0;EjK` z;KE-nm@!hE_c+iX`WlRKyopFK1=jFI&0?hQoH`vHrU}!ANS>{7HxaWL7c8DFKi{3i zeL#Bt{VWwgsm=4CU%yK1<;Sgb4A{F`mD{09ufhI63b|kFUcc$GOCo;KpYFy!nG0VS ztF|M_A{chh`GIz+Ancy);-G=+4l`U@PZxvlrV0xR8XR^LkMPl80BHg^3GQS~8@WU( zF+){Q6oX~2R9Y$t+%NlL^6`$#LQM^@ff_VRh?S=8!|xnW0mHBOfjA{igiVjPATt=m zkj(0x+{v9NSVK`C-!f2Q`rIZG#?f-Igq*_9iFHc9*>>73eIILi(5^*r8=;fbPyeiMn7iEKNx|GQ&c4&tK1G?RA&%_VShk{##Q zY`r-2ot4g~=qoOrU-kB~@!7S|1#X~o*fy~iJszcTInB*`5dH9izbIy}l~MJ+9)2(e zE>4n&;K<26>y(;+cDe1y=jo%dJ7hx)3h0nTEaxA7TR3w9?KX<0lmAI?4#*IRwSQDP z*8r%ei6V*D!N6k7@iYHTEwfVD>&0g1p|V$oWIgWd#aqcGFM#1%AXe~len*|A9r|?s zWLXO>S>?@q6rmYH%QzaXoa3OmmTpiKd7UJNAxM;e%NjRoZK2P;R`B$GURs~&_kMeriNq&t8jX}b8 zd*9G@JltnrMVLfL6W53w;B}t6osu(@=RlOg;P_Ghk?)6P2Sq(PBW3i<94rNp(bzau zq@7-=d+6bX|0VhX09!Kuv8R)rvwNKNvuwI3!Zdx8l2K88KykyCODM7 zk2_(4Pcis)^0$UR9Y^PDu8DIa-7Fs&%jw64@=FjspABQly-(UjE@lY5;lzY1jsI;A zgxOb7^hx1?Z)^jHQ#2GKuKcAuCMsw1#JqnugxZFw9<^4~ivwaCFl^_ou5=yp6bJ#? zl{6&%a6d>gPkM=-C(x(ZLe(%uHHiZ6#K5zg_w2>1UP z&4g3!VbE`;z>_y2zPVnn0xOg9X#P0Lr8cl@P;X#}Dc2!4fIF&PK=;Hj?kw9+k7DJj zmod`4hlp@n=vRgr0kg@GeAcS>nn9S@Qq)zxYRfqdS@5=c7lNKF)#?f@=7JRa;0I-0`Gl^5|aKH`%ti65ifnv zdUCCNgVp6SWP9QB3X$kpg%Vp&V_{EGMK139pp+oyx+Zc4*j*|?UH@lfzjBl7N6{O< zcHEJNMz(IFPTm%9{H#0Gz)ZxBy@P(Pl6#!mu20NWoPJ~ygxi}i6PXVJ;%S)#(%Vtg{f1~+yk^22l9|pQ}(9g zp`@R|S^&){bXd2QuOtuUA9OxpT)xC@8rI1WLsDb7%ElAdGMnV?l;O0v0We!&7wy_r z|C>y+*`#AiiDB9X(}ZPks%uSqcUUMGV~dx?N|*TA{jYq|NPdBM6Yp7zc!A@@vep+$ zv`#rM+H`pnDSqv77f)aFIJcC;1-gobScSlu?0xwU6mMid#bEM1xK82ChodZ2HZp3n2r0?rnjHy=(rN`A z83bWCmw**&3iI@^;gK$|ZMT)<&4`ic@&Q;{jG`Yi!ns<-1hr z-ns?2`nL_$y^q5UUb^%(zoM9w@SHlYyn-O#A{>q84Ui@oFNE5V47{ZQ-RFaUt%4lUL#KNL&%APfDV$rGU_{%t^ zf~8{j5nS19l;tB zIm211daClUex&?e?o(A81}}@Z7}!^4_N4Jh)pA zfYZFUQ>=9aNqgp>*Z`jXZc08wcv3ui<=6;*&c5UxMKbLB@OG6{%)opk;A-8B*}G(v z^`q#=E-C7SP_t-}=^T6S)xsh`X`pks(1lc{^5&$>0m;9Nj`oF!M(bpo8DEV#IPz{WFqCi)Zf3Aot`Imp-_lYzn+M8$=ahHCW z(dcz8V`N++xud}TIZ2cV7`WQlVUZBlnhkcSE@h9hx)&w|_a3k%h!wd_$^4yToiD!Q zppdllQ9g|^;FjOS1(gqsb?r{}HfEfE^NipF#>0krvRa~RkDtVx1!lJxpOd6tkARYcZV++GCM+e86@hJFhI%n-OO3+e1uTXyd7G*CugB* zc-_mqYVWLEYlHey#L^A~yMD)FfJGB=DyjMLRaYaRb^DM7VvViVBeMcKiQN59?5S%D zS2;a3is_AP#wqfl*v1L|W{6E^PLRg0aqs+DNO>6k&n)&@qJ@gtIm$0(%mfID%2E)6 zi5%zzzjK0pDts(+?(wf_?&;HgU6neRgdHba7O_j&c-xl;jPcyIwhU8r(k2~c-Ym7H zq#1a}O5UrB4pe9VcHMCqYsHN>my8m|G{$;o)G_503I0fgOxJ^V5Lx@9xM#NH1--4k zqFg-7WwQQs7n`k74t};Hr$NIGs|Lee>}zX$5wV8gw>tl!^?+NDX``|)+XX+}K*LQIKI%l^f<+jL&?^_L=0ICwU4u%&rFvRvO40AG>Ky9OH3?+yq0S7I-HFKdPSMl6wob zz)^Zj1v1^R!;T(sQE$nlc!myi@2Vy!>a+Q8y1fR4M_bN-h*lh0FoS0@HuN@Y80c^ClkV zdE8Ok7o=K^!s&QxKHku$$C`*LjZQL6sz*<}Rzlo@zaG`>5Z_bc)P15CP-W>t(IY77 z3QIMsiX3a`LgF9?18$v2p{fD_ex_zc{;vxCm}{5P+^dIS?W=GQ2uU26W( zt=b}8eU#dhE<5D(?HVK82LKyxQu}SCGIMM z$|_E1t7#cv63T^SXw!bpQpO=iFd4{gi=lmk8i93KYJJ>1(yt$Cu8S%&I?ZAB$p|tJ z_j_@y*j*u+ds_azD6hKnRMbh^p&jR!$&p@Magamd1k|#qAxDppc24G=hCW2Ak;=Zk zR>68cj5b$!ouZauu+1sI?ToiM!aCrEz5jl><~Jzz(pRO-|(UM{RxVNzT8TbFSPWJ_@Vc5@^Ih-N7OmCkQID-LO%1rUYY#!JRF`-eKjuw zjU+}1oiw3^&w;w9gry(`(2-bG99MPygI5<&Vd?F>zpnkoB3QN<|0BQa+vAybf}~I4 zfQ=sfL=Tkv+1n5scmrh@wb9^tZV?mi)ExN~{)|G;{k&;0%6dd9@+9-IvGmm=4vF;2 zEN{TLH6i3Ofhi~vr)JMnnMBh7GWMz7V20tmrYCYxHvgq&UrlN+{g-j55KyY^hkgrI z2Vsjz>V^^mt2x~26Sk=G(Q4bx7t}k&Ib*^6v^u)S+|&du9~LfmPSbdJ1t-Qb7W`K3 zhxyx4i>W8Gd4SmE&I__5u{qv5UDUX2HUaZKRCuqjaHX7#0%(;v*AG_{$VuyE^N3!j z307|MZ$s%Wt%r!21B;n8w}etn5Hzg!k-mgp=k|Y6h`rO4+7AoyHVM+^0+TFR21Ew0 zSL=BgDCX2G!#@r)l1csOJ}QfhNC8W4VEdJBym;tC#U@B)e{X#-uquwfu+LqlSR*id zB4Z==JylN)boNc1QoFcFl>0>cHnn6 z5ZF@+(uL1dQeB2y;LpIK@doR$fTT)h;64m?9(w*79;6RykK-S2TkQiM5A}l@OlC$N zY*63)=vV+4XUz3OjZUGoqW2tP;d-(*&AAu!)x#PmtD#|JracvW79rXsYx;X*XGIWN zzgjc5ZNuS+7-Xq=2r)NecOey#YHRO>b&{52OhVLwL@%XoX;X(34mOd}T~Cuvr#Hy) zNhb;qtu30B;yuTei+l!hs>9Q(7Wik8I)bo{r&`_BZ5_EkDHtlfC8yGDDk#bOvg&Wq zJhUdqVa@hrH+H|{Ecj<&zk?u5nz^^w37LPNGIc&B3bZFp_u<4B{gymT#z{5Q4cEnC zGcS8i137|V0ZIDrmO{X38eKQ=7HAAjj@Z=8J4~X?i}YyOS5`-SRB^ehN_cJ22+ z0x=46gg;{%^J5{)O@O+ugDkx*8S!lhqqkejUOItEdy{7AXcqlY79p-Rk%>d^)kL## z{&GsUjVS!W%9rO3XmO%=&|xGm{7E4^;FVoqm^R2^d0>$0Ig_l2fb zK@a*43dy~SNO2-n%;YRZ zyg`ue)6iE#4vzA<6_jJ;_r|0Z>q5F+eHyCAkr?735^wl}0`S5f@P2{61i&b^iTV5N zP$i7`Ept4)a@Sr!KK!%Bzs|CfzRSY%fFrd5tL1Mi-s|LQN7rmQ0$*Yh4G54x>b%>cr!yBO1M!;Kg@ri^+r4S>=2u4QYH<9asSW-(GT z^%m@_r`xRiZdH16N;4|O?&*{|pFFNQm~Mut-Qey9M3<5Pmyo%x`5k7laR1!@dCVF_2A57dHz~^ zB9d{oQ?FoF#}>$nD|aO5&er_+RrpgS6*UC3JE?nJSB$ce4>|SWna!Pnchuy=?{dOA zlZ~NguXW!|Jn?Fu?Mq(6H#(We^$=!Ysz*m2$t{nEV)#m8)%mfLV@W&$Fb0S@82G+| zBM2hW__cdjl{{KmRJOSUet#jt=%7)Pyk$E_5pFz$P<}y^nNypBUSfNJB98Kd6-;VB7D>_{$UEu zfQ#y(`&YdZij5_%oxU-NvwEXpVypQT=wd2S+{j)qZjrbf{&M=rXK|7f9@Ae*y35#fE%!~%ayUWZL}lzNaSyQOsw!P(`XFI-!l#1jMYILA?3KNdHf`(H{6Qd zowf)0`w-OM2uRI?HZJ*h`(|74|3`_W97{}VA$9 zZ5#s$XMS}_&}&me?bZIJ%C`vm$ALZw)^st$cq(&XA5=g3FMV?`Y^+-kQ1g3H>NXPQ zm&%r*BOD}5gQ~D*E2K)sP8+`9T`Qi)U>j!-W7@s#I-v5LGUCh;k#Rv(;@Mfwa@-KV zR$y_toSiPnU_);Zj&Z#8XOX+X#CAQkuR>E}2NzrZmp^%xx4UKK;4x)bCb6vE{!2?= zEz{JiDE0TzqdOUB1Di ziHI_iWeIy~9HgjeyLY}YGF87*?^-%?Id0#2U_V-Mg-CJVpY|~nXLnc;glfcmy2MkS z!Ys>#(-R(cS@FQh6_itPm^29UZ1`a4_;HjXztD=ltm}OW?kJx7ico-uEn*UP)a5s? zK?}!8d)F5at!JG;9bE`R4>U%vA1t1S^zGF|=8-*Hq|wJJz2a@zxe`eAE}LO(A~J2` z$%*{445-BmY(zMwE?@$CoahBQH4NdF)f#S&un$EkAs(z*>iEs8aS*eFVp@gZrO_Ew z`0s*|q%WbyuXD2Aom^VTWm(MvRmp;b=kF5mg)D{2Dku+O9krjkqnXClXzHt6HQv*} z^-6eHSGC}~KDV$x?O>=4-7WI4zEL8!1dUm=BeU%q^V}SjF^VrVDuAWg;)8oxq$E}X z7El|6KL@R}I9@|=4Q)dcX|v)O;V;6gTR_nJ`&<2S!2MSnR<;W+H_6>;HP0qtW@1A=ymCGrbNKBGe{;NuV?$eB`XHJ`reE z2vkjnxvD=cF>*;*KN^6lG7F1It%H!&I1e)JZgK>RDPf}CcNq@+~2ivgDmCf^J2LTn8@xkce<(7NZG%J_pAnN@N@En%wlMcFnG{M^8Dyj!^g z`sxXFwn4G~KNYE1Wl)ZfDns_dl+EVP?~GuGWL0r1 zMHyy5V8*GGTRLXCsj&L!e+Cg(F-Gc6=~2_U5e;Aq#X*e4WqqzgVyP5yBYoL{Bkh=4 z$^kCha`Vp!fCEWeyYXCVv{Xto(J|fh96*F=SAO|gUMWBJpa8Ze2WVnP~79Z9;6ZT39nv2ALd#Qemv%b7|NYdmnISIhwyd zA{bG9@|9b!tI*$*AqJ*T+Uiu-PG$KpD-iE=aF6d!-DB6(NH&TYF=dcesG&uruxlG- zp4++?fO^jHBrQGMPHR>QorT*$4*9L=G#eI~>7J zmvRT<40R@@{vLeUK(jK#x2snip|WT-mU52`=ADK8v-B-ukfAcz)wK~dHJTQh$$f6k zq?;128Z4&@bRV}ezJ7}~SE*KS0aI9!i4+;}g~sQX6K%T=J#}%b{6qtzAc#(43hNib z+Rc(P2j@C&E^4i!{aJcSskC$$80!>gR2GuSBNi9&j@v_J6@N&7tzYSho)1s|Z-Kb8 zaw+T0ST904RQBv%^C1n<;qdH$Mq&C?ssuYM`+JlPAjXN-U^+=DlD<;%lXu@rQ)JF* zavIbUtSsy5S0RO8ym+vFnJa~`fJA3*XaG}?Tqn5HHzmHUHC41#JcVhfT|H}=Go=x#@|JZIdfmYt9jNK?AvrhinDfiu5Aex zd6tQH*kAXAFl5-|V&wf9&A$Jk0S`wt;5FR;UENXMC<&|czXzEM8}EBv{qwlT$f(TH{Io?2xtB} zi|}#a=xyNZ8n5#<6`Mg^`tjM6FeX(k`l0Z1kM_68Jo+}7|<&ytFPk2*E)kIpjC23$uo91CKeCJGLoW(JldehsihE4$)MGLswl2o<-Fcl{QP z*YDg;_@JN9R3&Lbv`yq_N@e^Y?2}t(N#;3Oo=v9u^|p+M!$d+a_QKyeVEEpDvHlT( z6u-B}Cq;-=CE>?dbn`_|@y&~)X_gCmGz+l+ML@d0KXb#DsuWGC?3{bWC+Cd|9uN*$k=@Jjs}RF;V(5TgZYbSTeL2pm@b0*e`^ zQ{eyWWYpEsK*JI26sgta*HLei0~Q;&M9pX7FNPr$q6Qb3W(H!tn!Ej|CUO%EFYtKD zENWmzxzO;lg$F7Ib;ek|5;i~3YI!YO`{y4C@%e0%9I9Cm90!Y#?XmiotJef079%`7 zZ;VL!2;92$slcI|>UWY}^IwXcUyN}KSgjjUHMU>0=oT=@Hjp%lf1 zD-)fWg&n7bud$xv>M^3*D{O5!FV_&!Rtv$|`K#Yq}+Ek1l-|F~CigO^E946GZWT#>F~zxe^@Qi=~Pe2Lp6x zBgWn-=Q}0`rjJHbHrZzohjZjp&7b9Vv0K%nq(}En{jr&6mk0+8*4)66tUs6gYwr++ zootL2j}W??qswA0n`gk`L)j`AR&?HhXa2{)64hQX=)*;KvkXCsiv08Z$xWJ+XMg38 z2_dnq<*31Y;8>ZBS{)omCU|iG_x~KV8Rn7I(6=Yqcr%No!P5Vi^^wVqzTV5ZW*R0j zWt*-pPhZrG)lnuW9&b#<7_E@cXZ)lkekiQL<$2jaoRTOrTFH#J-oAG9%LGwrjg^!> z9s;&u2#X4F^{4y0DGF&jP}OkT0uy(t--j7Rkn^2fhjJ&bn6y!=JVk z?ont~1RvnlT((9y8Z13(FnRL#84`&{3L(u#3#)oDe787~CL=v7ox&orGRZk%Lj1)G|~x<62GW znl8h0K>rylPp<*GiR?PzowvE%pNpCG;&+9;_hn7RK9mdjrOoC`YqN0~?98*jeh3tJ z#g@zeOmOx;6%P~W02w1FMOlP1CAyhb< z%xoSu8R<#Lmhw)@&h~_a-8&vo1P@%ay2CT#0+F76&4A}7Vcy7EqO`O_?~hm@5`Rf&K-aUOU)XfvsJHz&l3r2aV!`+xo&~A5k6-(5>Sf3%RM9d1 ze^v80oeNvl6=wHwy)vZx#XPlwnR1y+_l4_>4Wwj8WI7 z_I`67di%p26L?+|?z$$F+2Z7{GJpq^fTzbXY^f9X<)ft4TI5L`J{U6X4mGvFwV$!4 z|CaY)bTNuXoj&MTqWh8$>AB6(IiwljW{5o`8jwG7dGvv3mii&Mv5$DuQNP3!;aeQh z@o?#n@r3YGJUF?<0)RT@ZOL(ihCJs?609XjP@LI1xgBTZ);nXti9fl4{0(myphe^& z)6f$n)Wu4S(FXVe)}pUW)oB2$*j5v+a!rmGn?V7mbb@!a<{#piD)!>r18c8K2!xHL z;(tjD0gzu1AP)d!<^hJiOtJz;YJg4T$~l^$b);e$xf8p2`taZdYO`Z$bmWTLS5H^U z(4w?O0*z5@2HlRu8%V~t#$^fxAx}-aB|~KfZw~^=5{?D0f}{4>o|+Fx98CC4YG8&{CrD^uhD=8v-gCF%-6v8eM3n#ZV@XdJ1MP>0)-y!`)! z=1hjw82j#0>5^=AFRpo-nuqNqM@Ry$dQfZzw2GM9akm(sT4E~^J*@#i;D35R89Xu6 zzpE^gnvQaTN3O3_?HJ+RhWCKGXG!B=%^oSn&+AON&#JiWcO@%i527|f77p2aM>K?W z;069;85Q*J9wpudS{I~X-F1P?8&YqZEVoXr-Y}Nw3$HOfbC(5jtmdP&@o%x|HrJh@ zKRufYsm@&3tg6;sVRl}8i81G1~C#@k&2OyNEY8s zBB>L_II?;UKu=oA1b&UP$Zhv3k9D|VF9=~3!|b~s4Zp|A zN6uYfx_(`OzGASO_IO!-?6onx8Z-$O>2|;(CF)SWDbzuzWX6$iA2PL6w(ZUwX{`Oz z$^%B(dwUpDrPGCpW3aF$!n-eVC5jRe8sQ3qIc!@og`$5=^ti!-*RL_S7622609fFy zu~9dsopS$KG@P#s>tj>b!S5;RwH)CJ-c`EYMM#Sx;>=1wmLQU7Unjt%CJ)13duI(6@xYfPM zs#!G231j|uYi$w}6Ee!LEbBG#$V&L>atp|)oud8P5d5(zLYf8t9zi&sg9O%IlZa{L z7a=Qd2UD~`Q-P61CJ}&pT6klJKnUh&-{{>vomwuSS#T*b>ArT@nISji%-hjeh`RM^ zNHeY4)+ZT67a74ai@qiC7c)euRah~nDCnP!+R*l__-q0P9!T2s&wBTiZQGa*TxeX=M4s52bl7B~vBrq>B}It0x!94(?)6g(T_ajK zIxJtZO$M$2+5IN6VtVHygLHdNj73NQlWEK~K~ao>1~%-%KFbvo2eGS*gy3W(#u^t& zRfen*fSj)BB7B`4FO7Q@B^hJ_Q@F*Epd1}x2UNi0l8&BpFcTBS`ZBcCtu@z6O5{T5 z#)U7YOq4UW0hL|xLen2wcZjRJ&|h{cpBslj33LJZdcrlk3#@EgWPDudvS6vkQ*N{&&>KoO}UI2}tBwW&kYME@(c~DamhTGn;^+k!EQLI=|=eaJ}#O zeYfgRU)xD;B}g%E%u$LgipNF`oE#&{_hNd@>l2=O`6a(2`5Ptl88q44TdI!iq(?4? z4=87uu#!q+0-}Uz;GNE8$fwOtlX`oXzBrM_qSkM8B?B>zZiWOZg5YY&QABMlwD$1> zi_Ke+kL0r*br6UYdzfd1rTV#VWmpAB%yJKZ* zSo{zKTc^%3bE7RW5BJjr7eX5XaKj+;{@GLV6~TQ!B!k2C0!^?ZIs?g~eql*9#ldE4 z7%ctp%hpD!224*F#xnXA2w{-pRK1<2o4VjQmzV#dRq!92am&bMPTL>%mY=-3H>hsf z$9{`pOl%WJtbS_?#M!p-btsm8gyIE6Dp1grqz4e~Ty(ECE4tB3Uh$ZArN;=hxLsd* z3w#E%mQ*EF(7qc+!y)xID&o52BP@J$OwBg?mZxR)yI$A807Vpvr+MeM@dS~_)!MEfP^)zsdVqw(dGb;k8bkxTsC zb~16O4Le>S++NF1SvNVD1M7r4&O=d z2$O2zh*Sf@gBsP+;h?t$qj6t7)m3XNGT`TC%((hOW}AU0$=ieR320RClQ(^ z-&xz%;2EPeE(BMC>4zGFR4`Y`QwwsQO6G~h%tDb1GSk!Q=|eo2iujjQ1o2ezqdM38 zR8=1(e>HY!0lL>{Hq(?#ZmaGk#5VylIOip^64}XDcjsTfu;dveQX+^GBV3WJD`H=v zD_ch&bsimN;U|j%vp1)HYbjI&__mUROsoq#0HcT3CGDR4%skb^CL115&Uq`Nt~V(5 zLksiKQrL=%0^e5UT1!Z%si-?*8)2j66?(X81nR#kp(a8VTp;zc11*(i&6$MQN)9#i z$)Ie=%kW02&DNWwdwO=98v!PYQ)3wZyKczaxJkpiMJ-Qs)4zoCAYPmUAU&2g@fV?# zlQPrEmejI)2pk+AhYRi3>^mkx+- z-Dcu=tL=k)$iWCgs1e*Ks1vOd>bP+~0J6GH_oTf;KJ+hNwI{sjCDv;1w z#Gu2lnBOmVW#0%eHeGsD?UftdIKl*rtz%9sqE2yngT1(7uabTC03872D0fz|VnG+< zG}bsP_(1_}0f}rzZD~UzFI?GA2`=Z!L9Wr6HT9z_s#Ed#L@~WYEz~W|#t=1pqV@Q) zalN8({mND>P_sE&;VQlJcF$7kra&RxPdv6rnz_8N-95!NaSV=N&Y}S5EOpL?%D<0b zfFAo_u^_wuLw6B+b{4FCCj_6jEdTr))U(h*dbY%w><`0E(wEu%*OV{6^-z6)rQbF` z3d#6Yi9(OF`hAiq5kbC zWRdl@R*N_mdb`23=l7T=@gD|xRWk|vbgoH)ESm|zoAQeS z;fiu5NMAW;($e)2^th<}9}7bNrhTZme-Y6yEZ`@t_ot+Kgy}xYN4a}RH-obg^y^-{ zW%ZSzd`1f$DjTcnCX;}0yuI+@#J$G;zP<8{tUkuTro=l@k3W9^l1{dFu5rrMpr`!@ zfI+&0#S~mBNmo&)vO*#CLw5)Nybo!Tcb-SgsTJ$BGvLI{w{?G7mys6 ztC&N6v7o&jCcm*5kQX|F#E#uXF>RBn1r8@ zvRjg0lZ3Q~QaDsNGLyOTO&Ks6x`*F_C3E?Cu3Z`CxD)1_Li(LLm?#L< z_=k`(rtr`1hegNKyD8Pg2%%;*m)pKJf)E4=$22aZ61PvzW3y=U-Bat@=ian;x7}}n z{f3%P<$u(DBhc7~HbS;YWq0ng$Ae8RfH^vHd0@>pT(4Mc0Z=_4Do1|~Mef&Mtve-B zrbdC8nF?{LM^6K9tn;s>e2EkVS9BkGs~F3`#e#)9L!sHOcT@emRRRTMv;^`;-IIi9 z$YwT^t;_;BEUBIJGje}`iIgE-QBXZ=;d;+#@c^wzx2Kc;xH%=DCzYTZF!CaQY(frHgN}sds7Crl%g;OYD2!4sH@}8;M@c4gX z>=7Wi{S-eCBF=vb1|p3!N!l{f5-dDn^HZo0u~fUS@72Ex`7ctJ_8Iasq{pjW)O(8A zH=(eCh+#N!Gll>E;kz#t=qOZ9$EB$1seeRk*v*wyS@q;!#uXI@)^b8U=%hy_G$M2; ziXY!DRw1R!2-Q5#Zy-&Us2}+Y;@2uxoPxC~?_y-x@@u?JAo0tFHM^daL+IzJsH+a^ z5YPj0CIkbVRV)y!c@C{(l9MUXjyaDeD!5r-sX%O1e82tseJaBA2nXoi0+uF!K_LXA zoWB2=N146;B|CL;4Qrs;0k_yRpN@6ej)=v>flk@YX|`v|UcGH*)HMS1a^IH|*cNsz zt=R-O*r&;GqksgM7GI%p92&&tRz>Et(zuiRq)J5JjeW48xs-z zg8n(hlj<$Q;0^{Q2%Csr)S$y*jA^L|yFHQJ3H#S?XZxw>&jcK=1* zUSqv{Auw)7CY8cGqI{xihJXr6ilo@em>GPAu$1G1pC`X^mijUqzP)GH!#(4-Igb58 z6p(IgWTb^C+^x$YkYJY7SHXh`6in}%liu9HJR{_Q)pI%)k$fe}PIRLjU4;hc6vHCYQ&&VH~bkO$s zA4{xIL3OK48bv@GBQpRoA6h&0 zvWXgkW3pE{Gpl!_cX^@SOY(zA5ZW$VWwbOAGVC)F#(4q_-u z^5u#(wo{GXK3PS0v3|FroZ5&tE7785cxO!`BffPG(LOI|I^{$`&(9F>jC+&NFknnl zZLRw1XP7LW7CtMKBFLXpj0hQZOEannWF}N5^E_KiH!oldR2?3_hgRci+|oui(oeh1 z7M2irITebE0AkH6-AP}BGp%5=Q?CDSE#Luj`}D~rfjVjQrJ{omo>{52_wwAmqTllN zK^!u-`sObBnW|M#*fl$@?O1C?B!7QXiCWMLP+A5uLa+A&irVgBm$paLPsZD;fGiPb z0nDFCLKGaB@pB+^GhiBzh5|| zDv+GtCf3kqM0j9M)I&L2w63B|&K}!O&3fpjeQpii=sf`gq6rPHxrmq@&;<5n)6yA3 z4cWnlh{@`g{of&ASo`=|0MN*;#iym{X*jRw(t4YO^rkO8_(>km?$GTLva1z(G|<#? zY_+LGym?nr-c*lJ)$4miNzTlN-RMWe`dw{g5ke{pHUmrKizK#VA&L@PwBF8a;t{O9YKQu8e0KvwLKxlG4 z#n^@@=omLWIQ{MD^KLiLI#b1Fyhu*XVQ@njj5AJJr3jw21@C z3k@jWRX8t4=#^<-mG9?c(T4&tLfxt3?o!?5QEpXomQPFuz48K;=8#gWS04bEe+V#q z7oa*lFsklqXZ34cI!ztrS`>wR1RMu86lhL&527-;G&* zCwhx29z1dn$6uehzE~Lii~{h?Qw!{h3J00RZYPwJ|4lu6pj3((oF}(8prJ*0T@ zOn0LGKxY|?;TSLIVI~*c0oyzj%d600g^$D>-oZAIc^a?m3I7ADpOGl8t0BQ`oXDQ^ zL{6xY!tFt$Ju~$gKv*Vfy(9}>!1vj{YR0y)$N-Rx%?C%bM=5dwCbJ8-kpBg&q$~Qu`0EBN{Hx$rO^?N$1)yr@ElhLLN<#8 z%U20lKxnvv+-yRU5Kc(G>$bK>esN?#cwRO6@6E}OtmtdssXWh2P@5qNs0E+tp;aGD ze6S8E(bOdQs2Gb@Bt6~o2)YM41kRihcrS#pyey-&ewy+ub41ct16Dnicc%!?b9QY< zL33fPPt5Fn2x-W^O5jl*Q!sqr9#v&oNiWri&;Uk-p|~X}l=TFiSV}^s^o`_rMmMkJ zvny@3yQXvdYt-q;=ervRRbImhy!_Z#l%r3>ltis8JThRa=Uq%#r8Y-~sV>DZ(2H8C z1Rs#)a_8Pj0bL7aJ=0lv4lGcqoR0RBoBL-e%s#fQMn3mtC%jy?yFOMRRM}4GGrh># zt&7!EEr>#zdBNZV6MM==2{zSV7{Rmr5AuMQE#H%5*xoQv%QOqRO{|i4Q}-EGvZIX= zzQomCQuRue!I1eQq%qeWzDp2u%Q3U1FN=vQGM0mSbP6wEx@CrqG=xpKUUhn^A<@Wi z7wjjGo=yiQ^^+%>A2am59yXKI}pln$AQF$JX3VvM)`vMAGr&{#D zq5z3-5IQn10D%en%Q=Fphd&+j_i(X*53u{|I_UWrdZ+88YbP!prs!w{5U5VA{PRIX zL-$<6LxG`6Ny9Xv(v>5`t7mahVYYP?|1G@ya64^OH?QYOd0Mh!9Z0+*l9li-bFT$< zoW*kSN?E(Z(Wu14IcT3T93!l-`ajntJge)DCE z|L#nepGF43643mlR7t{*0>4^CgDD+D=RKq5xlW440BFE>Eo;^TS`xvDZh%b}Sv9vi zjpSqZrqgP5B%z)XZ~1~M0#&- z9ym^2None3FfJtYo*89n%e}zU8b=kUD3Te>SL0j>#AzBvFJ5lyBQxr4(k!#z?Z?xA z-=`i>T;~Yxx^PIIurvU1UBUzsMj5*;^*ELi_;-izk92APD)wSLTDY@FG2DkN{w5@B zHbw-KEWq{^yk$#DO)3>+r7(Rm=8K~PXsv_EA+H4o`nVklSRtKKF(Jcga7DiuY?YaC_m~r<59$(u5Ox%4H|p48vFsyQiE; zM)!1Jd^~kZt-cFU_9g+iFFhFS7Q{XDB7WFBdZ{OA#1{KBz~5pewdZ!*zI}XiGpZGJ z)i6;BWnJ#1QMXrqLE3@4wdzK}grN=GxHS`_qlVrCMmb7{TL?Mj zDfXkI$4<`|c7F8M?X$kZT9Gu*mLP;L3>=UqaT7G1GV<(PPV{}U=$gT1=~vI50E$?P?&GR|bkc6l*QL2u zcqk7hz8^hLL;d3*8xTyf=rdk}dMZf_*)R_$MC}R{m2eGRpucOy+OFMHhg%jWf*S|* z5fix!jkgEcFD}mep+DCl?#aAljQn#CJ$o48e|q`|%iX|ZD|`VzRg*5Skyt+O$5MZJ zjnUBF1`C_}!k$!>r=ssiJI{Ky#N96^4h+3{^*Re4*#=DMcPXgXtyGyp5kz9Yloo1HDxXu^Whlb>x;%vEvsex;@lX@=RzrpDx|{Q#h<=T+Z2(I z(nXKv`ywW-J^B8KHD&mkZv0`Kd~o4fTn5((#}pCdsQ{*1NW z6ZI*}`;rgBj0XFxvjL@jts5Jp`_9y!banYfg?z<0KUO1mbS|&od!R>!4L7wu2 zCztkXFB>tz4WL)tYem?Yr^9(Q|AP+8q&}44FyYE^wlMh(<@D4eGgdU~+VN5px+)=T zL99iboTs8y!<`ug1R>#uu)2m=vrGSc>__n%o%U;;X9?2y${!ibs|C1|zq53Ue*J|X zIA3FF(0L`xDVl&I??(7?9DsK%P%x z zwKTD;WS{r~kav5lEoE4g0DVd_B2bXymEk`aXI=**g4!3{7ftW|!(g=>4(joL+j)Cb zzIX<9rT<(ni&ghZBRd#?n`<~Ky=S9M4234T;dd>hI4(XrLG}rrGA**)nskJ%c*5N* z&b>;tnC>1%&i3a)%5JxCGBkLAK;&a@n`l|W%_|1V#!02Wd#3ZLiwZ;6&=3CKe-GkQ z4QhPVpyVy7(0?$tZ7sr?rO(H%7p?G&QiHdWnFM%al6slL4~;n)j_=Il<`^KHF4)sX z!`g?1p`vY|2lG9NuXC$>bYLCzCQw&b>K*YWT&GlaZ!COMq7Y;cMLmY|Ocw-gjSKNh zPM8)H%X;XO@r_u|X>BUL_uJSkT%C~XdrH3TP=PN2!b1xtqN^S7VZdypyw6a`MJHW` z0%GXlUKDvMjM_Lzv@2xxTi zJ6RNK7^!G;v59am+MxRj{+J*3 zf5=i!F?Rpg*9kti4&cv_m7LR9)1Yz8iUsAP5ogJ(Ujx^^FfJiCCT8?b29#_D52~tB z?O&EXP7-5W3L!!18#6>(_Lb->2a$}HE!u$rkFncu(@F>nl;z&Au-qYp=n;2n0<|f7 zVnMCba&Gqn`%T&8{hPhE6yYfI$Yx5x^_&4;AO!>WKZ|i0L zz%ZQsq1zom?*gOsd57OpX=QhlgA|$1ULtgmFSjNJ!O`CMp_D&$Tb-1988xSQh<)AQ zdYmB|{=bcnTRe=_C$|~;-zWBm7_R8h##(gpOyPQ1rLYXXGbM2j`1H=%lY%sKt2Gg+ z7fM8YhOu#xcNx`p1spu?Shc=9t}U(h91&)x{oVlMbS{97&U=P~m7i z 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 diff --git a/Include/A_HistoryChecker.mqh b/Include/A_HistoryChecker.mqh deleted file mode 100644 index cce9256868ab3b6bd42f61c4df16378c2c6805cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4692 zcmd5~}Y@fsS5S~t8Erz{iS;TKi>bQRkZ)b8UN4TEgc@6gw z{P*F#i|2Q^o+73$X8Y2?^=9$RjwfS{5ql)hd@a5ThoaJ#r?@*r%!5=scZoj_5&O`i z&uYe~f%6e(t5HGSZ@Wen&zQUj`ryGSY97|1;(0L()@qk*{DPQ!V2uk{n`U!WYCZ~j zy7+VFWCR|Oab%m07?zavv8;ldE5T~=awPBZ4cW+{s2<~+IJ2^YnJ#|433u%-w8w5^ zFC_jWRAvAVXYdiO%tq<(c(8qYPj%aD*N9dpY2wRx%c$PRI;G{jtVI8>- zG1MjzbXQ)66_v{4ra3oc{Ys#){$hI_~Fb(v1EfsOPO8lDG9wLG&eu`ZZ zPrW3TwB3Kj&j~;CraM4y&n!NxT-x)&A!*d_6|QL-J@QWS6%p5#kqJksOPO^pgXvYvW>n&YP1t&i{U<~cB z@?;X960WM>o*W|=<%L-(s^x3=jXhgzWfgX77%zZPq6Nkd{+-TrI^QI>ABdXSGBajj z`pQnYgzrl~OGK`dqk1&v^Jx_sXM43)z+laK!}oj_nnvu?c-7H^P3)_i=*Bksatlw! zFZCT>Lp3T#nmuYtR_w7Q`|$V@YOq=2)s#)M&+paiX1ec{s5sL^CyDrN_-x`d(}wo# zmt-359_3ye=n30-it*inzioMiy0%NahW*Ra75Bid-=(NlWHNmvT^q81jHkZyJ$p9x zU7GDw4(&_!8&kqII*R8%s`E6@_=b9EY(4wK$ zk5W}7;oPd%@~}&kI|tzH9;(R`Cr{$De9=M#n;1?WVVFkfX~D?@?`aWd$09{i9E)^G z-}Vv7Jbrf02zTsR5o!sBu&!euM&34!kYCoLOI!?!>Gik2b z4#kM5pFHtqcUrD_fq62__6cJh5w$t;i_GMIL}Wg@K-qg;ZYD^Z%@!iF6Q5ZPJI>Z6 ze6zk$Td=JoeqP?7O9$ z2YGB*laF4tsBZ(Wc&u-Df>TtBBPd5keSV)hv*^5D^Ux#v%DZ2`y(xNnKFyvF!|1~M cbSLeCQ4tj8e<7ETYIZhx);sP#cj-Uy-(t#m7ytkO diff --git a/Include/A_LotSizeCal.mqh b/Include/A_LotSizeCal.mqh deleted file mode 100644 index 79f5c11..0000000 --- a/Include/A_LotSizeCal.mqh +++ /dev/null @@ -1,62 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_LotSizeCal.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -//Lot Size Calculator -void LotSizeCalculate(double SL=0) - { -//If the position size is dynamic - if(RiskDefaultSize==RISK_DEFAULT_AUTO) - { - //If the stop loss is not zero then calculate the lot size - if(SL!=0) - { - double RiskBaseAmount=0; - //TickValue is the value of the individual price increment for 1 lot of the instrument, expressed in the account currenty - TickValue=SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE); - //Define the base for the risk calculation depending on the parameter chosen - if(RiskBase==RISK_BASE_BALANCE) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_BALANCE); - if(RiskBase==RISK_BASE_EQUITY) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_EQUITY); - if(RiskBase==RISK_BASE_FREEMARGIN) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_FREEMARGIN); - //Calculate the Position Size - Print("Multiplier ", lotMultiplier, "Before lot multiplier ", (RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue)); - Print("RiskBaseAmount ", RiskBaseAmount, " MaxRiskPerTrade ", MaxRiskPerTrade, "Stop loss ", SL, " TickValue ", TickValue); - - LotSize=((RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue)); - - Print("After lot multiplier ", LotSize, " Lot multiplier ", lotMultiplier); - if(ActiveMartingale) - { - LotSize = LotSize * lotMultiplier; - } - } - //If the stop loss is zero then the lot size is the default one - if(SL==0) - { - LotSize=DefaultLotSize; - } - } -//Normalize the Lot Size to satisfy the allowed lot increment and minimum and maximum position size - LotSize=MathFloor(LotSize/SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP))*SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP); - -//Limit the lot size in case it is greater than the maximum allowed by the user - if(LotSize>MaxLotSize) - LotSize=MaxLotSize; -//Limit the lot size in case it is greater than the maximum allowed by the broker - if(LotSize>SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)) - LotSize=SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX); - Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)); -//If the lot size is too small then set it to 0 and don't trade - if(LotSize < SymbolInfoDouble(Symb,SYMBOL_VOLUME_MIN)) - { - LotSize=0; - Print("Lot size too small"); - } - } diff --git a/Include/A_Parameters.mqh b/Include/A_Parameters.mqh deleted file mode 100644 index 42702da..0000000 --- a/Include/A_Parameters.mqh +++ /dev/null @@ -1,213 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_Parameters.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -//+------------------------------------------------------------------+ -//| defines | -//+------------------------------------------------------------------+ - -//-ENUMERATIVE VARIABLES-// -//Enumerative variables are useful to associate numerical values to easy to remember strings -//It is similar to constants but also helps if the variable is set from the input page of the EA -//The text after the // is what you see in the input paramenters when the EA loads -//It is good practice to place all the enumberative at the start - -//Enumerative for the entry signal value -enum ENUM_SIGNAL_ENTRY - { - SIGNAL_ENTRY_NEUTRAL=0, //SIGNAL ENTRY NEUTRAL - SIGNAL_ENTRY_BUY=1, //SIGNAL ENTRY BUY - SIGNAL_ENTRY_SELL=-1, //SIGNAL ENTRY SELL - }; - -//Enumerative for the exit signal value -enum ENUM_SIGNAL_EXIT - { - SIGNAL_EXIT_NEUTRAL=0, //SIGNAL EXIT NEUTRAL - SIGNAL_EXIT_BUY=1, //SIGNAL EXIT BUY - SIGNAL_EXIT_SELL=-1, //SIGNAL EXIT SELL - SIGNAL_EXIT_ALL=2, //SIGNAL EXIT ALL - }; - -//Enumerative for the allowed trading direction -enum ENUM_TRADING_ALLOW_DIRECTION - { - TRADING_ALLOW_BOTH=0, //ALLOW BOTH BUY AND SELL - TRADING_ALLOW_BUY=1, //ALLOW BUY ONLY - TRADING_ALLOW_SELL=-1, //ALLOW SELL ONLY - }; - -//Enumerative for the base used for risk calculation -enum ENUM_RISK_BASE - { - RISK_BASE_EQUITY=1, //EQUITY - RISK_BASE_BALANCE=2, //BALANCE - RISK_BASE_FREEMARGIN=3, //FREE MARGIN - }; - -//Enumerative for the default risk size -enum ENUM_RISK_DEFAULT_SIZE - { - RISK_DEFAULT_FIXED=1, //FIXED SIZE - RISK_DEFAULT_AUTO=2, //AUTOMATIC SIZE BASED ON RISK - }; - -//Enumerative for the Stop Loss mode -enum ENUM_MODE_SL - { - SL_FIXED=0, //FIXED STOP LOSS - SL_AUTO=1, //AUTOMATIC STOP LOSS - }; - -//Enumerative for the Take Profit Mode -enum ENUM_MODE_TP - { - TP_FIXED=0, //FIXED TAKE PROFIT - TP_AUTO=1, //AUTOMATIC TAKE PROFIT - }; - -//Enumerative for the stop loss calculation -enum ENUM_MODE_SL_BY - { - SL_BY_POINTS=0, //STOP LOSS PASSED IN POINTS - SL_BY_PRICE=1, //STOP LOSS PASSED BY PRICE - }; - -//Enumerative for candle type -enum ENUM_CANDLE_TYPE - { - NEUTRAL_CANDLE=0, - BEARISH_CANDLE=1, - BULLISH_CANDLE=2, - }; - -//Enumerative for price momentum -enum ENUM_PRICE_MOMENTUM - { - UP=2, - DOWN=1, - NEUTRAL=0, - }; - -struct LastTransaction - { - string time; - int type; - double profit; - } lt; - -//-INPUT PARAMETERS-// -//The input parameters are the ones that can be set by the user when launching the EA -//If you place a comment following the input variable this will be shown as description of the field - -//This is where you should include the input parameters for your entry and exit signals -input string Comment_strategy="=========="; //Entry And Exit Settings -//Add in this section the parameters for the indicators used in your entry and exit - -//General input parameters -input string Comment_0="=========="; //Risk Management Settings -input ENUM_RISK_DEFAULT_SIZE RiskDefaultSize=RISK_DEFAULT_AUTO; //Position Size Mode -input double DefaultLotSize=1; //Position Size (if fixed or if no stop loss defined) -input ENUM_RISK_BASE RiskBase=RISK_BASE_BALANCE; //Risk Base -input double MaxRiskPerTrade=0.5; //Percentage To Risk Each Trade -input double MinLotSize=0.01; //Minimum Position Size Allowed -input double MaxLotSize=100; //Maximum Position Size Allowed - -input string Comment_1="=========="; //Trading Hours Settings -input bool UseTradingHours=false; //Limit Trading Hours -input string TradingHourStart="01"; //Trading Start Hour (Broker Server Hour) -input string TradingHourEnd="23"; //Trading End Hour (Broker Server Hour) -input string TradingStartMin="30"; //Trading Start minute (Broker Server Hour) -input string TradingEndMin="00"; //Trading End minute - -input string Comment_2="=========="; //Stop Loss And Take Profit Settings -input ENUM_MODE_SL StopLossMode=SL_AUTO; //Stop Loss Mode -input int DefaultStopLoss=0; //Default Stop Loss In Points (0=No Stop Loss) -input int MinStopLoss=0; //Minimum Allowed Stop Loss In Points -input int MaxStopLoss=5000; //Maximum Allowed Stop Loss In Points -input bool AtrStopLoss=false; //Set Stop loss based on ATR -input int atr_sl_factor=3; //Multiplicator for ATR stop loss -input ENUM_MODE_TP TakeProfitMode=TP_AUTO; //Take Profit Mode -input int DefaultTakeProfit=0; //Default Take Profit In Points (0=No Take Profit) -input int MinTakeProfit=0; //Minimum Allowed Take Profit In Points -input int MaxTakeProfit=5000; //Maximum Allowed Take Profit In Points -input double TakeProfitPercent=1.0; //Take Profit percent on risk base -input double Breakevent=1.0; //Minimum Profit to breakeven -input bool ProfitRun=true; -input bool ActiveMartingale=false; - -input string Comment_3="=========="; //Trailing Stop Settings -input bool UseTrailingStop=false; //Use Trailing Stop - -input string Comment_4="=========="; //Additional Settings -input int MagicNumber=0; //Magic Number For The Orders Opened By This EA -input string OrderNote=""; //Comment For The Orders Opened By This EA -input int Slippage=5; //Slippage in points -input double MaxSpread=10.0; //Maximum Allowed Spread To Trade In Points - -input string Comment_5="==========="; //Zigzag indicator setting -input int Depth=5; -input int Deviation=5; -input int Backstep=3; -input int GapPoint=100; //Minimum gap between peaks -input int Sensitivity=2; //Minimum peak at same level -input int LookBack=50; //Maximum peak to consider - -input int NumberOfCandles=3; - -//-GLOBAL VARIABLES-// -//The variables included in this section are global, hence they can be used in any part of the code -string Symb=Symbol(), server_time; - -long current_chart_id = ChartID(); - -bool IsPreChecksOk=false; //Indicates if the pre checks are satisfied -bool IsNewCandle=false; //Indicates if this is a new candle formed -bool IsSpreadOK=false; //Indicates if the spread is low enough to trade -bool IsOperatingHours=false; //Indicates if it is possible to trade at the current time (server time) -bool IsTradedThisBar=false; //Indicates if an order was already executed in the current candle -bool In_Trade = true; //Indicates if trade range has been formed -bool CanBuy = true; -bool CanSell = true; -bool ClosePosition = false; -bool FollowProfit = false; -bool UpTrendingMarket = false; -bool DownTrendingMarket = false; - -double TickValue=0; //Value of a tick in account currency at 1 lot -double LotSize=0; //Lot size for the position -double Tick_Size = SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_SIZE); //Tick size -double High[]; -double Low[]; -double PositionProfit; - -//Indicators - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -long Spread = SymbolInfoInteger(Symb,SYMBOL_SPREAD) / 100; //Check the impact. It's originally a double -int OrderOpRetry=10; //Number of attempts to retry the order submission -int TotalOpenOrders=0; //Number of total open orders -int TotalOpenBuy=0; //Number of total open buy orders -int TotalOpenSell=0; //Number of total open sell orders -int StopLossBy=SL_BY_POINTS; //How the stop loss is passed for the lot size calculation -double lotMultiplier =1; //Adust lot size according to loosing trades -int candleCounter =0; -double firstCandleOpen =0; -double lastCandleClose=0; -double ProfitRunTargetPercent=10.0; - -datetime LastBarTraded; - -MqlDateTime dt; -MqlTick last_tick; - -ENUM_SIGNAL_ENTRY SignalEntry=SIGNAL_ENTRY_NEUTRAL; //Entry signal variable -ENUM_SIGNAL_EXIT SignalExit=SIGNAL_EXIT_NEUTRAL; -ENUM_CANDLE_TYPE candleType=NEUTRAL_CANDLE; -ENUM_PRICE_MOMENTUM priceMomentum=NEUTRAL; -//+------------------------------------------------------------------+ diff --git a/Include/A_PositionsManager.mqh b/Include/A_PositionsManager.mqh deleted file mode 100644 index ac8a2b1..0000000 --- a/Include/A_PositionsManager.mqh +++ /dev/null @@ -1,123 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_PositionsManager.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -CTrade trade; - -//Scan all positions to find the ones submitted by the EA -//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails -bool ScanPositions() - { - -//Scan all the orders, retrieving some of the details - TotalOpenOrders = 0; - TotalOpenBuy = 0; - TotalOpenSell = 0; - for(int i=0; iLastBarTraded || LastBarTraded==0) - LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME); - } - Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell); - return true; - } - -// We declare a function CloseOpenPositions of type int and we want to return -// the number of positions that are closed. -void CloseOpenPositions() - { - - int TotalClose=0; // We want to count how many orders have been closed. - int c_slippage = Slippage; - Print("Close position status ", ClosePosition); -// Normalization of the slippage. - if(_Digits==3 || _Digits==5) - { - c_slippage=c_slippage*10; - } - -// We scan all the orders backwards. -// This is required as if we start from the first order, we will have problems with the counters and the loop. - for(int i=PositionsTotal()-1; i>=0; i--) - { - - ulong ticket = PositionGetTicket(i); - - Print("Position profit is ", PositionGetDouble(POSITION_PROFIT)); - PositionProfit = PositionGetDouble(POSITION_PROFIT); - /*if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - - if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - }*/ - - if(ClosePosition) - { - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - ClosePosition = false; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - // We can use a delay if the execution is too fast. - // Sleep() will wait X milliseconds before proceeding with the code. - // Sleep(300); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/A_TradeManager.mqh b/Include/A_TradeManager.mqh deleted file mode 100644 index fa829a9..0000000 --- a/Include/A_TradeManager.mqh +++ /dev/null @@ -1,23 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_TradeManager.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -void ProfitRunner() - { - if(ProfitRun) - { - if(iClose(Symb, _Period, 1) < iClose(Symb, _Period, 2) && TotalOpenBuy > 0) - { - ClosePosition = true; - } - if(iClose(Symb, _Period, 1) > iClose(Symb, _Period, 2) && TotalOpenSell > 0) - { - ClosePosition = true; - } - } - Print("Looking to close this position ", ClosePosition); - } \ No newline at end of file diff --git a/Include/A_TradingHour.mqh b/Include/A_TradingHour.mqh deleted file mode 100644 index 72d352a..0000000 --- a/Include/A_TradingHour.mqh +++ /dev/null @@ -1,27 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_TradingHour.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -//+------------------------------------------------------------------+ -//| defines | -//+------------------------------------------------------------------+ -// #define MacrosHello "Hello, world!" -// #define MacrosYear 2010 -//+------------------------------------------------------------------+ -//| DLL imports | -//+------------------------------------------------------------------+ -// #import "user32.dll" -// int SendMessageA(int hWnd,int Msg,int wParam,int lParam); -// #import "my_expert.dll" -// int ExpertRecalculate(int wParam,int lParam); -// #import -//+------------------------------------------------------------------+ -//| EX5 imports | -//+------------------------------------------------------------------+ -// #import "stdlib.ex5" -// string ErrorDescription(int error_code); -// #import -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/Array.mqh b/Include/Arrays/Array.mqh deleted file mode 100644 index b78f528..0000000 --- a/Include/Arrays/Array.mqh +++ /dev/null @@ -1,182 +0,0 @@ -//+------------------------------------------------------------------+ -//| Array.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CArray | -//| Purpose: Base class of dynamic arrays. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CArray : public CObject - { -protected: - int m_step_resize; // increment size of the array - int m_data_total; // number of elements - int m_data_max; // maximmum size of the array without memory reallocation - int m_sort_mode; // mode of array sorting - -public: - CArray(void); - ~CArray(void); - //--- methods of access to protected data - int Step(void) const { return(m_step_resize); } - bool Step(const int step); - int Total(void) const { return(m_data_total); } - int Available(void) const { return(m_data_max-m_data_total); } - int Max(void) const { return(m_data_max); } - bool IsSorted(const int mode=0) const { return(m_sort_mode==mode); } - int SortMode(void) const { return(m_sort_mode); } - //--- cleaning method - void Clear(void) { m_data_total=0; } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- sorting method - void Sort(const int mode=0); - -protected: - virtual void QuickSort(int beg,int end,const int mode=0) { m_sort_mode=-1; } - //--- templates for methods of searching for minimum and maximum - template - int Minimum(const T &data[],const int start,const int count) const; - template - int Maximum(const T &data[],const int start,const int count) const; - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CArray::CArray(void) : m_step_resize(16), - m_data_total(0), - m_data_max(0), - m_sort_mode(-1) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CArray::~CArray(void) - { - } -//+------------------------------------------------------------------+ -//| Method Set for variable m_step_resize | -//+------------------------------------------------------------------+ -bool CArray::Step(const int step) - { -//--- check - if(step>0) - { - m_step_resize=step; - return(true); - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Sorting an array in ascending order | -//+------------------------------------------------------------------+ -void CArray::Sort(const int mode) - { -//--- check - if(IsSorted(mode)) - return; - m_sort_mode=mode; - if(m_data_total<=1) - return; -//--- sort - QuickSort(0,m_data_total-1,mode); - } -//+------------------------------------------------------------------+ -//| Writing header of array to file | -//+------------------------------------------------------------------+ -bool CArray::Save(const int file_handle) - { -//--- check handle - if(file_handle!=INVALID_HANDLE) - { - //--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)==sizeof(long)) - { - //--- write array type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)==INT_VALUE) - return(true); - } - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Reading header of array from file | -//+------------------------------------------------------------------+ -bool CArray::Load(const int file_handle) - { -//--- check handle - if(file_handle!=INVALID_HANDLE) - { - //--- read and check start marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)==-1) - { - //--- read and check array type - if(FileReadInteger(file_handle,INT_VALUE)==Type()) - return(true); - } - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Find minimum of array | -//+------------------------------------------------------------------+ -template -int CArray::Minimum(const T &data[],const int start,const int count) const - { - int real_count; -//--- check for empty array - if(m_data_total<1) - { - SetUserError(ERR_USER_ARRAY_IS_EMPTY); - return(-1); - } - //--- check for start is out of range - if(start<0 || start>=m_data_total) - { - SetUserError(ERR_USER_ITEM_NOT_FOUND); - return(-1); - } -//--- compute count of elements - real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count; -#ifdef __MQL5__ - return(ArrayMinimum(data,start,real_count)); -#else - return(ArrayMinimum(data,real_count,start)); -#endif - } -//+------------------------------------------------------------------+ -//| Find maximum of array | -//+------------------------------------------------------------------+ -template -int CArray::Maximum(const T &data[],const int start,const int count) const - { - int real_count; -//--- check for empty array - if(m_data_total<1) - { - SetUserError(ERR_USER_ARRAY_IS_EMPTY); - return(-1); - } - //--- check for start is out of range - if(start<0 || start>=m_data_total) - { - SetUserError(ERR_USER_ITEM_NOT_FOUND); - return(-1); - } -//--- compute count of elements - real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count; -#ifdef __MQL5__ - return(ArrayMaximum(data,start,real_count)); -#else - return(ArrayMaximum(data,real_count,start)); -#endif - } -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/ArrayChar.mqh b/Include/Arrays/ArrayChar.mqh deleted file mode 100644 index ea822b0..0000000 --- a/Include/Arrays/ArrayChar.mqh +++ /dev/null @@ -1,771 +0,0 @@ -//+------------------------------------------------------------------+ -//| ArrayChar.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Array.mqh" -//+------------------------------------------------------------------+ -//| Class CArrayChar. | -//| Purpose: Class of dynamic array of variables | -//| of char or uchar type. | -//| Derives from class CArray. | -//+------------------------------------------------------------------+ -class CArrayChar : public CArray - { -protected: - char m_data[]; // data array - -public: - CArrayChar(void); - ~CArrayChar(void); - //--- method of identifying the object - virtual int Type(void) const { return(TYPE_CHAR); } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- methods of managing dynamic memory - bool Reserve(const int size); - bool Resize(const int size); - bool Shutdown(void); - //--- methods of filling the array - bool Add(const char element); - bool AddArray(const char &src[]); - bool AddArray(const CArrayChar *src); - bool Insert(const char element,const int pos); - bool InsertArray(const char &src[],const int pos); - bool InsertArray(const CArrayChar *src,const int pos); - bool AssignArray(const char &src[]); - bool AssignArray(const CArrayChar *src); - //--- method of access to the array - char At(const int index) const; - char operator[](const int index) const { return(At(index)); } - //--- methods of searching for minimum and maximum - int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); } - int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); } - //--- methods of changing - bool Update(const int index,const char element); - bool Shift(const int index,const int shift); - //--- methods of deleting - bool Delete(const int index); - bool DeleteRange(int from,int to); - //--- methods for comparing arrays - bool CompareArray(const char &array[]) const; - bool CompareArray(const CArrayChar *array) const; - //--- methods for working with the sorted array - bool InsertSort(const char element); - int Search(const char element) const; - int SearchGreat(const char element) const; - int SearchLess(const char element) const; - int SearchGreatOrEqual(const char element) const; - int SearchLessOrEqual(const char element) const; - int SearchFirst(const char element) const; - int SearchLast(const char element) const; - int SearchLinear(const char element) const; - -protected: - virtual void QuickSort(int beg,int end,const int mode=0); - int QuickSearch(const char element) const; - int MemMove(const int dest,const int src,int count); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CArrayChar::CArrayChar(void) - { -//--- initialize protected data - m_data_max=ArraySize(m_data); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CArrayChar::~CArrayChar(void) - { - if(m_data_max!=0) - Shutdown(); - } -//+------------------------------------------------------------------+ -//| Moving the memory within a single array | -//+------------------------------------------------------------------+ -int CArrayChar::MemMove(const int dest,const int src,int count) - { - int i; -//--- check parameters - if(dest<0 || src<0 || count<0) - return(-1); -//--- check count - if(src+count>m_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayChar::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayChar::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayChar::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayChar::Add(const char element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayChar::AddArray(const char &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(CHAR_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayChar::Update(const int index,const char element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayChar::Shift(const int index,const int shift) - { - char tmp_char; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_char=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_char; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayChar::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayChar::CompareArray(const char &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_char=m_data[(beg+end)>>1]; - while(ip_char) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_char=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_char; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLinear(const char element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_char=m_data[m]; - if(t_char==element) - break; - if(t_char>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::Search(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchGreat(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLess(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchGreatOrEqual(const char element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLessOrEqual(const char element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchFirst(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLast(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayChar::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayDouble::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayDouble::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayDouble::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayDouble::Add(const double element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayDouble::AddArray(const double &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(DBL_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayDouble::Update(const int index,const double element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayDouble::Shift(const int index,const int shift) - { - double tmp_double; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_double=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_double; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayDouble::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayDouble::CompareArray(const double &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_double=m_data[(beg+end)>>1]; - while(ip_double) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_double=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_double; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLinear(const double element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_double=m_data[m]; - //--- compare with delta - if(MathAbs(t_double-element)<=m_delta) - break; - if(t_double>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::Search(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - if(MathAbs(m_data[pos]-element)<=m_delta) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchGreat(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]<=element+m_delta) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLess(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]>=element-m_delta) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchGreatOrEqual(const double element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLessOrEqual(const double element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchFirst(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLast(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayDouble::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayFloat::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayFloat::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayFloat::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayFloat::Add(const float element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayFloat::AddArray(const float &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(FLT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayFloat::Update(const int index,const float element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayFloat::Shift(const int index,const int shift) - { - float tmp_float; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_float=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_float; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayFloat::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayFloat::CompareArray(const float &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_float=m_data[(beg+end)>>1]; - while(ip_float) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_float=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_float; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLinear(const float element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_float=m_data[m]; - //--- compare with delta - if(MathAbs(t_float-element)<=m_delta) - break; - if(t_float>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::Search(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - if(MathAbs(m_data[pos]-element)<=m_delta) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchGreat(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]<=element+m_delta) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLess(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]>=element-m_delta) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchGreatOrEqual(const float element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLessOrEqual(const float element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchFirst(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLast(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayFloat::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayInt::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayInt::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayInt::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayInt::Add(const int element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayInt::AddArray(const int &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(INT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayInt::Update(const int index,const int element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayInt::Shift(const int index,const int shift) - { - int tmp_int; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_int=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_int; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayInt::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayInt::CompareArray(const int &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_int=m_data[(beg+end)>>1]; - while(ip_int) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_int=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_int; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLinear(const int element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_int=m_data[m]; - if(t_int==element) - break; - if(t_int>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::Search(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchGreat(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLess(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchGreatOrEqual(const int element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLessOrEqual(const int element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchFirst(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLast(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayInt::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayLong::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayLong::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayLong::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayLong::Add(const long element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayLong::AddArray(const long &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(LONG_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayLong::Update(const int index,const long element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayLong::Shift(const int index,const int shift) - { - long tmp_long; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_long=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_long; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayLong::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayLong::CompareArray(const long &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_long=m_data[(beg+end)>>1]; - while(ip_long) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_long=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_long; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLinear(const long element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_long=m_data[m]; - if(t_long==element) - break; - if(t_long>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::Search(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchGreat(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLess(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchGreatOrEqual(const long element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLessOrEqual(const long element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchFirst(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLast(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayLong::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - { - //--- "physical" removal of the object (if necessary and possible) - if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC) - delete m_data[dest+i]; - //--- - m_data[dest+i]=m_data[src+i]; - m_data[src+i]=NULL; - } - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayObj::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayObj::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_total>size) - { - //--- "physical" removal of the object (if necessary and possible) - if(m_free_mode) - for(int i=size;i=m_data_total) - return(NULL); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayObj::Update(const int index,CObject *element) - { -//--- check - if(index<0 || !CheckPointer(element) || index>=m_data_total) - return(false); -//--- "physical" removal of the object (if necessary and possible) - if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) - delete m_data[index]; -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayObj::Shift(const int index,const int shift) - { - CObject *tmp_node; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_node=m_data[index]; - m_data[index]=NULL; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_node; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayObj::Delete(const int index) - { -//--- check - if(index>=m_data_total) - return(false); -//--- delete - if(index=0 && MemMove(index,index+1,m_data_total-index-1)<0) - return(false); - } - else - if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) - delete m_data[index]; - m_data_total--; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Detach element from the specified position | -//+------------------------------------------------------------------+ -CObject *CArrayObj::Detach(const int index) - { - CObject *result; -//--- check - if(index>=m_data_total) - return(NULL); -//--- detach - result=m_data[index]; -//--- reset the array element, so as not remove the method MemMove - m_data[index]=NULL; - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - for(int i=to-from+1;i>0;i--,m_data_total--) - if(m_free_mode && CheckPointer(m_data[m_data_total-1])==POINTER_DYNAMIC) - delete m_data[m_data_total-1]; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Clearing of array without the release of memory | -//+------------------------------------------------------------------+ -void CArrayObj::Clear(void) - { -//--- "physical" removal of the object (if necessary and possible) - if(m_free_mode) - { - for(int i=0;i>1" is quick division by 2 - p_node=m_data[(beg+end)>>1]; - while(i0) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_node=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_node; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(beg0) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=mode; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Quick search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::QuickSearch(const CObject *element) const - { - int i,j,m=-1; - CObject *t_node; -//--- search - i=0; - j=m_data_total-1; - while(j>=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m==m_data_total-1) - break; - t_node=m_data[m]; - if(t_node.Compare(element,m_sort_mode)==0) - break; - if(t_node.Compare(element,m_sort_mode)>0) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::Search(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchGreat(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos].Compare(element,m_sort_mode)<=0) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLess(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos].Compare(element,m_sort_mode)>=0) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchGreatOrEqual(const CObject *element) const - { -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLessOrEqual(const CObject *element) const - { -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos].Compare(element,m_sort_mode)<=0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchFirst(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - { - while(m_data[pos].Compare(element,m_sort_mode)==0) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLast(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - { - while(m_data[pos].Compare(element,m_sort_mode)==0) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayObj::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayShort::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayShort::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayShort::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayShort::Add(const short element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayShort::AddArray(const short &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(SHORT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayShort::Update(const int index,const short element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayShort::Shift(const int index,const int shift) - { - short tmp_short; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_short=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_short; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayShort::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayShort::CompareArray(const short &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_short=m_data[(beg+end)>>1]; - while(ip_short) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_short=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_short; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLinear(const short element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_short=m_data[m]; - if(t_short==element) - break; - if(t_short>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::Search(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchGreat(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLess(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchGreatOrEqual(const short element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLessOrEqual(const short element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchFirst(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLast(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayShort::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayString::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayString::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayString::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayString::Add(const string element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayString::AddArray(const string &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(""); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayString::Update(const int index,const string element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayString::Shift(const int index,const int shift) - { - string tmp_string; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_string=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_string; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayString::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayString::CompareArray(const string &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_string=m_data[(beg+end)>>1]; - while(ip_string) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_string=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_string; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLinear(const string element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_string=m_data[m]; - if(t_string==element) - break; - if(t_string>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::Search(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchGreat(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLess(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchGreatOrEqual(const string element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLessOrEqual(const string element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchFirst(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLast(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayString::Save(const int file_handle) - { - int i=0,len; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;i -//+------------------------------------------------------------------+ -//| Class CList. | -//| Purpose: Provides the possibility of working with the list of | -//| CObject instances and its dervivatives | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CList : public CObject - { -protected: - CObject *m_first_node; // pointer to the first element of the list - CObject *m_last_node; // pointer to the last element of the list - CObject *m_curr_node; // pointer to the current element of the list - int m_curr_idx; // index of the current list item - int m_data_total; // number of elements - bool m_free_mode; // flag of the necessity of "physical" deletion of object - bool m_data_sort; // flag if the list is sorted or not - int m_sort_mode; // mode of sorting of array - -public: - CList(void); - ~CList(void); - //--- methods of access to protected data - bool FreeMode(void) const { return(m_free_mode); } - void FreeMode(bool mode) { m_free_mode=mode; } - int Total(void) const { return(m_data_total); } - bool IsSorted(void) const { return(m_data_sort); } - int SortMode(void) const { return(m_sort_mode); } - //--- method of identifying the object - virtual int Type(void) const { return(0x7779); } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- method of creating an element of the list - virtual CObject *CreateElement(void) { return(NULL); } - //--- methods of filling the list - int Add(CObject *new_node); - int Insert(CObject *new_node,int index); - //--- methods for navigating - int IndexOf(CObject *node); - CObject *GetNodeAtIndex(int index); - CObject *GetFirstNode(void); - CObject *GetPrevNode(void); - CObject *GetCurrentNode(void); - CObject *GetNextNode(void); - CObject *GetLastNode(void); - //--- methods for deleting - CObject *DetachCurrent(void); - bool DeleteCurrent(void); - bool Delete(int index); - void Clear(void); - //--- method for comparing lists - bool CompareList(CList *List); - //--- methods for changing - void Sort(int mode); - bool MoveToIndex(int index); - bool Exchange(CObject *node1,CObject *node2); - //--- method for searching - CObject *Search(CObject *element); -protected: - void QuickSort(int beg,int end,int mode); - CObject *QuickSearch(CObject *element); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CList::CList(void) : m_first_node(NULL), - m_last_node(NULL), - m_curr_node(NULL), - m_curr_idx(-1), - m_data_total(0), - m_free_mode(true), - m_data_sort(false), - m_sort_mode(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CList::~CList(void) - { - Clear(); - } -//+------------------------------------------------------------------+ -//| Method QuickSort | -//+------------------------------------------------------------------+ -void CList::QuickSort(int beg,int end,int mode) - { - int i,j,k; - CObject *i_ptr,*j_ptr,*k_ptr; -//--- - i_ptr=GetNodeAtIndex(i=beg); - j_ptr=GetNodeAtIndex(j=end); - while(i>1" is quick division by 2 - k_ptr=GetNodeAtIndex(k=(beg+end)>>1); - while(i0) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - j_ptr=j_ptr.Prev(); - } - if(i<=j) - { - Exchange(i_ptr,j_ptr); - i++; - i_ptr=GetNodeAtIndex(i); - //--- control the output of the array bounds - if(j==0) - break; - else - { - j--; - j_ptr=GetNodeAtIndex(j); - } - } - } - if(begm_data_total || index<0) - return(-1); -//--- adjust - if(index==-1) - { - if(m_curr_node==NULL) - return(Add(new_node)); - } - else - { - if(GetNodeAtIndex(index)==NULL) - return(Add(new_node)); - } -//--- no need to check m_curr_node - tmp_node=m_curr_node.Prev(); - new_node.Prev(tmp_node); - if(tmp_node!=NULL) - tmp_node.Next(new_node); - else - m_first_node=new_node; - new_node.Next(m_curr_node); - m_curr_node.Prev(new_node); - m_data_total++; - m_data_sort=false; - m_curr_node=new_node; -//--- result - return(index); - } -//+------------------------------------------------------------------+ -//| Get a pointer to the position of element in the list | -//+------------------------------------------------------------------+ -CObject *CList::GetNodeAtIndex(int index) - { - int i; - bool revers; - CObject *result; -//--- check - if(index>=m_data_total) - return(NULL); - if(index==m_curr_idx) - return(m_curr_node); -//--- optimize bust list - if(indexindex;i--) - { - result=result.Prev(); - if(result==NULL) - return(NULL); - } - } - else - { - //--- search from left to right - for(;i=m_data_total || !CheckPointer(m_curr_node)) - return(false); -//--- tune - if(m_curr_idx==index) - return(true); - if(m_curr_idx=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_node=GetNodeAtIndex(m); - if(t_node.Compare(element,m_sort_mode)==0) - break; - if(t_node.Compare(element,m_sort_mode)>0) - j=m-1; - else - i=m+1; - t_node=NULL; - } -//--- result - return(t_node); - } -//+------------------------------------------------------------------+ -//| Search position of an element in a sorted list | -//+------------------------------------------------------------------+ -CObject *CList::Search(CObject *element) - { - CObject *result; -//--- check - if(!CheckPointer(element) || !m_data_sort) - return(NULL); -//--- search - result=QuickSearch(element); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Writing list to file | -//+------------------------------------------------------------------+ -bool CList::Save(const int file_handle) - { - CObject *node; - bool result=true; -//--- check - if(!CheckPointer(m_curr_node) || file_handle==INVALID_HANDLE) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write list size - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- sequential scannning of elements in the list using the call of method Save() - node=m_first_node; - while(node!=NULL) - { - result&=node.Save(file_handle); - node=node.Next(); - } -//--- successful - return(result); - } -//+------------------------------------------------------------------+ -//| Reading list from file | -//+------------------------------------------------------------------+ -bool CList::Load(const int file_handle) - { - uint i,num; - CObject *node; - bool result=true; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- read and checking begin marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)!=-1) - return(false); -//--- read and checking type - if(FileReadInteger(file_handle,INT_VALUE)!=Type()) - return(false); -//--- read list size - num=FileReadInteger(file_handle,INT_VALUE); -//--- sequential creation of list items using the call of method Load() - Clear(); - for(i=0;i0) - p_node.Left(new_node); - else - p_node.Right(new_node); - new_node.Parent(p_node); - Balance(p_node); - } - else - m_root_node=new_node; -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Method of removing a node from the tree | -//+------------------------------------------------------------------+ -bool CTree::Delete(CTreeNode *node) - { -//--- check - if(!CheckPointer(node)) - return(false); -//--- delete - if(Detach(node) && CheckPointer(node)==POINTER_DYNAMIC) - delete node; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Method of detaching node from the tree | -//+------------------------------------------------------------------+ -bool CTree::Detach(CTreeNode *node) - { - CTreeNode *curr_node,*tmp_node; - CTreeNode *nodeA,*nodeB; -//--- check - curr_node=node; - if(!CheckPointer(curr_node)) - return(false); -//--- detach - if(curr_node.BalanceL()>curr_node.BalanceR()) - { - nodeA=curr_node.Left(); - while(nodeA.Right()!=NULL) - nodeA=nodeA.Right(); - nodeB=nodeA.Parent(); - if(nodeB!=curr_node) - { - nodeB.Right(nodeA.Left()); - tmp_node=nodeB.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - tmp_node=curr_node.Left(); - nodeA.Left(tmp_node); - tmp_node.Parent(nodeA); - } - //--- left link of curr_node is already installed as it should be - curr_node.Left(NULL); - //--- transferring the right link of curr_node to nodeA - nodeA.Right(curr_node.Right()); - tmp_node=curr_node.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - curr_node.Right(NULL); - //--- transferring the root link of curr_node to nodeA - tmp_node=curr_node.Parent(); - nodeA.Parent(tmp_node); - if(tmp_node!=NULL) - { - if(tmp_node.Left()==curr_node) - tmp_node.Left(nodeA); - else - tmp_node.Right(nodeA); - } - else - { - curr_node.Parent(NULL); - m_root_node=nodeA; - tmp_node=nodeA; - } - Balance(tmp_node); - } - else - { - if(curr_node.BalanceR()>0) - { - nodeA=curr_node.Right(); - while(nodeA.Left()!=NULL) - nodeA=nodeA.Left(); - nodeB=nodeA.Parent(); - if(nodeB!=curr_node) - { - nodeB.Left(nodeA.Right()); - tmp_node=nodeB.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - tmp_node=curr_node.Right(); - nodeA.Right(tmp_node); - tmp_node.Parent(nodeA); - } - //--- right link of curr_node is already installed as it should be - curr_node.Right(NULL); - //--- transferring the left link of curr_node to nodeA - nodeA.Left(curr_node.Left()); - tmp_node=curr_node.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - curr_node.Left(NULL); - //--- transferring the root link of curr_node to nodeA - tmp_node=curr_node.Parent(); - nodeA.Parent(tmp_node); - if(tmp_node!=NULL) - { - if(tmp_node.Left()==curr_node) - tmp_node.Left(nodeA); - else - tmp_node.Right(nodeA); - } - else - { - curr_node.Parent(NULL); - m_root_node=nodeA; - tmp_node=nodeA; - } - Balance(tmp_node); - } - else - { - //--- node list - if(curr_node.Parent()==NULL) - m_root_node=NULL; - else - { - tmp_node=curr_node.Parent(); - if(tmp_node.Left()==curr_node) - tmp_node.Left(NULL); - else - tmp_node.Right(NULL); - curr_node.Parent(NULL); - } - Balance(curr_node.Parent()); - } - } -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Method of cleaning the tree | -//+------------------------------------------------------------------+ -void CTree::Clear(void) - { - if(CheckPointer(m_root_node)==POINTER_DYNAMIC) - delete m_root_node; - m_root_node=NULL; - } -//+------------------------------------------------------------------+ -//| Method of searching for a node in the tree | -//+------------------------------------------------------------------+ -CTreeNode *CTree::Find(const CTreeNode *node) - { - CTreeNode *result=m_root_node; -//--- find - while(result!=NULL && result.Compare(node)!=0) - result=result.GetNext(node); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Method of balancing the tree | -//+------------------------------------------------------------------+ -void CTree::Balance(CTreeNode *node) - { - CTreeNode *nodeA,*nodeB,*nodeC,*curr_node,*tmp_node; -//--- - curr_node=node; - while(curr_node!=NULL) - { - curr_node.RefreshBalance(); - if(MathAbs(curr_node.BalanceL()-curr_node.BalanceR())<=1) - curr_node=curr_node.Parent(); - else - { - if(curr_node.BalanceR()>curr_node.BalanceL()) - { - //--- rotation to the right - tmp_node=curr_node.Right(); - if(tmp_node.BalanceL()>tmp_node.BalanceR()) - { - //--- great rotation to the right - nodeA=curr_node; - nodeB=nodeA.Right(); - nodeC=nodeB.Left(); - nodeC.Parent(nodeA.Parent()); - tmp_node=nodeC.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeC); - else - tmp_node.Left(nodeC); - } - else - m_root_node=nodeC; - nodeA.Parent(nodeC); - nodeB.Parent(nodeC); - nodeA.Right(nodeC.Left()); - tmp_node=nodeA.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeC.Left(nodeA); - nodeB.Left(nodeC.Right()); - tmp_node=nodeB.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - nodeC.Right(nodeB); - if(m_root_node==nodeA) - m_root_node=nodeC; - curr_node=nodeC.Parent(); - } - else - { - //--- slight rotation to the right - nodeA=curr_node; - nodeB=nodeA.Right(); - nodeB.Parent(nodeA.Parent()); - tmp_node=nodeB.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeB); - else - tmp_node.Left(nodeB); - } - else - m_root_node=nodeB; - nodeA.Parent(nodeB); - nodeA.Right(nodeB.Left()); - tmp_node=nodeA.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeB.Left(nodeA); - if(m_root_node==nodeA) - m_root_node=nodeB; - curr_node=nodeB.Parent(); - } - } - else - { - //--- rotation to the left - tmp_node=curr_node.Left(); - if(tmp_node.BalanceR()>tmp_node.BalanceL()) - { - //--- great rotation to the left - nodeA=curr_node; - nodeB=nodeA.Left(); - nodeC=nodeB.Right(); - nodeC.Parent(nodeA.Parent()); - tmp_node=nodeC.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeC); - else - tmp_node.Left(nodeC); - } - else - m_root_node=nodeC; - nodeA.Parent(nodeC); - nodeB.Parent(nodeC); - nodeA.Left(nodeC.Right()); - tmp_node=nodeA.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeC.Right(nodeA); - nodeB.Right(nodeC.Left()); - tmp_node=nodeB.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - nodeC.Left(nodeB); - if(m_root_node==nodeA) - m_root_node=nodeC; - curr_node=nodeC.Parent(); - } - else - { - //--- small rotation to the left - nodeA=curr_node; - nodeB=nodeA.Left(); - nodeB.Parent(nodeA.Parent()); - tmp_node=nodeB.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeB); - else - tmp_node.Left(nodeB); - } - else - m_root_node=nodeB; - nodeA.Parent(nodeB); - nodeA.Left(nodeB.Right()); - tmp_node=nodeA.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeB.Right(nodeA); - if(m_root_node==nodeA) - m_root_node=nodeB; - curr_node=nodeB.Parent(); - } - } - } - } - } -//+------------------------------------------------------------------+ -//| Writing tree to file | -//+------------------------------------------------------------------+ -bool CTree::Save(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); - if(m_root_node==NULL) - return(true); -//--- result - return(m_root_node.SaveNode(file_handle)); - } -//+------------------------------------------------------------------+ -//| Reading tree from file | -//+------------------------------------------------------------------+ -bool CTree::Load(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- create root node only - Clear(); - Insert(CreateElement()); -//--- result - return(m_root_node.LoadNode(file_handle,m_root_node)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/TreeNode.mqh b/Include/Arrays/TreeNode.mqh deleted file mode 100644 index fde1633..0000000 --- a/Include/Arrays/TreeNode.mqh +++ /dev/null @@ -1,174 +0,0 @@ -//+------------------------------------------------------------------+ -//| TreeNode.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CTreeNode. | -//| Purpose: Base class of node of binary tree CTree. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CTreeNode : public CObject - { -private: - CTreeNode *m_p_node; // link to node up - CTreeNode *m_l_node; // link to node left - CTreeNode *m_r_node; // link to node right - //--- variables - int m_balance; // balance of node - int m_l_balance; // balance of the left branch - int m_r_balance; // balance of the right branch - -public: - CTreeNode(void); - ~CTreeNode(void); - //--- methods of access to protected data - CTreeNode* Parent(void) const { return(m_p_node); } - void Parent(CTreeNode *node) { m_p_node=node; } - CTreeNode* Left(void) const { return(m_l_node); } - void Left(CTreeNode *node) { m_l_node=node; } - CTreeNode* Right(void) const { return(m_r_node); } - void Right(CTreeNode *node) { m_r_node=node; } - int Balance(void) const { return(m_balance); } - int BalanceL(void) const { return(m_l_balance); } - int BalanceR(void) const { return(m_r_balance); } - //--- method of identifying the object - virtual int Type(void) const { return(0x8888); } - //--- methods for controlling - int RefreshBalance(void); - CTreeNode *GetNext(const CTreeNode *node); - //--- methods for working with files - bool SaveNode(const int file_handle); - bool LoadNode(const int file_handle,CTreeNode *main); - -protected: - //--- method for creating an instance of class - virtual CTreeNode *CreateSample(void) { return(NULL); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CTreeNode::CTreeNode(void) : m_p_node(NULL), - m_l_node(NULL), - m_r_node(NULL), - m_balance(0), - m_l_balance(0), - m_r_balance(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTreeNode::~CTreeNode(void) - { -//--- delete nodes of the next level - if(m_l_node!=NULL) - delete m_l_node; - if(m_r_node!=NULL) - delete m_r_node; - } -//+------------------------------------------------------------------+ -//| Calculating the balance of the node | -//+------------------------------------------------------------------+ -int CTreeNode::RefreshBalance(void) - { -//--- calculate the balance of the left branch - if(m_l_node==NULL) - m_l_balance=0; - else - m_l_balance=m_l_node.RefreshBalance(); -//--- calculate the balance of the right branch - if(m_r_node==NULL) - m_r_balance=0; - else - m_r_balance=m_r_node.RefreshBalance(); -//--- calculate the balance of the node - if(m_r_balance>m_l_balance) - m_balance=m_r_balance+1; - else - m_balance=m_l_balance+1; -//--- result - return(m_balance); - } -//+------------------------------------------------------------------+ -//| Selecting next node | -//+------------------------------------------------------------------+ -CTreeNode *CTreeNode::GetNext(const CTreeNode *node) - { - if(Compare(node)>0) - return(m_l_node); -//--- result - return(m_r_node); - } -//+------------------------------------------------------------------+ -//| Writing node data to file | -//+------------------------------------------------------------------+ -bool CTreeNode::SaveNode(const int file_handle) - { - bool result=true; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- write left node (if it is available) - if(m_l_node!=NULL) - { - FileWriteInteger(file_handle,'L',SHORT_VALUE); - result&=m_l_node.SaveNode(file_handle); - } - else - FileWriteInteger(file_handle,'X',SHORT_VALUE); -//--- write data of current node - result&=Save(file_handle); -//--- write right node (if it is available) - if(m_r_node!=NULL) - { - FileWriteInteger(file_handle,'R',SHORT_VALUE); - result&=m_r_node.SaveNode(file_handle); - } - else - FileWriteInteger(file_handle,'X',SHORT_VALUE); -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Reading node data from file | -//+------------------------------------------------------------------+ -bool CTreeNode::LoadNode(const int file_handle,CTreeNode *main) - { - bool result=true; - short s_val; - CTreeNode *node; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- read directions - s_val=(short)FileReadInteger(file_handle,SHORT_VALUE); - if(s_val=='L') - { - //--- read left node (if there is data) - node=CreateSample(); - if(node==NULL) - return(false); - m_l_node=node; - node.Parent(main); - result&=node.LoadNode(file_handle,node); - } -//--- read data of current node - result&=Load(file_handle); -//--- read directions - s_val=(short)FileReadInteger(file_handle,SHORT_VALUE); - if(s_val=='R') - { - //--- read right node (if there is data) - node=CreateSample(); - if(node==NULL) - return(false); - m_r_node=node; - node.Parent(main); - result&=node.LoadNode(file_handle,node); - } -//--- result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Canvas.mqh b/Include/Canvas/Canvas.mqh deleted file mode 100644 index 75b7a34..0000000 --- a/Include/Canvas/Canvas.mqh +++ /dev/null @@ -1,4846 +0,0 @@ -//+------------------------------------------------------------------+ -//| Canvas.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -#define SIGN(i) ((i<0) ? -1 : 1) - -//+------------------------------------------------------------------+ -//| Macro to generate color | -//+------------------------------------------------------------------+ -#define XRGB(r,g,b) (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b)) -#define ARGB(a,r,g,b) ((uchar(a)<<24)|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b)) -#define TRGB(a,rgb) ((uchar(a)<<24)|(rgb)) -#define GETRGB(clr) ((clr)&0xFFFFFF) -#define GETRGBA(clr) uchar((clr)>>24) -#define GETRGBR(clr) uchar((clr)>>16) -#define GETRGBG(clr) uchar((clr)>>8) -#define GETRGBB(clr) uchar(clr) -#define COLOR2RGB(clr) (0xFF000000|(uchar(clr)<<16)|(uchar((clr)>>8)<<8)|uchar((clr)>>16)) -#define RGB2COLOR(rgb) ((uchar(rgb)<<16)|(uchar((rgb)>>8)<<8)|uchar((rgb)>>16)) - -//+------------------------------------------------------------------+ -//| Line end style (round, butt, square) | -//+------------------------------------------------------------------+ -enum ENUM_LINE_END - { - LINE_END_ROUND, - LINE_END_BUTT, - LINE_END_SQUARE, - }; - -//+------------------------------------------------------------------+ -//| Class CCanvas | -//| Usage: class for working with a dynamic resource | -//+------------------------------------------------------------------+ -class CCanvas - { -private: - uint m_style; // line style template - uint m_style_idx; // variable - current index of bit in line style template - static uint m_default_colors[9]; // default colors - -protected: - long m_chart_id; // chart ID - string m_objname; // object name - ENUM_OBJECT m_objtype; // object type - string m_rcname; // resource name - int m_width; // canvas width - int m_height; // canvas height - ENUM_COLOR_FORMAT m_format; // method of color processing - //--- for text - string m_fontname; // font name - int m_fontsize; // font size - uint m_fontflags; // font flags - uint m_fontangle; // angle of text tilt to the X axis in 0.1 degrees - //--- data - uint m_pixels[]; // array of pixels - -public: - CCanvas(void); - ~CCanvas(void); - //--- create/attach/destroy - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmap(const string name,const datetime time,const double price, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmap(const long chart_id,const int subwin,const string name, - const datetime time,const double price,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmapLabel(const string name,const int x,const int y, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmapLabel(const long chart_id,const int subwin,const string name, - const int x,const int y,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual bool Attach(const long chart_id,const string objname,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual bool Attach(const long chart_id,const string objname,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual void Destroy(void); - //--- properties - string ChartObjectName(void) const { return(m_objname); } - string ResourceName(void) const { return(m_rcname); } - int Width(void) const { return(m_width); } - int Height(void) const { return(m_height); } - //--- update object on screen - void Update(const bool redraw=true); - bool Resize(const int width,const int height); - //--- clear/fill color - void Erase(const uint clr=0); - //--- data access - uint PixelGet(const int x,const int y) const; - void PixelSet(const int x,const int y,const uint clr); - //--- draw primitives - void LineVertical(int x,int y1,int y2,const uint clr); - void LineHorizontal(int x1,int x2,int y,const uint clr); - void Line(int x1,int y1,int x2,int y2,const uint clr); - void Polyline(int &x[],int &y[],const uint clr); - void Polygon(int &x[],int &y[],const uint clr); - void Rectangle(int x1,int y1,int x2,int y2,const uint clr); - void Triangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr); - void Circle(int x,int y,int r,const uint clr); - void Ellipse(int x1,int y1,int x2,int y2,const uint clr); - void Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr); - void Arc(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr); - void Arc(int x,int y,int rx,int ry,double fi3,double fi4,int &x3,int &y3,int &x4,int &y4,const uint clr); - void Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr,const uint fill_clr); - void Pie(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr,const uint fill_clr); - //--- draw filled primitives - void FillRectangle(int x1,int y1,int x2,int y2,const uint clr); - void FillTriangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr); - void FillPolygon(int &x[],int &y[],const uint clr); - void FillCircle(int x,int y,int r,const uint clr); - void FillEllipse(int x1,int y1,int x2,int y2,const uint clr); - void Fill(int x,int y,const uint clr); - void Fill(int x,int y,const uint clr,const uint threshould); - //--- draw primitives with antialiasing - void PixelSetAA(const double x,const double y,const uint clr); - void LineAA(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style=UINT_MAX); - void PolylineAA(int &x[],int &y[],const uint clr,const uint style=UINT_MAX); - void PolygonAA(int &x[],int &y[],const uint clr,const uint style=UINT_MAX); - void TriangleAA(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3, - const uint clr,const uint style=UINT_MAX); - void CircleAA(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX); - void EllipseAA(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style=UINT_MAX); - //--- draw primitives with antialiasing by Wu's algorithm - void LineWu(int x1,int y1,int x2,int y2,const uint clr,const uint style=UINT_MAX); - void PolylineWu(const int &x[],const int &y[],const uint clr,const uint style=UINT_MAX); - void PolygonWu(const int &x[],const int &y[],const uint clr,const uint style=UINT_MAX); - void TriangleWu(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3,const uint clr,const uint style=UINT_MAX); - void CircleWu(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX); - void EllipseWu(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style=UINT_MAX); - //--- draw primitives with prefiltered antialiasing - void LineThickVertical(const int x,const int y1,const int y2,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void LineThickHorizontal(const int x1,const int x2,const int y,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void LineThick(const int x1,const int y1,const int x2,const int y2,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void PolylineThick(const int &x[],const int &y[],const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void PolygonThick(const int &x[],const int &y[],const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - //--- draw primitives smoothing polyline and polygon - void PolylineSmooth(const int &x[],const int &y[],const uint clr,const int size, - ENUM_LINE_STYLE style=STYLE_SOLID,ENUM_LINE_END end_style=LINE_END_ROUND, - double tension=0.5,double step=10); - void PolygonSmooth(int &x[],int &y[],const uint clr,const int size, - ENUM_LINE_STYLE style=STYLE_SOLID,ENUM_LINE_END end_style=LINE_END_ROUND, - double tension=0.5,double step=10); - //--- for text - bool FontSet(const string name,const int size,const uint flags=0,const uint angle=0); - bool FontNameSet(string name); - bool FontSizeSet(int size); - bool FontFlagsSet(uint flags); - bool FontAngleSet(uint angle); - void FontGet(string &name,int &size,uint &flags,uint &angle); - string FontNameGet(void) const { return(m_fontname); } - int FontSizeGet(void) const { return(m_fontsize); } - uint FontFlagsGet(void) const { return(m_fontflags); } - uint FontAngleGet(void) const { return(m_fontangle); } - void TextOut(int x,int y,string text,const uint clr,uint alignment=0); - int TextWidth(const string text); - int TextHeight(const string text); - void TextSize(const string text,int &width,int &height); - //--- services - static uint GetDefaultColor(const int i); - void TransparentLevelSet(const uchar value); - //--- load bitmap from file - bool LoadFromFile(const string filename); - //--- line style property - uint LineStyleGet(void) const; - void LineStyleSet(const uint style); - //--- load bitmap from file to buffer - static bool LoadBitmap(const string filename,uint &data[],int &width,int &height); - -private: - bool FontSet(void); - void TextOutFast(int x,int y,string text,const uint clr,uint alignment=0); - bool PixelsSimilar(const uint clr0,const uint clr1,const uint threshould); - //--- for Wu's algorithm - void PixelTransform(const int x,const int y,const uint clr,const double alpha); - //--- for circle and ellipse - void PixelTransform4(const int x,const int y,const int dx,const int dy,const uint clr,const double alpha); - void PixelSet4AA(const double x,const double y,const double dx,const double dy,const uint clr); - //--- for thick line - void SegmentVertical(const int x,const int y1,const int y2,const int ysign,const double r,const uint clr,ENUM_LINE_END end_style); - void SegmentHorizontal(const int x1,const int x2,const int y,const int xsign,const double r,const uint clr,ENUM_LINE_END end_style); - void Segment(const int x1,const int y1,const int x2,const int y2,const double kp0,const double kp1,const int xsign,const int ysign, - const double rcos_k,const double rsin_k,const double r,const uint clr,ENUM_LINE_END end_style); - double DistancePointSegment(const double px,const double py,const double x1,const double y1,const double x2,const double y2); - //--- for pie - double AngleCalc(int x1,int y1,int x2,int y2); - //--- for polygon - int PointClassify(const CPoint &p0,const CPoint &p1,const CPoint &p2); - int PolygonClassify(const CPoint &p[]); - bool IsPolygonConvex(CPoint &p[]); - void PolygonNormalize(CPoint &p[]); - void PolygonIntersect(CPoint &p[],CPoint &add[]); - void PolygonFill(CPoint &p[],const uint clr); - //--- for smoothing polyline and polygon - void CalcCurveBezierEndp(const double xend,const double yend,const double xadj,const double yadj,const double tension,double &x,double &y); - void CalcCurveBezier(const int &x[],const int &y[],const int i,const double tension,double &x1,double &y1,double &x2,double &y2); - double CalcBezierX(const double t,const double x0,const double x1,const double x2,const double x3); - double CalcBezierY(const double t,const double y0,const double y1,const double y2,const double y3); - -protected: - //--- method for prefiltered antialiasing - virtual double FilterFunction(const double x); - }; -//+------------------------------------------------------------------+ -//| Initialize static array | -//+------------------------------------------------------------------+ -uint CCanvas::m_default_colors[9]= - { - XRGB(0,0,255), // blue - XRGB(255,0,0), // red - XRGB(0,128,0), // green - XRGB(255,242,0), // yellow - XRGB(255,0,128), // pink - XRGB(0,255,0), // lime - XRGB(185,0,61), // crimson - XRGB(0,183,239), // sky blue - XRGB(255,128,0) // orange - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCanvas::CCanvas(void) : m_chart_id(0), - m_objname(NULL), - m_objtype(WRONG_VALUE), - m_rcname(NULL), - m_width(0), - m_height(0), - m_format(COLOR_FORMAT_XRGB_NOALPHA), - m_fontname("arial"), - m_fontsize(-120), - m_fontflags(0), - m_fontangle(0), - m_style(UINT_MAX), - m_style_idx(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCanvas::~CCanvas(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - Destroy(); -//--- prepare data array - if(width>0 && height>0 && ArrayResize(m_pixels,width*height)>0) - { - //--- generate resource name - m_rcname="::"+name+(string)ChartID()+(string)(GetTickCount()+MathRand()); - //--- initialize data with zeros - ArrayInitialize(m_pixels,0); - //--- create dynamic resource - if(ResourceCreate(m_rcname,m_pixels,width,height,0,0,0,clrfmt)) - { - //--- successfully created - //--- complete initialization - m_width =width; - m_height=height; - m_format=clrfmt; - //--- succeed - return(true); - } - } -//--- error - destroy object - Destroy(); - return(false); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmap(const string name,const datetime time,const double price, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - return(CreateBitmap(0,0,name,time,price,width,height,clrfmt)); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmap(const long chart_id,const int subwin,const string name, - const datetime time,const double price,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt) - { -//--- create canvas - if(Create(name,width,height,clrfmt)) - { - //--- create attached object - if(ObjectCreate(chart_id,name,OBJ_BITMAP,subwin,time,price)) - { - //--- bind object with resource - if(ObjectSetString(chart_id,name,OBJPROP_BMPFILE,m_rcname)) - { - //--- successfully created - //--- complete initialization - m_chart_id=chart_id; - m_objname =name; - m_objtype =OBJ_BITMAP; - //--- succeed - return(true); - } - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmapLabel(const string name,const int x,const int y, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - return(CreateBitmapLabel(0,0,name,x,y,width,height,clrfmt)); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmapLabel(const long chart_id,const int subwin,const string name, - const int x,const int y,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt) - { -//--- create canvas - if(Create(name,width,height,clrfmt)) - { - //--- create attached object - if(ObjectCreate(chart_id,name,OBJ_BITMAP_LABEL,subwin,0,0)) - { - //--- set x,y and bind object with resource - if(ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x) && - ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y) && - ObjectSetString(chart_id,name,OBJPROP_BMPFILE,m_rcname)) - { - //--- successfully created - //--- complete initialization - m_chart_id=chart_id; - m_objname =name; - m_objtype =OBJ_BITMAP_LABEL; - //--- succeed - return(true); - } - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Attach new object with bitmap resource | -//+------------------------------------------------------------------+ -bool CCanvas::Attach(const long chart_id,const string objname,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA) - { - if(OBJ_BITMAP_LABEL==ObjectGetInteger(chart_id,objname,OBJPROP_TYPE)) - { - string rcname=ObjectGetString(chart_id,objname,OBJPROP_BMPFILE); - rcname=StringSubstr(rcname,StringFind(rcname,"::")); - if(ResourceReadImage(rcname,m_pixels,m_width,m_height)) - { - m_chart_id=chart_id; - m_objname=objname; - m_rcname=rcname; - m_format=clrfmt; - m_objtype=OBJ_BITMAP_LABEL; - //--- success - return(true); - } - } -//--- failed - return(false); - } -//+------------------------------------------------------------------+ -//| Attach new object without bitmap resource | -//+------------------------------------------------------------------+ -bool CCanvas::Attach(const long chart_id,const string objname,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA) - { - if(OBJ_BITMAP_LABEL==ObjectGetInteger(chart_id,objname,OBJPROP_TYPE)) - { - string rcname=ObjectGetString(chart_id,objname,OBJPROP_BMPFILE); - if(StringLen(rcname)==0 && width>0 && height>0 && ArrayResize(m_pixels,width*height)>0) - { - ZeroMemory(m_pixels); - if(ResourceCreate("::"+objname,m_pixels,width,height,0,0,0,clrfmt) && - ObjectSetString(chart_id,objname,OBJPROP_BMPFILE,"::"+objname)) - { - m_chart_id=chart_id; - m_width=width; - m_height=height; - m_objname=objname; - m_rcname="::"+objname; - m_format=clrfmt; - m_objtype=OBJ_BITMAP_LABEL; - //--- success - return(true); - } - } - } -//--- failed - return(false); - } -//+------------------------------------------------------------------+ -//| Remove object from chart and deallocate data array | -//+------------------------------------------------------------------+ -void CCanvas::Destroy(void) - { -//--- delete object - if(m_objname!=NULL) - { - ObjectDelete(m_chart_id,m_objname); - m_chart_id=0; - m_objname =NULL; - m_objtype =WRONG_VALUE; - } -//--- deallocate array - ArrayFree(m_pixels); -//--- free resource - if(m_rcname!=NULL) - { - ResourceFree(m_rcname); - m_rcname=NULL; - } -//--- zeroize data - m_width =0; - m_height=0; - } -//+------------------------------------------------------------------+ -//| Update object on screen (redraw) | -//+------------------------------------------------------------------+ -void CCanvas::Update(const bool redraw) - { -//--- check - if(m_rcname==NULL) - return; -//--- update resource and redraw - if(ResourceCreate(m_rcname,m_pixels,m_width,m_height,0,0,0,m_format) && redraw) - ChartRedraw(this.m_chart_id); - } -//+------------------------------------------------------------------+ -//| Resize | -//+------------------------------------------------------------------+ -bool CCanvas::Resize(const int width,const int height) - { -//--- check - if(m_rcname!=NULL && width>0 && height>0) - if(ArrayResize(m_pixels,width*height)>0) - { - m_width =width; - m_height=height; - //--- initialize data with zeros - ArrayInitialize(m_pixels,0); - //--- create dynamic resource - if(ResourceCreate(m_rcname,m_pixels,m_width,m_height,0,0,0,m_format)) - { - //--- bind object with resource - if(m_objname!=NULL && ObjectSetString(m_chart_id,m_objname,OBJPROP_BMPFILE,m_rcname)) - return(true); - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Clear/Fill color | -//+------------------------------------------------------------------+ -void CCanvas::Erase(const uint clr) - { - ArrayInitialize(m_pixels,clr); - } -//+------------------------------------------------------------------+ -//| Get pixel color | -//+------------------------------------------------------------------+ -uint CCanvas::PixelGet(const int x,const int y) const - { -//--- check coordinates - if(x>=0 && x=0 && y=0 && x=0 && y=m_width || y<0 || y>=m_height) - return; -//--- - int index=y*m_width+x; - uint old_clr=m_pixels[index]; -//--- check if replacement is necessary - if(old_clr==clr) - return; -//--- use pseudo stack to emulate deeply-nested recursive calls - int stack[]; - uint count=1; - int idx; - int total=ArraySize(m_pixels); -//--- allocate memory for stack - if(ArrayResize(stack,total)==-1) - return; - stack[0]=index; - m_pixels[index]=clr; - for(uint i=0; i0 && m_pixels[idx]==old_clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- top adjacent point - idx=index-m_width; - if(idx>=0 && m_pixels[idx]==old_clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- right adjacent point - idx=index+1; - if(x=m_width || y<0 || y>=m_height || threshould>255) - return; -//--- - int index=y*m_width+x; - uint old_clr=m_pixels[index]; -//--- check if replacement is necessary - if(old_clr==clr) - return; -//--- use pseudo stack to emulate deeply-nested recursive calls - int stack[]; - uint count=1; - int idx; - int total=ArraySize(m_pixels); -//--- allocate memory for stack - if(ArrayResize(stack,total)==-1) - return; - stack[0]=index; - m_pixels[index]=clr; - for(uint i=0; i0 && PixelsSimilar(m_pixels[idx],old_clr,threshould) && m_pixels[idx]!=clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- top adjacent point - idx=index-m_width; - if(idx>=0 && PixelsSimilar(m_pixels[idx],old_clr,threshould) && m_pixels[idx]!=clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- right adjacent point - idx=index+1; - if(xy2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } -//--- line is out of image boundaries - if(y2<0 || y1>=m_height || x<0 || x>=m_width) - return; -//--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height) - y2=m_height-1; -//--- draw line - int index=y1*m_width+x; - for(int i=y1; i<=y2; i++,index+=m_width) - m_pixels[index]=clr; - } -//+------------------------------------------------------------------+ -//| Draw horizontal line | -//+------------------------------------------------------------------+ -void CCanvas::LineHorizontal(int x1,int x2,int y,const uint clr) - { - int tmp; -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- line is out of image boundaries - if(x2<0 || x1>=m_width || y<0 || y>=m_height) - return; -//--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; -//--- draw line - ArrayFill(m_pixels,y*m_width+x1,(x2-x1)+1,clr); - } -//+------------------------------------------------------------------+ -//| Draw line according to Bresenham's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::Line(int x1,int y1,int x2,int y2,const uint clr) - { -//--- line is out of image boundaries - if((x1<0 && x2<0) || (y1<0 && y2<0)) - return; - if(x1>=m_width && x2>=m_width) - return; - if(y1>=m_height && y2>=m_height) - return; -//--- get length by X and Y - int dx=(x2>x1)? x2-x1 : x1-x2; - int dy=(y2>y1)? y2-y1 : y1-y2; - if(dx==0) - { - //--- vertical line - LineVertical(x1,y1,y2,clr); - return; - } - if(dy==0) - { - //--- horizontal line - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- get direction by X and Y - int sx=(x1=m_width || - y1<0 || y1>=m_height) - { - if(draw) - return; - } - else - { - //--- draw pixel - m_pixels[y1*m_width+x1]=clr; - draw=true; - } - //--- get coordinates of next pixel - int er2=er<<1; - if(er2>-dy) - { - er-=dy; - x1+=sx; - } - if(er2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- draw - for(int i=0; iArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- draw - for(int i=0; i=dx) - { - xx=x+dx; - if(xx>=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0) - { - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - dd_x+=2; - f+=dd_x; - } - } -//+------------------------------------------------------------------+ -//| Draw ellipse according to Bresenham's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::Ellipse(int x1,int y1,int x2,int y2,const uint clr) - { - int x,y; - int rx,ry; - int dx,dy; - int xx,yy; - int rx_sq,ry_sq; - int f; - int tmp; -//--- handle extreme conditions - if(x1==x2) - { - if(y1==y2) - PixelSet(x1,y1,clr); - else - LineVertical(x1,y1,y2,clr); - return; - } - if(y1==y2) - { - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; - rx=(x2-x1)>>1; - ry=(y2-y1)>>1; - dx=0; - dy=ry; - rx_sq=rx*rx; - ry_sq=ry*ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>ry_sq*dx) - { - yy=y+dy; - if(yy>=0 && yy=0 && xx=0 && xx=0 && yy=0 && xx=0 && xx=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - f=(ry_sq<<1)*(dx+1)*dx+(rx_sq<<1)*(dy*(dy-2)+1)+(1-(rx_sq<<1))*ry_sq; - while(dy>=0) - { - yy=y+dy; - if(yy>=0 && yy=0 && xx=0 && xx=0 && yy=0 && xx=0 && xxx2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; -//--- check rays - if(x3==x && y3==y) - return; - if(x4==x && y4==y) - return; -//--- calculate parameters of ray x3,y3 - fi3=AngleCalc(x,y,x3,y3); -//--- calculate parameters of ray x4,y4 - fi4=AngleCalc(x,y,x4,y4); -//--- draw arc - Arc(x,y,x2-x,y2-y,fi3,fi4,clr); - } -//+------------------------------------------------------------------+ -//| Draws ellipse arc | -//+------------------------------------------------------------------+ -void CCanvas::Arc(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr) - { - int x3,y3,x4,y4; -//--- check - if(rx<10 || ry<10) - return; - if(rx<0) - rx=-rx; - if(ry<0) - ry=-ry; -//--- check rays - if(fi3==fi4) - return; -//--- adjustment for passing through 0 - if(fi40) || // ray 3 is in the 1st or 2nd quadrant - (fi0) || // ray 4 is in the 1st or 2nd quadrant - (fi4-fi3>=M_PI)) // arc will pass through the top of the ellipse - { - dx=0; - dy=ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>=ry_sq*dx) - { - yy=y-dy; - if(dx==0) - { - //--- central point - fi=AngleCalc(0,0,0,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(x,yy,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=x; - yy_c=yy; - fi_c=fi; - xx_a=x; - yy_a=yy; - fi_a=fi; - } - else - { - //--- iterate clockwise - xx=x+dx; - fi=AngleCalc(0,0,dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - xx=x-dx; - fi=AngleCalc(0,0,-dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,dx,-dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x+dx,y3=y-dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,-dx,-dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x-dx,y4=y-dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 2 left -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi3>M_PI_2 && fi3<3*M_PI_2) || // ray 3 is in the 2nd or 3rd quadrant - (fi>M_PI_2 && fi<3*M_PI_2) || // ray 4 is in the 2nd or 3rd quadrant - (fi4-fi3>=M_PI)) // arc will pass through the left part of the ellipse - { - dx=rx; - dy=0; - f=(ry_sq<<1)*((dx-1)*dx)+ry_sq+(rx_sq<<1)*(1-ry_sq); - while(ry_sq*dx>=rx_sq*dy) - { - xx=x-dx; - if(dy==0) - { - //--- central point - fi=AngleCalc(0,0,-dx,0); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,y,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=xx; - yy_c=y; - fi_c=fi; - xx_a=xx; - yy_a=y; - fi_a=fi; - } - else - { - //--- iterate clockwise - yy=y-dy; - fi=AngleCalc(0,0,-dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - yy=y+dy; - fi=AngleCalc(0,0,-dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dx--; - f-=(ry_sq<<2)*dx; - } - f+=(rx_sq<<1)*(3+(dy<<1)); - dy++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,-dx,-dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x-dx,y3=y-dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,-dx,dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x-dx,y4=y+dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 3 bottom -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi3>M_PI && fi3<2*M_PI) || // ray 3 is in the 3rd or 4th quadrant - (fi>M_PI && fi<2*M_PI) || // ray 4 is in the 3rd or 4th quadrant - (fi4-fi3>=M_PI)) // arc will pass through the bottom of the ellipse - { - dx=0; - dy=ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>=ry_sq*dx) - { - yy=y+dy; - if(dx==0) - { - //--- central point - fi=AngleCalc(0,0,0,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(x,yy,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=x; - yy_c=yy; - fi_c=fi; - xx_a=x; - yy_a=yy; - fi_a=fi; - } - else - { - //--- iterate clockwise - xx=x-dx; - fi=AngleCalc(0,0,-dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - xx=x+dx; - fi=AngleCalc(0,0,dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,-dx,dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x-dx,y3=y+dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,dx,dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x+dx,y4=y+dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 4 right -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi33*M_PI_2) || // ray 3 is 1 or 4 quadrant - (fi3*M_PI_2) || // ray 4 is 1 or 4 quadrant - (fi4-fi3>=M_PI)) // arc will pass through the right side of the ellipse - { - dx=rx; - dy=0; - f=(ry_sq<<1)*((dx-1)*dx)+ry_sq+(rx_sq<<1)*(1-ry_sq); - while(ry_sq*dx>=rx_sq*dy) - { - xx=x+dx; - if(dy==0) - { - //--- central point - fi=AngleCalc(0,0,dx,0); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,y,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=xx; - yy_c=y; - fi_c=fi; - xx_a=xx; - yy_a=y; - fi_a=fi; - } - else - { - //--- iterate clockwise - yy=y+dy; - fi=AngleCalc(0,0,dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - yy=y-dy; - fi=AngleCalc(0,0,dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(MathMod(fi_a,2*M_PI)-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dx--; - f-=(ry_sq<<2)*dx; - } - f+=(rx_sq<<1)*(3+(dy<<1)); - dy++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,dx,dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x+dx,y3=y+dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,dx,-dy); - if(MathAbs(MathMod(fi_a,2*M_PI)-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x+dx,y4=y-dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } - } -//+------------------------------------------------------------------+ -//| Draws ellipse pie | -//+------------------------------------------------------------------+ -void CCanvas::Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr,const uint fill_clr) - { - int tmp; - int x,y; -//--- - double fi3; - double fi4; -//--- check - if(x1==x2 || y1==y2) - return; -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; -//--- check rays - if(x3==x && y3==y) - return; - if(x4==x && y4==y) - return; -//--- calculate parameters of ray x3,y3 - fi3=AngleCalc(x,y,x3,y3); -//--- calculate parameters of ray x4,y4 - fi4=AngleCalc(x,y,x4,y4); -//--- draw pie - Pie(x,y,x2-x,y2-y,fi3,fi4,clr,fill_clr); - } -//+------------------------------------------------------------------+ -//| Draws ellipse pie | -//+------------------------------------------------------------------+ -void CCanvas::Pie(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr,const uint fill_clr) - { - int x3=x; - int y3=y; - int x4=x; - int y4=y; -//--- check - if(rx==0 || ry==0) - return; - if(rx<0) - rx=-rx; - if(ry<0) - ry=-ry; -//--- check rays - if(fi3==fi4) - return; -//--- adjustment for passing through 0 - if(fi4ry) - rx=ry; - double fi=(fi3+fi4)/2; - int xf=x+(int)(0.9*rx*cos(fi)); - int yf=y-(int)(0.9*rx*sin(fi)); - Fill(xf,yf,fill_clr); - } -//+------------------------------------------------------------------+ -//| Draw filled circle | -//+------------------------------------------------------------------+ -void CCanvas::FillCircle(int x,int y,int r,const uint clr) - { - int f =1-r; - int dd_x=1; - int dd_y=-2*r; - int dx =0; - int dy =r; -//--- draw - while(dy>=dx) - { - LineHorizontal(x-dy,x+dy,y-dx,clr); - LineHorizontal(x-dy,x+dy,y+dx,clr); - //--- - if(f>=0) - { - LineHorizontal(x-dx,x+dx,y-dy,clr); - LineHorizontal(x-dx,x+dx,y+dy,clr); - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - dd_x+=2; - f+=dd_x; - } - } -//+------------------------------------------------------------------+ -//| Draw filled ellipse | -//+------------------------------------------------------------------+ -void CCanvas::FillEllipse(int x1,int y1,int x2,int y2,const uint clr) - { - int x,y; - int rx,ry; - int dx,dy; - int rx_sq,ry_sq; - int f; - int tmp; -//--- handle extreme conditions - if(x1==x2) - { - if(y1==y2) - PixelSet(x1,y1,clr); - else - LineVertical(x1,y1,y2,clr); - return; - } - if(y1==y2) - { - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; - rx=(x2-x1)>>1; - ry=(y2-y1)>>1; - dx=0; - dy=ry; - rx_sq=rx*rx; - ry_sq=ry*ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>ry_sq*(dx)) - { - LineHorizontal(x-dx,x+dx,y+dy,clr); - LineHorizontal(x-dx,x+dx,y-dy,clr); - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - f=(ry_sq<<1)*(dx+1)*dx+(rx_sq<<1)*(dy*(dy-2)+1)+(1-(rx_sq<<1))*ry_sq; - while(dy>=0) - { - LineHorizontal(x-dx,x+dx,y+dy,clr); - LineHorizontal(x-dx,x+dx,y-dy,clr); - if(f<=0) - { - dx++; - f+=(ry_sq<<2)*dx; - } - dy--; - f+=(rx_sq<<1)*(3-(dy<<1)); - } - } -//+------------------------------------------------------------------+ -//| Draw filled rectangle | -//+------------------------------------------------------------------+ -void CCanvas::FillRectangle(int x1,int y1,int x2,int y2,const uint clr) - { - int tmp; -//--- sort vertexes - if(x2=m_width || y1>=m_height) - return; -//--- stay withing screen boundaries - if(x1<0) - x1=0; - if(y1<0) - y1=0; - if(x2>=m_width) - x2=m_width -1; - if(y2>=m_height) - y2=m_height-1; - int len=(x2-x1)+1; -//--- set pixels - for(; y1<=y2; y1++) - ArrayFill(m_pixels,y1*m_width+x1,len,clr); - } -//+------------------------------------------------------------------+ -//| Draw filled triangle | -//+------------------------------------------------------------------+ -void CCanvas::FillTriangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr) - { - int xx1,xx2,tmp; - double k1=0,k2=0,xd1,xd2; -//--- sort vertexes from lesser to greater - if(y1>y2) - { - tmp=y2; - y2 =y1; - y1 =tmp; - tmp=x2; - x2 =x1; - x1=tmp; - } - if(y1>y3) - { - tmp=y1; - y1 =y3; - y3 =tmp; - tmp=x1; - x1 =x3; - x3 =tmp; - } - if(y2>y3) - { - tmp=y2; - y2 =y3; - y3 =tmp; - tmp=x2; - x2 =x3; - x3 =tmp; - } -//--- all vertexes are out of image boundaries - if(y3<0 || y1>m_height) - return; - if(x1<0 && x2<0 && x3<0) - return; - if(x1>m_width && x2>m_width && x3>m_width) - return; -//--- find coefficients of lines - if((tmp=y1-y2)!=0) - k1=(x1-x2)/(double)tmp; - if((tmp=y1-y3)!=0) - k2=(x1-x3)/(double)tmp; -//--- - xd1=x1; - xd2=x1; -//--- - for(int i=y1; i<=y3; i++) - { - if(i==y2) - { - if((tmp=y2-y3)!=0) - k1=(x2-x3)/(double)tmp; - xd1=x2; - } - //--- calculate new boundaries of triangle line - xx1 =(int)xd1; - xd1+=k1; - xx2 =(int)xd2; - xd2+=k2; - //--- triangle line is out of screen boundaries - if(i<0 || i>=m_height) - continue; - //--- sort - if(xx1>xx2) - { - tmp=xx1; - xx1=xx2; - xx2=tmp; - } - //--- line is out of screen boundaries - if(xx2<0 || xx1>=m_width) - continue; - //--- draw only what is within screen boundaries - if(xx1<0) - xx1=0; - if(xx2>=m_width) - xx2=m_width-1; - //--- draw horizontal line of triangle - ArrayFill(m_pixels,i*m_width+xx1,xx2-xx1,clr); - } - } -//+------------------------------------------------------------------+ -//| Draw filled poligon | -//+------------------------------------------------------------------+ -void CCanvas::FillPolygon(int &x[],int &y[],const uint clr) - { - static CPoint p[]; - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<3) - return; -//--- resize array of points - ArrayResize(p,total); -//--- find top-left point - int imin=0; - int xmin=x[0]; - int ymin=y[0]; - for(int i=1; iymin) - continue; - if(y[i]==ymin) - { - if(x[i]0.0) - xx[1]=xx[3]=ix+1; - if(dy<0.0) - yy[2]=yy[2]=iy-1; - if(dy==0.0) - yy[2]=yy[2]=iy; - if(dy>0.0) - yy[2]=yy[2]=iy+1; -//--- calculate radii and sum of their squares - for(int i=0; i<4; i++) - { - dx=xx[i]-x; - dy=yy[i]-y; - rr[i]=1/(dx*dx+dy*dy); - rrr+=rr[i]; - } -//--- draw pixels - for(int i=0; i<4; i++) - { - k=rr[i]/rrr; - c=PixelGet(xx[i],yy[i]); - a=(uchar)(k*GETRGBA(clr)+(1-k)*GETRGBA(c)); - r=(uchar)(k*GETRGBR(clr)+(1-k)*GETRGBR(c)); - g=(uchar)(k*GETRGBG(clr)+(1-k)*GETRGBG(c)); - b=(uchar)(k*GETRGBB(clr)+(1-k)*GETRGBB(c)); - PixelSet(xx[i],yy[i],ARGB(a,r,g,b)); - } - } -//+------------------------------------------------------------------+ -//| Get line style | -//+------------------------------------------------------------------+ -uint CCanvas::LineStyleGet(void) const - { - switch(m_style) - { - case 0xFFFFFF: - return(STYLE_SOLID); - break; - case 0x3FFFF: - return(STYLE_DASH); - break; - case 0x1C71C7: - return(STYLE_DOT); - break; - case 0x381FF: - return(STYLE_DASHDOT); - break; - case 0x1C71FF: - return(STYLE_DASHDOTDOT); - break; - default: - return (m_style); - break; - } - } -//+------------------------------------------------------------------+ -//| Set line style | -//+------------------------------------------------------------------+ -void CCanvas::LineStyleSet(const uint style) - { - switch(style) - { - case STYLE_SOLID: - m_style=0xFFFFFF; - break; - case STYLE_DASH: - m_style=0x3FFFF; - break; - case STYLE_DOT: - m_style=0x1C71C7; - break; - case STYLE_DASHDOT: - m_style=0x381FF; - break; - case STYLE_DASHDOTDOT: - m_style=0x1C71FF; - break; - default: - //--- high-order bit must be set then custom style - if((style&0x80000000)!=0) - { - m_style=style; - } - break; - } - m_style_idx=0; - } -//+------------------------------------------------------------------+ -//| Draw line with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::LineAA(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style) - { -//--- line is out of image boundaries - if((x1<0 && x2<0) || (y1<0 && y2<0)) - return; - if(x1>=m_width && x2>=m_width) - return; - if(y1>=m_height && y2>=m_height) - return; -//--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - return; - } -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); -//--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - uint mask=1<=fabs(dx) && fabs(y2-yy)>=fabs(dy)); -//--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw polyline with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::PolylineAA(int &x[],int &y[],const uint clr,const uint style) - { -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<=m_width && x2>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - if(y1>=m_height && y2>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - //--- set pixels - dx/=xy; - dy/=xy; - do - { - if((m_style&mask)==mask) - { - PixelSetAA(xx,yy,clr); - } - xx+=dx; - yy+=dy; - mask<<=1; - if(mask==0x1000000) - mask=1; - } - while(fabs(x2-xx)>=fabs(dx) && fabs(y2-yy)>=fabs(dy)); - //--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } - mask<<=1; - if(mask==0x1000000) - mask=1; - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw polygon with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::PolygonAA(int &x[],int &y[],const uint clr,const uint style) - { -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<=m_width && x2>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - if(y1>=m_height && y2>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - //--- set pixels - dx/=xy; - dy/=xy; - do - { - if((m_style&mask)==mask) - { - PixelSetAA(xx,yy,clr); - } - xx+=dx; - yy+=dy; - mask<<=1; - if(mask==0x1000000) - mask=1; - } - while(fabs(x2-xx)>=fabs(dx) && fabs(y2-yy)>=fabs(dy)); - //--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw triangle with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::TriangleAA(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3,const uint clr,const uint style) - { -//--- draw - int x[3]; - int y[3]; - x[0] = x1; - x[1] = x2; - x[2] = x3; - y[0] = y1; - y[1] = y2; - y[2] = y3; - PolygonAA(x,y,clr,style); - } -//+------------------------------------------------------------------+ -//| Draw circle with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::CircleAA(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX) - { - if(r<=0) - return; -//--- preliminary calculations - double xx=x+r; - double yy=y; - double fi=0; - double df=M_PI_2/MathCeil(r); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<M_PI) - df/=2; - do - { - xx=x+r*cos(fi); - yy=y-r*sin(fi); - if((m_style&mask)==mask) - PixelSetAA(xx,yy,clr); - mask<<=1; - if(mask==0x1000000) - mask=1; - fi+=df; - } - while(fabs(2*M_PI-fi)>=df/2); -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw ellipse with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::EllipseAA(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style=UINT_MAX) - { - double rx = (x2-x1)/2; - double ry = (y2-y1)/2; -//--- preliminary calculations - double x=(x2>x1) ? x1+rx : x2+rx; - double y=(y2>y1) ? y1+ry : y2+ry; - double rx2=rx*rx; - double ry2=ry*ry; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<ym) - continue; - if((p[i].y==ym) && (p[i].x>xm)) - continue; - im=i; - xm=p[i].x; - ym=p[i].y; - } -//--- check the orientation of triangle - return PointClassify(p[(im-1+total)%total],p[im],p[(im+1)%total]); - } -//+------------------------------------------------------------------+ -//| Checks convexity of polygon | -//+------------------------------------------------------------------+ -bool CCanvas::IsPolygonConvex(CPoint &p[]) - { - int total=ArraySize(p); -//--- triangle - always convex - if(total==3) - return(true); - int res=SIGN(PointClassify(p[0],p[1],p[2])); - for(int i=1; iymin) - continue; - if(p[i].y==ymin) - { - if(p[i].xp[il].y) - return; - if(yy!=p[il].y) - { - dl=(p[il].x-xl)/(p[il].y-yy); - //--- make adjustment for half of left increment dl/2 - LineHorizontal((int)MathCeil(xl+dl/2),(int)MathFloor(xl),yy,clr); - xl+=dl/2; - } - else - LineHorizontal((int)MathCeil(xl),(int)MathFloor(p[il].x),yy,clr); - } - while(yy==p[ir].y) - { - ir=(ir+1)%total; - if(yy>p[ir].y) - return; - if(yy!=p[ir].y) - { - dr=(p[ir].x-xr)/(p[ir].y-yy); - //--- make adjustment for half of right increment dr/2 - LineHorizontal((int)MathCeil(xr),(int)MathFloor(xr+dr/2),yy,clr); - xr+=dr/2; - } - else - LineHorizontal((int)MathCeil(p[ir].x),(int)MathFloor(xr),yy,clr); - } - yy++; - if(yy==p[il].y) - xl=p[il].x; - else - xl+=dl; - if(yy==p[ir].y) - xr=p[ir].x; - else - xr+=dr; - LineHorizontal((int)MathCeil(xl),(int)MathFloor(xr),yy,clr); - } - while(il>=ir && ir!=0); - } -//+------------------------------------------------------------------+ -//| Draw line according to Wu's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::LineWu(int x1,int y1,int x2,int y2,const uint clr,const uint style=UINT_MAX) - { -//--- calculating the variation of the coordinates - int dx = (x2 > x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int i=y1; i<=y2; i++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - //--- success - return; - } -//--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int i=0,index=y1*m_width+x1; i 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1< x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); - int tmp; - //--- check if dx==0 then draw vertical line - if(dx==0) - { - //--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - continue; - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int j=y1; j<=y2; j++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - continue; - } - //--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - continue; - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int j=0,index=y1*m_width+x1; j 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1< x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); - int tmp; - //--- check if dx==0 then draw vertical line - if(dx==0) - { - //--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - continue; - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int j=y1; j<=y2; j++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - continue; - } - //--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - continue; - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int j=0,index=y1*m_width+x1; j 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2x1) ? x1+rx : x2+rx; - int y=(y2>y1) ? y1+ry : y2+ry; - if(rx<=0 || ry<=0) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - LineWu(x,y1,x,y2,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- primary calculate - int dy=MathAbs(y2-y1); - int sign=(y10) - LineWu(x1,y,x2,y,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- primary calculate - int dx=MathAbs(x2-x1); - int sign=(x10) - LineWu(x1,y1,x2,y2,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- compute x and y deltas - double dx=MathAbs(x2-x1); - double dy=MathAbs(y2-y1); - if(dx==0) - { - LineThickVertical(x1,y1,y2,clr,size,style,end_style); - return; - } - if(dy==0) - { - LineThickHorizontal(x1,x2,y1,clr,size,style,end_style); - return; - } -//--- compute the linear coefficients of the two (scaled) edge functions - double k=MathArctan(dx/dy); - double rcos_k=r*cos(k); - double rsin_k=r*sin(k); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - PolylineWu(x,y,clr,style); - return; - } -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- - double gap=1.0; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - PolylineWu(x,y,clr,style); - return; - } -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- - double gap=1.0; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<>16) &0xff) - - uint((clr1>>16) &0xff)); - uint dg=MathAbs(uint((clr0>>8) &0xff) - - uint((clr1>>8) &0xff)); - uint db=MathAbs(uint((clr0>>0) &0xff) - - uint((clr1>>0) &0xff)); -//--- return - return (dr<=threshould || dg<=threshould || db<=threshould); - } -//+------------------------------------------------------------------+ -//| Calculate and set new color | -//+------------------------------------------------------------------+ -void CCanvas::PixelTransform(const int x,const int y,const uint clr,const double alpha) - { - int index=y*m_width+x; -//--- check - if(x<0 || y<0 || x>m_width || y>m_height || index>=ArraySize(m_pixels)) - return; -//--- check alpha - if(alpha==1) - { - m_pixels[index]=clr; - return; - } -//--- get pixel color - uint clr0=m_pixels[index]; -//--- transform of color component for the background - double r0 = ((clr0>>16) & 0xFF) * (1.0-alpha); - double g0 = ((clr0>>8) & 0xFF) * (1.0-alpha); - double b0 = ((clr0>>0) & 0xFF) * (1.0-alpha); -//--- transform of color component - double r1 = ((clr>>16) & 0xFF) * (alpha); - double g1 = ((clr>>8) & 0xFF) * (alpha); - double b1 = ((clr>>0) & 0xFF) * (alpha); -//--- components of the new color - int r = (int)(r0+r1); - int g = (int)(g0+g1); - int b = (int)(b0+b1); -//--- set new color - m_pixels[y*m_width+x]=((r<<16)|(g<<8)|(b<<0)|(255<<24)); - } -//+------------------------------------------------------------------+ -//| Draw 4 pixel with PixelTransform method | -//+------------------------------------------------------------------+ -void CCanvas::PixelTransform4(const int x,const int y,const int dx,const int dy,const uint clr,const double alpha) - { - PixelTransform(x+dx,y+dy,clr,alpha); - PixelTransform(x-dx,y+dy,clr,alpha); - PixelTransform(x+dx,y-dy,clr,alpha); - PixelTransform(x-dx,y-dy,clr,alpha); - } -//+------------------------------------------------------------------+ -//| Draw 4 pixel with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::PixelSet4AA(const double x,const double y,const double dx,const double dy,const uint clr) - { - PixelSetAA(x+dx,y+dy,clr); - PixelSetAA(x-dx,y+dy,clr); - PixelSetAA(x+dx,y-dy,clr); - PixelSetAA(x-dx,y-dy,clr); - } -//+------------------------------------------------------------------+ -//| Draw solid segment for vertical thick line | -//+------------------------------------------------------------------+ -void CCanvas::SegmentVertical(const int x,const int y1,const int y2,const int ysign,const double r,const uint clr,ENUM_LINE_END end_style) - { -//--- compute the constol points of the solid segment - int ye1,ye2; - int ys1,ys2; - switch(end_style) - { - case LINE_END_ROUND: - { - ye1=y1; - ye2=y2; - ys1=y1-(int)(ysign*r); - ys2=y2+(int)(ysign*r); - break; - } - case LINE_END_BUTT: - { - ye1=y1; - ye2=y2; - ys1=y1; - ys2=y2; - break; - } - case LINE_END_SQUARE: - { - ye1=y1-(int)(ysign*r); - ye2=y2+(int)(ysign*r); - ys1=ye1; - ys2=ye2; - break; - } - default: - return; - }; -//--- darw solid segment - for(int i=0; i<=MathAbs(ys2-ys1); i++) - { - double yi=ys1+(ysign*i); - for(int j=0; j<2*r; j++) - { - double xi=x-r+j; - double dist=DistancePointSegment(xi,yi,x,ye1,x,ye2); - double val=MathAbs(dist/r); - PixelTransform((int)xi,(int)yi,clr,FilterFunction(val)); - } - } - } -//+------------------------------------------------------------------+ -//| Draw solid segment for horizontal thick line | -//+------------------------------------------------------------------+ -void CCanvas::SegmentHorizontal(const int x1,const int x2,const int y,const int xsign,const double r,const uint clr,ENUM_LINE_END end_style) - { -//--- compute the constol points of the solid segment - int xe1,xe2; - int xs1,xs2; - switch(end_style) - { - case LINE_END_ROUND: - { - xe1=x1; - xe2=x2; - xs1=x1-(int)(xsign*r); - xs2=x2+(int)(xsign*r); - break; - } - case LINE_END_BUTT: - { - xe1=x1; - xe2=x2; - xs1=x1; - xs2=x2; - break; - } - case LINE_END_SQUARE: - { - xe1=x1-(int)(xsign*r); - xe2=x2+(int)(xsign*r); - xs1=xe1; - xs2=xe2; - break; - } - default: - return; - }; -//--- draw solid segment - for(int i=0; i<=MathAbs(xs2-xs1); i++) - { - double xi=xs1+(xsign*i); - for(int j=0; j<2*r; j++) - { - double yi=y-r+j; - double dist=DistancePointSegment(xi,yi,xe1,y,xe2,y); - double val=MathAbs(dist/r); - PixelTransform((int)xi,(int)yi,clr,FilterFunction(val)); - } - } - } -//+------------------------------------------------------------------+ -//| Draw solid segment for thick line | -//+------------------------------------------------------------------+ -void CCanvas::Segment(const int x1,const int y1,const int x2,const int y2,const double kp0,const double kp1,const int xsign,const int ysign, - const double rcos_k,const double rsin_k,const double r,const uint clr,ENUM_LINE_END end_style) - { - if(x1==x2 && y1==y2) - return; - if(x1==x2) - { - SegmentVertical(x1,y1,y2,ysign,r,clr,end_style); - return; - } - if(y1==y2) - { - SegmentHorizontal(x1,x2,y1,xsign,r,clr,end_style); - return; - } -//--- compute the constol points of the solid segment - int xe1,ye1,xe2,ye2; - int xs1,ys1,xs2,ys2; - switch(end_style) - { - case LINE_END_ROUND: - { - xe1=x1; - ye1=y1; - xe2=x2; - ye2=y2; - xs1=x1-(xsign)*(int)(rsin_k); - ys1=y1-(ysign)*(int)(rcos_k); - xs2=x2+(xsign)*(int)(rsin_k); - ys2=y2+(ysign)*(int)(rcos_k); - break; - } - case LINE_END_BUTT: - { - xe1=x1; - ye1=y1; - xe2=x2; - ye2=y2; - xs1=x1; - ys1=y1; - xs2=x2; - ys2=y2; - break; - } - case LINE_END_SQUARE: - { - xe1=x1-(xsign)*(int)(rsin_k); - ye1=y1-(ysign)*(int)(rcos_k); - xe2=x2+(xsign)*(int)(rsin_k); - ye2=y2+(ysign)*(int)(rcos_k); - xs1=xe1; - ys1=ye1; - xs2=xe2; - ys2=ye2; - break; - } - default: - return; - }; -//--- compute the four corners of the wide line - double p0x=xs1+(xsign)*(rcos_k); - double p0y=ys1-(ysign)*(rsin_k); - double p1x=xs1-(xsign)*(rcos_k); - double p1y=ys1+(ysign)*(rsin_k); - double p2x=xs2+(xsign)*(rcos_k); - double p2y=ys2-(ysign)*(rsin_k); - double p3x=xs2-(xsign)*(rcos_k); - double p3y=ys2+(ysign)*(rsin_k); -//--- draw solid segment - if(MathAbs(kp0)>=1) - { - double xi0,xi1; - double height=MathAbs(p3y-p0y); - for(int i=0; i<=height; i++) - { - double y=p0y+(ysign*i); - double xi00 = MathRound(p0x + (y-p0y)/kp0); - double xi01 = MathRound(p1x + (y-p1y)/kp1); - double xi02 = MathRound(p2x + (y-p2y)/kp1); - double xi03 = MathRound(p3x + (y-p3y)/kp0); - if(xsign==1) - { - xi0 = MathMax(xi00,xi01); - xi1 = MathMin(xi02,xi03); - } - else - { - xi0 = MathMin(xi00,xi01); - xi1 = MathMax(xi02,xi03); - } - double width=MathAbs(MathRound(xi1-xi0)); - for(int j=0; j<=width; j++) - { - double xi=xi0+(xsign*j); - double dist=DistancePointSegment(xi,y,xe1,ye1,xe2,ye2); - double val = MathAbs(dist/r); - PixelTransform((int)xi,(int)y,clr,FilterFunction(val)); - } - } - } - else - { - double yi0,yi1; - double width=MathAbs(p2x-p1x); - for(int i=0; i<=width; i++) - { - double x=p1x+(xsign*i); - double yi00 = MathRound(p0y + (x-p0x)*kp0); - double yi01 = MathRound(p1y + (x-p1x)*kp1); - double yi02 = MathRound(p2y + (x-p2x)*kp1); - double yi03 = MathRound(p3y + (x-p3x)*kp0); - if(ysign==1) - { - yi0 = MathMax(yi00,yi02); - yi1 = MathMin(yi01,yi03); - } - else - { - yi0 = MathMin(yi00,yi02); - yi1 = MathMax(yi01,yi03); - } - double height=MathAbs(yi1-yi0); - for(int j=0; j<=height; j++) - { - double yi=yi0+(ysign*j); - double dist=DistancePointSegment(x,yi,xe1,ye1,xe2,ye2); - double val=MathAbs(dist/r); - PixelTransform((int)x,(int)yi,clr,FilterFunction(val)); - } - } - } - } -//+------------------------------------------------------------------+ -//| Filter function for calculating alpha channel | -//+------------------------------------------------------------------+ -double CCanvas::FilterFunction(const double x) - { - if(x<=0.8) - return(1.0); - else - return MathExp(-(x-0.8)*(x-0.8)*50); - } -//+------------------------------------------------------------------+ -//| Calculate distance between point and segment | -//+------------------------------------------------------------------+ -double CCanvas::DistancePointSegment(const double px,const double py,const double x1,const double y1,const double x2,const double y2) - { -//--- primary calculate - double a=(px-x1)*(px-x1)+(py-y1)*(py-y1); - double b=(px-x2)*(px-x2)+(py-y2)*(py-y2); - double c=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); -//--- check - if(a>=b+c) - return (MathSqrt(b)); - if(b>=a+c) - return (MathSqrt(a)); -//--- calculate distance - a=MathSqrt(a); - b=MathSqrt(b); - c=MathSqrt(c); - double p=(a+b+c)/2; - double s=MathSqrt((p-a)*(p-b)*(p-c)*p); -//--- check distance - if(MathIsValidNumber(s)) - return(s*2.0/c); - else - return(0); - } -//+------------------------------------------------------------------+ -//| Draw smothing polyline | -//+------------------------------------------------------------------+ -void CCanvas::PolylineSmooth(const int &x[],const int &y[],const uint clr,const int size,ENUM_LINE_STYLE style=STYLE_SOLID, - ENUM_LINE_END end_style=LINE_END_ROUND,double tension=0.5,double step=10) - { -//--- - int arr_size= ArraySize(x); - if(arr_size!=ArraySize(y)) - return; -//--- - double x1,x2,y1,y2; - tension*=0.3; -//--- coordinates of Bezier curve - int xc[]; - int yc[]; -//--- initialize control points - double ptX[]; - double ptY[]; - int size_pt=arr_size*3-2; - - ArrayResize(ptX,size_pt); - ArrayResize(ptY,size_pt); -//--- calculation of control points - CalcCurveBezierEndp(x[0],y[0],x[1],y[1],tension,x1,y1); - - ptX[0] = x[0]; - ptY[0] = y[0]; - ptX[1] = x1; - ptY[1] = y1; - - for(int i=0; i0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; t0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; t0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; 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 M#L|%;i-Umw2O)7eL;wH) diff --git a/Include/Canvas/Charts/ChartCanvas.mqh b/Include/Canvas/Charts/ChartCanvas.mqh deleted file mode 100644 index 5c72678..0000000 --- a/Include/Canvas/Charts/ChartCanvas.mqh +++ /dev/null @@ -1,1041 +0,0 @@ -//+------------------------------------------------------------------+ -//| ChartCanvas.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "..\Canvas.mqh" -#include -#include -#include -//--- enumerations -enum ENUM_SHOW_FLAGS - { - FLAG_SHOW_NONE =0, - FLAG_SHOW_LEGEND =1, - FLAG_SHOW_SCALE_LEFT =2, - FLAG_SHOW_SCALE_RIGHT =4, - FLAG_SHOW_SCALE_TOP =8, - FLAG_SHOW_SCALE_BOTTOM=16, - FLAG_SHOW_GRID =32, - FLAG_SHOW_DESCRIPTORS =64, - FLAG_SHOW_VALUE =128, - FLAG_SHOW_PERCENT =256, - FLAGS_SHOW_SCALES =(FLAG_SHOW_SCALE_LEFT+FLAG_SHOW_SCALE_RIGHT+ - FLAG_SHOW_SCALE_TOP+FLAG_SHOW_SCALE_BOTTOM), - FLAGS_SHOW_ALL =(FLAG_SHOW_LEGEND+FLAGS_SHOW_SCALES+FLAG_SHOW_GRID+ - FLAG_SHOW_DESCRIPTORS+FLAG_SHOW_VALUE+FLAG_SHOW_PERCENT) - }; -enum ENUM_ALIGNMENT - { - ALIGNMENT_LEFT = 1, // align by left border - ALIGNMENT_TOP = 2, // align by top border - ALIGNMENT_RIGHT = 4, // align by right border - ALIGNMENT_BOTTOM = 8 // align by bottom border - }; -//--- macro -#define IS_SHOW_LEGEND ((m_show_flags&FLAG_SHOW_LEGEND) !=0) -#define IS_SHOW_SCALES ((m_show_flags&FLAGS_SHOW_SCALES) !=0) -#define IS_SHOW_SCALE_LEFT ((m_show_flags&FLAG_SHOW_SCALE_LEFT) !=0) -#define IS_SHOW_SCALE_RIGHT ((m_show_flags&FLAG_SHOW_SCALE_RIGHT) !=0) -#define IS_SHOW_SCALE_TOP ((m_show_flags&FLAG_SHOW_SCALE_TOP) !=0) -#define IS_SHOW_SCALE_BOTTOM ((m_show_flags&FLAG_SHOW_SCALE_BOTTOM)!=0) -#define IS_SHOW_GRID ((m_show_flags&FLAG_SHOW_GRID) !=0) -#define IS_SHOW_DESCRIPTORS ((m_show_flags&FLAG_SHOW_DESCRIPTORS) !=0) -#define IS_SHOW_VALUE ((m_show_flags&FLAG_SHOW_VALUE) !=0) -#define IS_SHOW_PERCENT ((m_show_flags&FLAG_SHOW_PERCENT) !=0) -//+------------------------------------------------------------------+ -//| Class CChartCanvas | -//| Usage: base class for graphical charts | -//+------------------------------------------------------------------+ -class CChartCanvas : public CCanvas - { -protected: - //--- colors - uint m_color_background; - uint m_color_border; - uint m_color_text; - uint m_color_grid; - //--- adjusted parameters - uint m_max_data; - uint m_max_descr_len; - uint m_allowed_show_flags; - uint m_show_flags; - ENUM_ALIGNMENT m_legend_alignment; - uint m_threshold_drawing; - bool m_accumulative; - //--- parameters for scales and grid - double m_v_scale_min; - double m_v_scale_max; - uint m_num_grid; - int m_scale_digits; - //--- data - int m_data_offset; - uint m_data_total; - CArray *m_data; - CArrayInt m_colors; - CArrayString m_descriptors; - //--- - CArrayInt m_index; - uint m_index_size; - double m_sum; - double m_others; - uint m_max_descr_width; - uint m_max_value_width; - //--- variables - CRect m_data_area; - //--- variables for scaling and scales - double m_scale_x; - int m_x_min; - int m_x_0; - int m_x_max; - int m_dx_grid; - double m_scale_y; - int m_y_min; - int m_y_0; - int m_y_max; - int m_dy_grid; - string m_scale_text[]; - -public: - CChartCanvas(void); - ~CChartCanvas(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - //--- colors - uint ColorBackground(void) const { return(m_color_background); } - void ColorBackground(const uint value); - uint ColorBorder(void) const { return(m_color_border); } - void ColorBorder(const uint value); - uint ColorText(void) const { return(m_color_text); } - void ColorText(const uint value); - uint ColorGrid(void) const { return(m_color_grid); } - void ColorGrid(const uint value) { m_color_grid=value; } - //--- adjusted parameters - uint MaxData(void) const { return(m_max_data); } - void MaxData(const uint value); - uint MaxDescrLen(void) const { return(m_max_descr_len); } - void MaxDescrLen(const uint value); - //--- show flags - void AllowedShowFlags(const uint flags); - uint ShowFlags(void) const { return(m_show_flags); } - void ShowFlags(const uint flags); - bool IsShowLegend(void) const { return(IS_SHOW_LEGEND); } - bool IsShowScaleLeft(void) const { return(IS_SHOW_SCALE_LEFT); } - bool IsShowScaleRight(void) const { return(IS_SHOW_SCALE_RIGHT); } - bool IsShowScaleTop(void) const { return(IS_SHOW_SCALE_TOP); } - bool IsShowScaleBottom(void) const { return(IS_SHOW_SCALE_BOTTOM); } - bool IsShowGrid(void) const { return(IS_SHOW_GRID); } - bool IsShowDescriptors(void) const { return(IS_SHOW_DESCRIPTORS); } - bool IsShowPercent(void) const { return(IS_SHOW_PERCENT); } - void ShowLegend(const bool flag=true); - void ShowScaleLeft(const bool flag=true); - void ShowScaleRight(const bool flag=true); - void ShowScaleTop(const bool flag=true); - void ShowScaleBottom(const bool flag=true); - void ShowGrid(const bool flag=true); - void ShowDescriptors(const bool flag=true); - void ShowValue(const bool flag=true); - void ShowPercent(const bool flag=true); - void LegendAlignment(const ENUM_ALIGNMENT value); - void Accumulative(const bool flag=true); - //--- for scales and grid - double VScaleMin(void) const { return(m_v_scale_min); } - void VScaleMin(const double value); - double VScaleMax(void) const { return(m_v_scale_max); } - void VScaleMax(const double value); - uint NumGrid(void) const { return(m_num_grid); } - void NumGrid(const uint value); - void VScaleParams(const double max,const double min,const uint grid); - //--- state - int DataOffset(void) const { return(m_data_offset); } - void DataOffset(const int value); - //--- data - uint DataTotal(void) const { return(m_data_total); } - bool DescriptorUpdate(const uint pos,const string descr); - bool ColorUpdate(const uint pos,const uint clr); - -protected: - virtual void ValuesCheck(void); - virtual void Redraw(void); - virtual void DrawBackground(void); - virtual void DrawLegend(void); - int DrawLegendVertical(const int w,const int h); - int DrawLegendHorizontal(const int w,const int h); - virtual void CalcScales(void); - virtual void DrawScales(void); - virtual int DrawScaleLeft(const bool draw=true); - virtual int DrawScaleRight(const bool draw=true); - virtual int DrawScaleTop(const bool draw=true); - virtual int DrawScaleBottom(const bool draw=true); - virtual void DrawGrid(void); - virtual void DrawDescriptors(void) {} - virtual void DrawChart(void); - virtual void DrawData(const uint idx=0) {} - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChartCanvas::CChartCanvas(void) : m_color_background(XRGB(0xFF,0xFF,0xFF)), - m_color_border(XRGB(0x9F,0x9F,0x9F)), - m_color_text(XRGB(0x3F,0x3F,0x3F)), - m_color_grid(XRGB(0xCF,0xCF,0xCF)), - m_max_data(10), - m_max_descr_len(10), - m_allowed_show_flags(FLAGS_SHOW_ALL), - m_show_flags(FLAG_SHOW_NONE), - m_legend_alignment(ALIGNMENT_BOTTOM), - m_threshold_drawing(2), - m_accumulative(false), - m_data_offset(0), - m_data_total(0), - m_data(NULL), - m_v_scale_min(0.0), - m_v_scale_max(10.0), - m_num_grid(5), - m_scale_digits(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChartCanvas::~CChartCanvas(void) - { - if(m_data!=NULL) - delete m_data; - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CChartCanvas::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- call method of parent class - if(!CCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- set font - FontSet("Tahoma",-100); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Sets background color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorBackground(const uint value) - { - m_color_background=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets border color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorBorder(const uint value) - { - m_color_border=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets text color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorText(const uint value) - { - m_color_text=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets maximum amount of data | -//+------------------------------------------------------------------+ -void CChartCanvas::MaxData(const uint value) - { -//--- check - if((value==0) || (m_data_total==value)) - return; -//--- save - m_max_data=value; - if(m_data_total>m_max_data) - { - m_data_total=value; - m_colors.Resize(value); - m_descriptors.Resize(value); - } - } -//+------------------------------------------------------------------+ -//| Sets maximum length of descriptor | -//+------------------------------------------------------------------+ -void CChartCanvas::MaxDescrLen(const uint value) - { - m_max_descr_len=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets allowed visibility flags | -//+------------------------------------------------------------------+ -void CChartCanvas::AllowedShowFlags(const uint flags) - { - m_allowed_show_flags=flags; - m_show_flags&=m_allowed_show_flags; - } -//+------------------------------------------------------------------+ -//| Sets visibility flags | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowFlags(const uint flags) - { - m_show_flags=flags&m_allowed_show_flags; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for "legend" | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowLegend(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_LEGEND)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_LEGEND; - else - m_show_flags&=~FLAG_SHOW_LEGEND; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for left scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleLeft(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_LEFT)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_LEFT; - else - m_show_flags&=~FLAG_SHOW_SCALE_LEFT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for right scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleRight(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_RIGHT)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_RIGHT; - else - m_show_flags&=~FLAG_SHOW_SCALE_RIGHT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for top scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleTop(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_TOP)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_TOP; - else - m_show_flags&=~FLAG_SHOW_SCALE_TOP; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for bottom scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleBottom(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_BOTTOM)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_BOTTOM; - else - m_show_flags&=~FLAG_SHOW_SCALE_BOTTOM; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for grid | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowGrid(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_GRID)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_GRID; - else - m_show_flags&=~FLAG_SHOW_GRID; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for descriptors | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowDescriptors(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_DESCRIPTORS)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_DESCRIPTORS; - else - m_show_flags&=~FLAG_SHOW_DESCRIPTORS; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for value | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowValue(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_VALUE)!=0) - { - if(flag) - { - m_show_flags|=FLAG_SHOW_VALUE; - m_show_flags&=~FLAG_SHOW_PERCENT; - } - else - m_show_flags&=~FLAG_SHOW_VALUE; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for percentage | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowPercent(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_PERCENT)!=0) - { - if(flag) - { - m_show_flags|=FLAG_SHOW_PERCENT; - m_show_flags&=~FLAG_SHOW_VALUE; - } - else - m_show_flags&=~FLAG_SHOW_PERCENT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets legend alignment | -//+------------------------------------------------------------------+ -void CChartCanvas::LegendAlignment(const ENUM_ALIGNMENT value) - { - m_legend_alignment=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets accumulative flag | -//+------------------------------------------------------------------+ -void CChartCanvas::Accumulative(const bool flag=true) - { - m_accumulative=flag; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets lower limit for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleMin(const double value) - { -//--- check - if(value==m_v_scale_max) - return; -//--- save - m_v_scale_min=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets upper limit for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleMax(const double value) - { - if(value==m_v_scale_min) - return; -//--- save - m_v_scale_max=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets number of vertical scale divisions | -//+------------------------------------------------------------------+ -void CChartCanvas::NumGrid(const uint value) - { -//--- check - if(value==0) - return; -//--- save - m_num_grid=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets parameters for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleParams(const double max,const double min,const uint grid) - { -//--- check - if(grid==0) - return; - if(max<=min) - return; -//--- save - m_v_scale_max=max; - m_v_scale_min=min; - m_num_grid =grid; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets data offset | -//+------------------------------------------------------------------+ -void CChartCanvas::DataOffset(const int value) - { - m_data_offset=value; -//--- redraw - Redraw(); - } -//+------------------------------------------------------------------+ -//| Updates parameter descriptor only (in specified position) | -//+------------------------------------------------------------------+ -bool CChartCanvas::DescriptorUpdate(const uint pos,const string descr) - { -//--- update - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates parameter color only (in specified position) | -//+------------------------------------------------------------------+ -bool CChartCanvas::ColorUpdate(const uint pos,const uint clr) - { -//--- update - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Checks values for insignificance | -//+------------------------------------------------------------------+ -void CChartCanvas::ValuesCheck(void) - { - string text; - uint w,h; -//--- clear - m_max_value_width=0; - m_sum =0; - m_others =0; - m_index_size =0; - m_index.Clear(); -//--- check - if(m_data==NULL) - return; - if(m_data.Type()==TYPE_DOUBLE) - { - //--- single-series chart - //--- calculate sum of all values - for(uint i=0;im_height) - { - cols++; - rows=(int)m_index_size/cols; - if((int)m_index_size%cols!=0) - rows++; - } -//--- draw - int x0=(m_legend_alignment==ALIGNMENT_RIGHT) ? width-w*cols+h : h; - int x=0; - int y =-h/2; - int i; - if(m_data_total==m_index_size) - { - for(i=0;i<(int)m_data_total;i++,x+=w) - { - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[i]); - TextOut(x+h,y," - "+m_descriptors[i],m_color_text); - } - } - else - { - for(i=0;i<(int)m_index_size;i++,x+=w) - { - int index=m_index[i]; - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[index]); - TextOut(x+h,y," - "+m_descriptors[index],m_color_text); - } - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,COLOR2RGB(clrBlack)); - TextOut(x+h,y," - Others",m_color_text); - } -//--- width - return(w*cols); - } -//+------------------------------------------------------------------+ -//| Draw horizontal "legend" | -//+------------------------------------------------------------------+ -int CChartCanvas::DrawLegendHorizontal(const int w,const int h) - { - int width =m_data_area.Width(); - int height=m_data_area.Height(); - int rows =1; - int cols =(int)m_index_size; -//--- calculate - while(w*cols>m_width) - { - rows++; - cols=(int)m_index_size/rows; - if((int)m_index_size%rows!=0) - cols++; - } -//--- draw - int dx=width/(cols+1); - int x =dx-w/2+h; - int dy=(int)(1.5*h); - int y =(m_legend_alignment==ALIGNMENT_BOTTOM) ? height-dy*(rows+1) : -h/2; - int i; - if(m_data_total==m_index_size) - { - for(i=0;i<(int)m_data_total;i++,x+=dx) - { - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[i]); - TextOut(x+h,y," - "+m_descriptors[i],m_color_text); - } - } - else - { - for(i=0;i<(int)m_index_size;i++,x+=dx) - { - int index=m_index[i]; - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[index]); - TextOut(x+h,y," - "+m_descriptors[index],m_color_text); - } - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,COLOR2RGB(clrBlack)); - TextOut(x+h,y," - Others",m_color_text); - } -//--- height - return(dy*(rows+1)); - } -//+------------------------------------------------------------------+ -//| Calculates coordinates of scales | -//+------------------------------------------------------------------+ -void CChartCanvas::CalcScales(void) - { - int width =m_data_area.Width(); - int height=m_data_area.Height(); -//--- limits - m_y_max=m_data_area.top+DrawScaleTop(false); - m_y_min=m_data_area.bottom-DrawScaleBottom(false); -//--- additional - m_dy_grid=(int)((m_y_min-m_y_max)/m_num_grid); - m_y_max+=(int)(((m_y_min-m_y_max)-m_dy_grid*m_num_grid)/2); - m_y_min=(int)(m_y_max+m_dy_grid*m_num_grid); -//--- normalize - if(m_v_scale_min>=0.0) - m_y_0=m_y_min; - else - { - if(m_v_scale_max<=0.0) - m_y_0=m_y_max; - else - m_y_0=(int)(m_y_max+(m_y_min-m_y_max)*m_v_scale_max/(m_v_scale_max-m_v_scale_min)); - } -//--- scale - m_scale_y=(m_v_scale_max!=m_v_scale_min) ? (m_y_min-m_y_max)/(m_v_scale_max-m_v_scale_min) : 1; -//--- labels on scale - if(ArraySize(m_scale_text)!=m_num_grid+1 && ArrayResize(m_scale_text,m_num_grid+1)==-1) - return; - double val=m_v_scale_min; - double dval=(m_v_scale_max-m_v_scale_min)/m_num_grid; - for(uint i=0;i<=m_num_grid;i++,val+=dval) - m_scale_text[i]=DoubleToString(val,m_scale_digits); - } -//+------------------------------------------------------------------+ -//| Redraws scales | -//+------------------------------------------------------------------+ -void CChartCanvas::DrawScales(void) - { -//--- recalculate - CalcScales(); -//--- redraw scales - if(IS_SHOW_SCALE_LEFT) - DrawScaleLeft(); - if(IS_SHOW_SCALE_RIGHT) - DrawScaleRight(); - if(IS_SHOW_SCALE_TOP) - DrawScaleTop(); - if(IS_SHOW_SCALE_BOTTOM) - DrawScaleBottom(); - } -//+------------------------------------------------------------------+ -//| Redraws left scale | -//+------------------------------------------------------------------+ -int CChartCanvas::DrawScaleLeft(const bool draw) - { -//--- check flag - if(!IS_SHOW_SCALE_LEFT) - return(0); -//--- variables - int x1=m_data_area.left; - int x2; - int y=m_y_min; -//--- calculate scale width - int size=0; - for(uint i=0;i<=m_num_grid;i++) - { - if(size -//+------------------------------------------------------------------+ -//| Class CHistogramChart | -//| Usage: generates histogram chart | -//+------------------------------------------------------------------+ -class CHistogramChart : public CChartCanvas - { -private: - //--- colors - uint m_fill_brush[]; - //--- adjusted parameters - bool m_gradient; - uint m_bar_gap; - uint m_bar_min_size; - uint m_bar_border; - //--- data - CArrayObj *m_values; - -public: - CHistogramChart(void); - ~CHistogramChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE); - //--- adjusted parameters - void Gradient(const bool flag=true) { m_gradient=flag; } - void BarGap(const uint value) { m_bar_gap=value; } - void BarMinSize(const uint value) { m_bar_min_size=value; } - void BarBorder(const uint value) { m_bar_border=value; } - //--- data - bool SeriesAdd(const double &value[],const string descr="",const uint clr=0); - bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0); - bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0); - bool SeriesDelete(const uint pos); - bool ValueUpdate(const uint series,const uint pos,double value); - -protected: - virtual void DrawData(const uint idx); - void DrawBar(const int x,const int y,const int w,const int h,const uint clr); - void GradientBrush(const int size,const uint fill_clr); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CHistogramChart::CHistogramChart(void) : m_gradient(true), - m_bar_gap(3), - m_bar_min_size(5), - m_bar_border(0) - { - ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CHistogramChart::~CHistogramChart(void) - { - if(ArraySize(m_fill_brush)!=0) - ArrayFree(m_fill_brush); - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CHistogramChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayObj)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesAdd(const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); -//--- add - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Add(arr)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); - if(pos>=m_data_total) - return(false); -//--- insert - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Insert(arr,pos)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(pos>=m_data_total) - return(false); - CArrayDouble *data=m_values.At(pos); - if(data==NULL) - return(false); -//--- update - if(!data.AssignArray(value)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesDelete(const uint pos) - { -//--- check - if(pos>=m_data_total && m_data_total!=0) - return(false); -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_colors.Delete(pos)) - return(false); - if(!m_descriptors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates element in data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::ValueUpdate(const uint series,const uint pos,double value) - { - CArrayDouble *data=m_values.At(series); -//--- check - if(data==NULL) - return(false); -//--- update - if(!data.Update(pos,value)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Draws histogram | -//+------------------------------------------------------------------+ -void CHistogramChart::DrawData(const uint idx) - { - double value=0.0; -//--- check - CArrayDouble *data=m_values.At(idx); - if(data==NULL) - return; - int total=data.Total(); - if(total==0 || (int)idx>=total) - return; -//--- calculate - int x1=m_data_area.left; - int x2=m_data_area.right; - int dx=(x2-x1)/total; - uint clr=m_colors[idx]; - uint w=dx/m_data_total; - if(w0) - { - y=(m_y_0-(int)(value*m_scale_y)); - h=m_y_0-y; - } - else - { - y=m_y_0; - h=-(int)(value*m_scale_y); - } - DrawBar(x,y,w,h,clr); - //--- draw text of value - if(IS_SHOW_VALUE) - { - string text =DoubleToString(value,2); - int width=(int)(TextWidth(text)+w); - if(value>0) - { - if(width>y-m_y_max) - TextOut(x+w/2,y+w,text,m_color_text,TA_RIGHT|TA_VCENTER); - else - TextOut(x+w/2,y-w,text,m_color_text,TA_LEFT|TA_VCENTER); - } - else - { - if(width>m_y_min-y-h) - TextOut(x+w/2,y+h-w,text,m_color_text,TA_LEFT|TA_VCENTER); - else - TextOut(x+w/2,y+h+w,text,m_color_text,TA_RIGHT|TA_VCENTER); - } - } - } - if(IS_SHOW_VALUE) - FontSet(fontname,fontsize,fontflags,fontangle); - } -//+------------------------------------------------------------------+ -//| Draws bar | -//+------------------------------------------------------------------+ -void CHistogramChart::DrawBar(const int x,const int y,const int w,const int h,const uint clr) - { -//--- draw bar - if(!m_gradient || ArraySize(m_fill_brush)>1; - if((r&1)==0) - i1--; - //--- calculate - while(dy>=dx) - { - clr=fill_clr; - dclr=GETRGB(XRGB((r-dy)*GETRGBR(clr)/r,(r-dy)*GETRGBG(clr)/r,(r-dy)*GETRGBB(clr)/r)); - clr-=dclr; - m_fill_brush[i1]=clr; - m_fill_brush[i2]=clr; - //--- - if(f>=0) - { - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - if(--i1<0) - break; - i2++; - dd_x+=2; - f+=dd_x; - } - } - else - ArrayFree(m_fill_brush); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Charts/LineChart.mqh b/Include/Canvas/Charts/LineChart.mqh deleted file mode 100644 index c81e9e3..0000000 --- a/Include/Canvas/Charts/LineChart.mqh +++ /dev/null @@ -1,383 +0,0 @@ -//+------------------------------------------------------------------+ -//| LineChart.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ChartCanvas.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CLineChart | -//| Usage: generates line chart | -//+------------------------------------------------------------------+ -class CLineChart : public CChartCanvas - { -private: - //--- data - CArrayObj *m_values; - //--- adjusted parameters - bool m_filled; - -public: - CLineChart(void); - ~CLineChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE); - //--- adjusted parameters - void Filled(const bool flag=true) { m_filled=flag; } - //--- set up - bool SeriesAdd(const double &value[],const string descr="",const uint clr=0); - bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0); - bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0); - bool SeriesDelete(const uint pos); - bool ValueUpdate(const uint series,const uint pos,double value); - -protected: - virtual void DrawChart(void); - virtual void DrawData(const uint index=0); - -private: - double CalcArea(const uint index); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CLineChart::CLineChart(void) : m_filled(false) - { - ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLineChart::~CLineChart(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CLineChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayObj)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesAdd(const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); -//--- add - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Add(arr)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); - if(pos>=m_data_total) - return(false); -//--- insert - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Insert(arr,pos)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(pos>=m_data_total) - return(false); - CArrayDouble *data=m_values.At(pos); - if(data==NULL) - return(false); -//--- update - if(!data.AssignArray(value)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesDelete(const uint pos) - { -//--- check - if(pos>=m_data_total && m_data_total!=0) - return(false); -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_colors.Delete(pos)) - return(false); - if(!m_descriptors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates element in data series | -//+------------------------------------------------------------------+ -bool CLineChart::ValueUpdate(const uint series,const uint pos,double value) - { - CArrayDouble *data=m_values.At(series); -//--- check - if(data==NULL) - return(false); -//--- update - if(!data.Update(pos,value)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Redraws data | -//+------------------------------------------------------------------+ -void CLineChart::DrawChart(void) - { - if(m_filled) - { - //--- calculate areas of filling - double s[]; - ArrayResize(s,m_data_total); - ArrayInitialize(s,0); - for(uint i=0;im_y_0 && y2m_y_0)) - { - //--- draw two triangles - int x3; - if(y1>y2) - { - x3=x+dx*(y1-m_y_0)/(y1-y2); - FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]); - FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]); - } - else - { - x3=x+dx*(m_y_0-y1)/(y2-y1); - FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]); - FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]); - } - continue; - } - if(y1y2) - FillTriangle(x,y1,x+dx,y2,x+dx,y1,(uint)m_colors[index]); - if(y1m_y_0 || y2>m_y_0) - { - if(y1y2) - { - FillTriangle(x,y1,x+dx,y2,x,y2,(uint)m_colors[index]); - y1=y2; - } - } - FillRectangle(x,m_y_0,x+dx,y1,(uint)m_colors[index]); - } - else - LineAA(x,y1,x+dx,y2,(uint)m_colors[index],STYLE_SOLID); - } - } -//+------------------------------------------------------------------+ -//| Area of filling | -//+------------------------------------------------------------------+ -double CLineChart::CalcArea(const uint index) - { - double area =0; - double value=0; - int dx =100; -//--- - CArrayDouble *data=m_values.At(index); - if(data==NULL) - return(0); - int total=data.Total(); - if(total<=1) - return(0); - int y1=0; - int y2=(int)(m_y_0-data[0]*m_scale_y); - for(int i=0;im_y_0 && y2m_y_0)) - { - //--- line of values crosses the Y axis - int x; - if(y1>y2) - { - //--- from the bottom up - x=dx*(y1-m_y_0)/(y1-y2); - //--- add area of lower triangle - area+=x*(y1-m_y_0)/2; - //--- add area of upper triangle - area+=(dx-x)*(m_y_0-y2)/2; - } - else - { - //--- from top down - x=dx*(m_y_0-y1)/(y2-y1); - //--- add area of upper triangle - area+=x*(m_y_0-y1)/2; - //--- add area of lower triangle - area+=(dx-x)*(y2-m_y_0)/2; - } - continue; - } - if(y1y2) - { - //--- add area of triangle - area+=dx*(y1-y2)/2; - //--- add area of rectangle - area+=dx*(m_y_0-y2); - } - if(y1m_y_0 || y2>m_y_0) - { - //--- both values are less than zero - if(y1y2) - { - //--- add area of triangle - area+=dx*(y1-y2)/2; - //--- add area of rectangle - area+=dx*(y2-m_y_0); - } - } - } -//--- - return(area); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Charts/PieChart.mqh b/Include/Canvas/Charts/PieChart.mqh deleted file mode 100644 index 79be4d1..0000000 --- a/Include/Canvas/Charts/PieChart.mqh +++ /dev/null @@ -1,414 +0,0 @@ -//+------------------------------------------------------------------+ -//| PieChart.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ChartCanvas.mqh" -//+------------------------------------------------------------------+ -//| Class CPieChart | -//| Usage: generates pie chart | -//+------------------------------------------------------------------+ -class CPieChart : public CChartCanvas - { -private: - //--- data - CArrayDouble *m_values; - //--- for draw - int m_x0; - int m_y0; - int m_r; - -public: - CPieChart(void); - ~CPieChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - //--- data - bool SeriesSet(const double &value[],const string &text[],const uint &clr[]); - bool ValueAdd(const double value,const string descr="",const uint clr=0); - bool ValueInsert(const uint pos,const double value,const string descr="",const uint clr=0); - bool ValueUpdate(const uint pos,const double value,const string descr=NULL,const uint clr=0); - bool ValueDelete(const uint pos); - -protected: - virtual void DrawChart(void); - void DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr); - string LabelMake(const string text,const double value,const bool to_left); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CPieChart::CPieChart(void) - { - uint flags=FLAG_SHOW_LEGEND|FLAG_SHOW_DESCRIPTORS|FLAG_SHOW_VALUE|FLAG_SHOW_PERCENT; - AllowedShowFlags(flags); - ShowFlags(flags); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPieChart::~CPieChart(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CPieChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayDouble)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Sets displayed parameters | -//+------------------------------------------------------------------+ -bool CPieChart::SeriesSet(const double &value[],const string &text[],const uint &clr[]) - { -//--- !!! user is responsible for correct filling of arrays !!! -//--- check - if(m_values==NULL) - return(false); -//--- set - if(!m_values.AssignArray(value)) - return(false); - if(!m_descriptors.AssignArray(text)) - return(false); - if(!m_colors.AssignArray(clr)) - return(false); - m_data_total=m_values.Total(); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds displayed parameter (to the end) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueAdd(const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- add - if(!m_values.Add(value)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts displayed parameter (to specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueInsert(const uint pos,const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- insert - if(!m_values.Insert(value,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates displayed parameter (in specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueUpdate(const uint pos,const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- update - if(!m_values.Update(pos,value)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes displayed parameter (from specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueDelete(const uint pos) - { -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_descriptors.Delete(pos)) - return(false); - if(!m_colors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Draws | -//+------------------------------------------------------------------+ -void CPieChart::DrawChart(void) - { -//--- check - if(m_data_total==0) - return; -//--- variables - string text=""; - double angle=M_PI*(m_data_offset%360)/180; - int width,height; - int dw=0; - int dh=0; - int index; - CPoint p0[]; - CPoint p1[]; -//--- calculate geometry - width =(m_data_area.Width()<<3)/10; - height=(m_data_area.Height()<<3)/10; - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - dw=(int)m_max_value_width; - else - { - if(IS_SHOW_PERCENT) - dw=TextWidth("100.00%"); - } - } - else - { - if(IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - dw=(int)m_max_value_width+TextWidth(" ()"); - else - { - if(IS_SHOW_PERCENT) - dw=TextWidth(" (100.00%)"); - } - dw+=(int)m_max_descr_width; - } - } -//--- pie chart will always be round - width -=2*dw+10; - height-=20; - m_x0=m_data_area.left+(m_data_area.Width()>>1); - m_y0=m_data_area.top+(m_data_area.Height()>>1); - m_r =(((width>height) ? height : width)>>1); -//--- draw pie chart - if(ArrayResize(p0,m_data_total+1)==-1) - return; - if(m_data_total==1) - { - FillCircle(m_x0,m_y0,m_r,m_colors[0]); - Circle(m_x0,m_y0,m_r,m_color_border); - } - else - { - Circle(m_x0,m_y0,m_r,m_color_border); - for(uint i=0;i=m_x0) - { - x=p1[i].x+10; - y=p1[i].y; - index=m_index[i]; - text=LabelMake(m_descriptors[index],m_values[index],false); - if(text!="") - { - Line(p0[i].x,p0[i].y,p1[i].x,p1[i].y,m_color_border); - Line(p1[i].x,p1[i].y,x,y,m_color_border); - TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER); - } - } - if(m_data_total!=m_index_size) - { - index=(int)m_data_total-1; - if(p0[index].x>=m_x0) - { - x=p1[index].x+10; - y=p1[index].y; - text=LabelMake("Others",m_others,true); - TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER); - } - else - { - x=p1[index].x-10; - y=p1[index].y; - text=LabelMake("Others",m_others,false); - TextOut(x-5,y,text,m_color_text,TA_RIGHT|TA_VCENTER); - } - if(text!="") - { - Line(p0[index].x,p0[index].y,p1[index].x,p1[index].y,m_color_border); - Line(p1[index].x,p1[index].y,x,y,m_color_border); - } - } - ArrayFree(p1); - ArrayFree(p0); - } -//+------------------------------------------------------------------+ -//| Draw pie | -//+------------------------------------------------------------------+ -void CPieChart::DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr) - { -//--- draw arc - Arc(m_x0,m_y0,m_r,m_r,fi3,fi4,p[idx].x,p[idx].y,p[idx+1].x,p[idx+1].y,clr); -//--- variables - int x3=p[idx].x; - int y3=p[idx].y; - int x4=p[idx+1].x; - int y4=p[idx+1].y; -//--- draw radii - if(idx==0) - Line(m_x0,m_y0,x3,y3,clr); - if(idx!=m_data_total-1) - Line(m_x0,m_y0,x4,y4,clr); -//--- fill - double fi=(fi3+fi4)/2; - int xf=m_x0+(int)(0.99*m_r*cos(fi)); - int yf=m_y0-(int)(0.99*m_r*sin(fi)); - Fill(xf,yf,clr); -//--- for small pie - if(fi4-fi3<=M_PI_4) - Line(m_x0,m_y0,xf,yf,clr); - } -//+------------------------------------------------------------------+ -//| Make label for pie | -//+------------------------------------------------------------------+ -string CPieChart::LabelMake(const string text,const double value,const bool to_left) - { - string label=""; -//--- - if(to_left) - { - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - label=DoubleToString(value,2); - else - { - if(IS_SHOW_PERCENT) - label=DoubleToString(100*value/m_sum,2)+"%"; - } - } - else - { - label=text; - if(IS_SHOW_VALUE) - label+=" ("+DoubleToString(value,2)+")"; - else - { - if(IS_SHOW_PERCENT) - label+=" ("+DoubleToString(100*value/m_sum,2)+"%)"; - } - } - } - else - { - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - label=DoubleToString(value,2); - else - { - if(IS_SHOW_PERCENT) - label=DoubleToString(100*value/m_sum,2)+"%"; - } - } - else - { - if(IS_SHOW_VALUE) - label="("+DoubleToString(value,2)+") "; - else - { - if(IS_SHOW_PERCENT) - label="("+DoubleToString(100*value/m_sum,2)+"%) "; - } - label+=text; - } - } -//--- - return(label); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXBox.mqh b/Include/Canvas/DX/DXBox.mqh deleted file mode 100644 index fb50af5..0000000 --- a/Include/Canvas/DX/DXBox.mqh +++ /dev/null @@ -1,77 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXBox.mqh | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019, MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//--- -#include "DXMesh.mqh" -#include "DXMath.mqh" -#include "DXUtils.mqh" -//+------------------------------------------------------------------+ -//| 3D Box object | -//+------------------------------------------------------------------+ -class CDXBox : public CDXMesh - { -public: - CDXBox(); - ~CDXBox(); - //--- create bon in specified context - bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to); - //--- update box - bool Update(const DXVector3 &from,const DXVector3 &to); - -private: - //--- - void PrepareVertices(const DXVector3 &from,const DXVector3 &to); - }; -//+------------------------------------------------------------------+ -//| Class constructor | -//+------------------------------------------------------------------+ -void CDXBox::CDXBox() : CDXMesh() - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CDXBox::~CDXBox(void) - { - } -//+------------------------------------------------------------------+ -//| Create box in specified context | -//+------------------------------------------------------------------+ -bool CDXBox::Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to) - { -//--- release previous buffers - Shutdown(); -//--- - DXVertex vertices[]; - uint indices[]; -//--- prepare box vertices and indices - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - if(!DXComputeBox(from,to,vertices,indices)) - return(false); - for(int i=0; i - bool Create(int context_handle,const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY) - { - Shutdown(); - m_context=context_handle; - m_handle=DXBufferCreate(m_context,DX_BUFFER_VERTEX,vertices,start,count); - return(m_handle!=INVALID_HANDLE); - } - //+------------------------------------------------------------------+ - //| Render | - //+------------------------------------------------------------------+ - bool Render(uint start=0,uint count=WHOLE_ARRAY) - { - return(DXBufferSet(m_context,m_handle,start,count)); - } - //+------------------------------------------------------------------+ - //| Shutdown | - //+------------------------------------------------------------------+ - void Shutdown(void) - { - //--- relase handle - if(m_handle!=INVALID_HANDLE) - DXRelease(m_handle); - m_handle=INVALID_HANDLE; - } - }; -//+------------------------------------------------------------------+ -//| DX index buffer | -//+------------------------------------------------------------------+ -class CDXIndexBuffer : public CDXHandleShared - { -public: - //+------------------------------------------------------------------+ - //| Destructor | - //+------------------------------------------------------------------+ - virtual ~CDXIndexBuffer(void) - { - Shutdown(); - } - //+------------------------------------------------------------------+ - //| Create index buffer in specified context | - //+------------------------------------------------------------------+ - bool Create(int context_handle,const uint &indices[],uint start=0,uint count=WHOLE_ARRAY) - { - Shutdown(); - m_context=context_handle; - m_handle=DXBufferCreate(m_context,DX_BUFFER_INDEX,indices,start,count); - return(m_handle!=INVALID_HANDLE); - } - //+------------------------------------------------------------------+ - //| Render | - //+------------------------------------------------------------------+ - bool Render(uint start=0,uint count=WHOLE_ARRAY) - { - return(DXBufferSet(m_context,m_handle,start,count)); - } - //+------------------------------------------------------------------+ - //| Shutdown | - //+------------------------------------------------------------------+ - void Shutdown(void) - { - //--- relase handle - if(m_handle!=INVALID_HANDLE) - DXRelease(m_handle); - m_handle=INVALID_HANDLE; - } - }; -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXData.mqh b/Include/Canvas/DX/DXData.mqh deleted file mode 100644 index 252803c57692cc9d78ce97f6517147aecb616b20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4048 zcmeH}T~8BH5QgX4#Q(6VmncQl3o%|GRYOv#0x=}SY%1MKO~2gTQXAl}tIy1K+bun% z3uv<>=47|0d(L@h=ADl-zkijbENk+l0Ao!a$^*11%Y}F=9Tho}iqs|MS(lFdkW=Je z+(Dlm=}BKk5=u+Hffj?eDI4-sUdm(UA0#kopJc$!n12yp512RkH$;z+Z=NVl2+}(9 zyXcdjPt`R>VkBGUiy_(!$E>vF1+x=$>dfdxc4mZoW+zOPSOYnoG|e zO!irch?|(FNA$e9;rXs1cZjg|wP!aSvSZ69)vPghRT*2S3Xl&mWj~GMEvkxJ%IgW|S??v@EXhZy zQ5|>Xkf$blQnD(#VQ-b;%R9dBljYm&@tHlN-oCf@8+&itTlZDjsk=P6!C^Z)6?HTeROnqH15ckzKR4WFy3Fmr7CF_cK=g4ZBhX)95H_N1<`DOWgJ? z+7HN!fPZ?+u4>$un(AUH^>Q{lmC@v0)jr34OP#S2&_QJDQ=W5uDq>H*b5<+&?do!y zb4mB*Q(apiUWc}<+Gf$T0?yZ6wQCtlo!;rIani*u->UOfr2CagHS9_K^gokkyOU`q zWm&pyE@|&mx0|;~{Dnl))vQ_;eVPSL#(-NmSP*?lU$qP=Kza)l?VGe4a7S`JtcaSd unK`iTBV35pw4Bq - CDXVertexBuffer* VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY); - CDXIndexBuffer* IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY); - //--- create shader inputs - template - CDXInput* InputCreate(void); - CDXTexture* TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); - CDXTexture* TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); - -private: - //--- add resource to list - bool ResourceAdd(CDXObjectBase *resource); - //--- check resources - void ResourcesCheck(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CDXDispatcher::CDXDispatcher(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDXDispatcher::~CDXDispatcher(void) - { - Destroy(); - } -//+------------------------------------------------------------------+ -//| Create | -//+------------------------------------------------------------------+ -bool CDXDispatcher::Create(int context) - { -//--- check if context already exist - if(m_context!=INVALID_HANDLE) - return(false); -//--- save context - m_context=context; -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Destroy | -//+------------------------------------------------------------------+ -void CDXDispatcher::Destroy(void) - { -//--- release default shaders - if(m_default_ps) - { - m_default_ps.Release(); - m_default_ps=NULL; - } - if(m_default_vs) - { - m_default_vs.Release(); - m_default_vs=NULL; - } -//--- release and delete all DX resources - while(m_dx_resources.Next()) - { - CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); - resource.Release(); - } -//--- forget context - m_context=INVALID_HANDLE; - } -//+------------------------------------------------------------------+ -//| Check resources | -//+------------------------------------------------------------------+ -void CDXDispatcher::Check(void) - { -//--- - CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); -//--- release and delete all DX resources - while(CheckPointer(resource)!=POINTER_INVALID) - { - CDXHandleShared* next=(CDXHandleShared*)resource.Next(); - //--- if references count 1 or less, then only we hold the resource - if(resource.References()<=1) - resource.Release(); - //--- - resource=next; - } - } -//+------------------------------------------------------------------+ -//| Create default shader of specified type | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type) - { - switch(shader_type) - { - //--- default pixel shader - case DX_SHADER_PIXEL: - { - if(m_default_ps==NULL) - m_default_ps=ShaderCreateFromSource(DX_SHADER_PIXEL,ExtDefaultShaderPixel,"PSMain"); - return(m_default_ps); - } - //--- default vertex shader - case DX_SHADER_VERTEX: - { - if(m_default_vs==NULL) - { - m_default_vs=ShaderCreateFromSource(DX_SHADER_VERTEX,ExtDefaultShaderVertex,"VSMain"); - if(m_default_vs && !m_default_vs.LayoutSet()) - { - m_default_vs.Release(); - m_default_vs=NULL; - } - } - return(m_default_vs); - } - } -//--- return result - return(NULL); - } -//+------------------------------------------------------------------+ -//| Create new shader of specified type from file | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point) - { -//--- open source file - int file=FileOpen(path,FILE_READ); - if(file==INVALID_HANDLE) - return(NULL); -//--- check file size - uint size=(uint)FileSize(file); - FileClose(file); - if(size>16*1024*1024) - return(NULL); -//--- prepare buffer - char buffer[]; - ArrayResize(buffer,size); -//--- read file into buffer - int read=(int)FileLoad(path,buffer); - if(read<=0) - return(NULL); -//--- convert vuffer to string - string source=CharArrayToString(buffer,0,WHOLE_ARRAY,CP_UTF8); -//--- add shader by source - return(ShaderCreateFromSource(shader_type,source,entry_point)); - } -//+------------------------------------------------------------------+ -//| Create new shader of specified type from source code | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new shader - CDXShader* shader=new CDXShader(); - if(shader==NULL) - return(NULL); -//--- create shader - if(!shader.Create(m_context,shader_type,source,entry_point)) - { - shader.Release(); - return(NULL); - } -//--- add shader to resources list - if(!ResourceAdd(shader)) - { - shader.Release(); - return(NULL); - } -//--- return shader - return(shader); - } -//+------------------------------------------------------------------+ -//| Create vertex buffer | -//+------------------------------------------------------------------+ -template -CDXVertexBuffer* CDXDispatcher::VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new buffer - CDXVertexBuffer* buffer=new CDXVertexBuffer(); - if(buffer==NULL) - return(NULL); -//--- create buffer - if(!buffer.Create(m_context,vertices,start,count)) - { - buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(buffer)) - { - buffer.Release(); - return(NULL); - } -//--- return buffer - return(buffer); - } -//+------------------------------------------------------------------+ -//| Create vertex buffer | -//+------------------------------------------------------------------+ -CDXIndexBuffer* CDXDispatcher::IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new buffer - CDXIndexBuffer* buffer=new CDXIndexBuffer(); - if(buffer==NULL) - return(NULL); -//--- create buffer - if(!buffer.Create(m_context,indicies,start,count)) - { - buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(buffer)) - { - buffer.Release(); - return(NULL); - } -//--- return input buffer - return(buffer); - } -//+------------------------------------------------------------------+ -//| Create shader input buffer | -//+------------------------------------------------------------------+ -template -CDXInput* CDXDispatcher::InputCreate(void) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new input buffer - CDXInput* input_buffer=new CDXInput(); - if(input_buffer==NULL) - return(NULL); -//--- create buffer - if(!input_buffer.Create(m_context)) - { - input_buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(input_buffer)) - { - input_buffer.Release(); - return(NULL); - } -//--- return shader - return(input_buffer); - } -//+------------------------------------------------------------------+ -//| Create texture from bitmap file | -//+------------------------------------------------------------------+ -CDXTexture* CDXDispatcher::TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new texture - CDXTexture* texture=new CDXTexture(); - if(texture==NULL) - return(NULL); -//--- create texture - if(!texture.Create(m_context,path,data_x,data_y,data_width,data_height)) - { - texture.Release(); - return(NULL); - } -//--- add texture to resources list - if(!ResourceAdd(texture)) - { - texture.Release(); - return(NULL); - } -//--- return shader - return(texture); - } -//+------------------------------------------------------------------+ -//| Create texture from raw data, only 32-bit pixel formats supported| -//+------------------------------------------------------------------+ -CDXTexture* CDXDispatcher::TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new texture - CDXTexture* texture=new CDXTexture(); - if(texture==NULL) - return(NULL); -//--- create texture - if(!texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height)) - { - texture.Release(); - return(NULL); - } -//--- add texture to resources list - if(!ResourceAdd(texture)) - { - texture.Release(); - return(NULL); - } -//--- return shader - return(texture); - } -//+------------------------------------------------------------------+ -//| Add DX resource | -//+------------------------------------------------------------------+ -bool CDXDispatcher::ResourceAdd(CDXObjectBase *resource) - { -//--- add resource - if(!CheckPointer(resource)) - return(false); -//--- - CDXObjectBase *last=&m_dx_resources; - while(CheckPointer(last.Next())!=POINTER_INVALID) - { - if(last==resource) - return(false); - //--- - last=last.Next(); - } -//--- - resource.Next(NULL); - resource.Prev(last); - last.Next(resource); - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXHandle.mqh b/Include/Canvas/DX/DXHandle.mqh deleted file mode 100644 index 598d5290fb053b175fc2ecc741191687cbd61daa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8568 zcmd^EYflqF6uqBK{0~z|Obzlf@q;CN;1w`Ij1Z0A2vCaEKClmn0{(RMoS9DdZfAC> zMaUM@lrG!ZnS0MY_uezp-@g`RQRZa60IxZDDoyPH__|ctwWWv58;lnuR z;Zgx!=U~Dy#?=vfk6w%oj6d0Z1u4nu2xDBvxelSTj|yWS5ut)~+9F<${M!E6QHHwpbX88+nOqf@r+MA@z;-y+ z?CO73!SYo~8ka1^qPwDJ(Kt$_4^FnxAJ1|yCkq*u8s7Y*er9#iip43FaFpv&{ed20 ze=?{_pYgoG4Aeh9;%%kC=>gyQ`ergkqVd!{!DW?OHLgy4R_1+%HRtyA++13CZ;PjcA7c9Zn=uZ-sw(QnV0O1C-N1{3R#uz zrZrSj?)H2?Wo(YI4?Kfjbse2EP;ausb4{Lp)ocuFcT)(S! zN3L3jHFwRbT%Ht^WhSx@)0h}omYlm8d$P$hEPBFz;!ak0ziz!W@Poe0%MX0Z6POrE zoPnp1PIZ)EMfxPeS-y!G99ruZ=_6oXj*N6Qe-@*822A{X^oqSJbXp;X4;eF_4s%FN z`nQ;wto2a7T4OiJQe2(`VFoj6yyhTZPr=@J6cUaauqrE;v$NU7MXy)JZ#8rFTqB;l zD^tSVZHr+HwRCRZACn&gclUu}p2{yOhqLyZx{4RO_7eFfGWr6aF%~o5*}eEXneX1+ z%-!%L_4l#xH@>S(GuPqc&ge=x)z3fW@l03FrD5++^jPvl7AL9OTvbh;O6!-ra}KAr zJO^lxQ#b~yt%cu*W8CQuYq-~Hd-Lb|&BmD5a LFe_%ouOoi|5JmNF diff --git a/Include/Canvas/DX/DXInput.mqh b/Include/Canvas/DX/DXInput.mqh deleted file mode 100644 index 39076685c173e4f375d8d34a46bd4f6fd2d02698..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4968 zcmeHKVQ&&a5PhFb{10bM%r(VQP5dB=i2;+E)Fz5Cej`^n^x^?}K+kI1pRT^yWqZ4O zAP@|>CguX{-QMoZzIktE`2DMnIu7u#0@nfV;tsv3;}XFRuQop7HAeV~8KyYI5Z~~b z_Aj^ar-d>1yFi8npSatU`#r`H9^ol!9KS)#XA$1g=9r@x6F%*5Jm6iYQxI zh|P?VPZ{s>bzM?fh;w3@Fl+2vT#%KTE%qM5DXAZQuE?2bLauq{t-7-At5$dQSq!6E zs{TYgk5r+EpAknneN*PdNGuEpCXEM(G+pGGF5^RRVLb8#JpY!{I_c0NQI3vit zw>pa#R`k!vlJOEA8XWBygbH`*BBc6`l)dl#Ud>C1sP66pRuY$^b~L5;GM43c9X{*4 zSnM8AFLG+b71vka!Vq2WG)?c`*N*TFAMg?<9JM)r%<(BlCwR4B$J>)lIz&mh zYsaRqR3n*X7uWx6QuK~G8sS`P6BQXdPX%~jMXJk+CiyMeFxT|R?wB^dcyYHi=W8-i zO7fM_T&WCyAI&KF2UX~8z!Rj@Y`j28ZeEdhma)~hb$R!^d%x4%Dvn!b|-xN$T= 1.0f) || (q.w == -1.0f)) - t = 1.0f; - else - t = (float)(acos(q.w)/sqrt(1.0f - q.w*q.w)); - out.x = t*q.x; - out.y = t*q.y; - out.z = t*q.z; - out.w = 0.0f; - } -//+------------------------------------------------------------------+ -//| Multiplies two quaternions. | -//+------------------------------------------------------------------+ -void DXQuaternionMultiply(DXQuaternion &pout,const DXQuaternion &pq1,const DXQuaternion &pq2) - { - DXQuaternion out; - out.x = pq2.w*pq1.x + pq2.x*pq1.w + pq2.y*pq1.z - pq2.z*pq1.y; - out.y = pq2.w*pq1.y - pq2.x*pq1.z + pq2.y*pq1.w + pq2.z*pq1.x; - out.z = pq2.w*pq1.z + pq2.x*pq1.y - pq2.y*pq1.x + pq2.z*pq1.w; - out.w = pq2.w*pq1.w - pq2.x*pq1.x - pq2.y*pq1.y - pq2.z*pq1.z; - pout = out; - } -//+------------------------------------------------------------------+ -//| Computes a unit length quaternion. | -//+------------------------------------------------------------------+ -void DXQuaternionNormalize(DXQuaternion &out,const DXQuaternion &q) - { - float norm = DXQuaternionLength(q); - if(!norm) - { - out.x = 0.0f; - out.y = 0.0f; - out.z = 0.0f; - out.w = 0.0f; - } - else - { - out.x = q.x/norm; - out.y = q.y/norm; - out.z = q.z/norm; - out.w = q.w/norm; - } - } -//+------------------------------------------------------------------+ -//| Rotates a quaternion about an arbitrary axis. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationAxis(DXQuaternion &out,const DXVector3 &v,float angle) - { - DXVector3 temp; - DXVec3Normalize(temp,v); - out.x = (float)sin(angle/2.0f)*temp.x; - out.y = (float)sin(angle/2.0f)*temp.y; - out.z = (float)sin(angle/2.0f)*temp.z; - out.w = (float)cos(angle/2.0f); - } -//+------------------------------------------------------------------+ -//| Builds a quaternion from a rotation matrix. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationMatrix(DXQuaternion &out,const DXMatrix &m) - { - float s; - float trace = m.m[0][0] + m.m[1][1] + m.m[2][2] + 1.0f; - if(trace>1.0f) - { - s = 2.0f*(float)sqrt(trace); - out.x = (m.m[1][2] - m.m[2][1])/s; - out.y = (m.m[2][0] - m.m[0][2])/s; - out.z = (m.m[0][1] - m.m[1][0])/s; - out.w = 0.25f*s; - } - else - { - int maxi = 0; - for(int i=1; i<3; i++) - { - if(m.m[i][i] > m.m[maxi][maxi]) - maxi = i; - } - switch(maxi) - { - case 0: - s = 2.0f*(float)sqrt(1.0f + m.m[0][0] - m.m[1][1] - m.m[2][2]); - out.x = 0.25f*s; - out.y = (m.m[0][1] + m.m[1][0])/s; - out.z = (m.m[0][2] + m.m[2][0])/s; - out.w = (m.m[1][2] - m.m[2][1])/s; - break; - - case 1: - s = 2.0f*(float)sqrt(1.0f + m.m[1][1] - m.m[0][0] - m.m[2][2]); - out.x = (m.m[0][1] + m.m[1][0])/s; - out.y = 0.25f*s; - out.z = (m.m[1][2] + m.m[2][1])/s; - out.w = (m.m[2][0] - m.m[0][2])/s; - break; - - case 2: - s = 2.0f*(float)sqrt(1.0f + m.m[2][2] - m.m[0][0] - m.m[1][1]); - out.x = (m.m[0][2] + m.m[2][0])/s; - out.y = (m.m[1][2] + m.m[2][1])/s; - out.z = 0.25f*s; - out.w = (m.m[0][1] - m.m[1][0])/s; - break; - } - } - } -//+------------------------------------------------------------------+ -//| Builds a quaternion with the given yaw, pitch, and roll. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationYawPitchRoll(DXQuaternion &out,float yaw,float pitch,float roll) - { - float syaw = (float)sin(yaw/2.0f); - float cyaw = (float)cos(yaw/2.0f); - float spitch = (float)sin(pitch/2.0f); - float cpitch = (float)cos(pitch/2.0f); - float sroll = (float)sin(roll/2.0f); - float croll = (float)cos(roll/2.0f); -//--- - out.x = syaw*cpitch*sroll + cyaw*spitch*croll; - out.y = syaw*cpitch*croll - cyaw*spitch*sroll; - out.z = cyaw*cpitch*sroll - syaw*spitch*croll; - out.w = cyaw*cpitch*croll + syaw*spitch*sroll; - } -//+------------------------------------------------------------------+ -//| Interpolates between two quaternions, using spherical linear | -//| interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSlerp(DXQuaternion &out,DXQuaternion &q1,DXQuaternion &q2,float t) - { - float temp = 1.0f - t; - float dot = DXQuaternionDot(q1,q2); - if(dot<0.0f) - { - t = -t; - dot = -dot; - } - if(1.0f-dot>0.001f) - { - float theta = (float)acos(dot); - temp = (float)sin(theta*temp)/(float)sin(theta); - t = (float)sin(theta*t)/(float)sin(theta); - } - out.x = temp*q1.x + t*q2.x; - out.y = temp*q1.y + t*q2.y; - out.z = temp*q1.z + t*q2.z; - out.w = temp*q1.w + t*q2.w; - } -//+------------------------------------------------------------------+ -//| Interpolates between quaternions, using spherical quadrangle | -//| interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSquad(DXQuaternion &pout,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3,DXQuaternion &pq4,float t) - { - DXQuaternion temp1,temp2; - DXQuaternionSlerp(temp1,pq1,pq4,t); - DXQuaternionSlerp(temp2,pq2,pq3,t); - DXQuaternionSlerp(pout,temp1,temp2,2.0f*t*(1.0f - t)); - } -//+------------------------------------------------------------------+ -//| add_diff | -//+------------------------------------------------------------------+ -DXQuaternion add_diff(const DXQuaternion &q1,const DXQuaternion &q2,const float add) - { - DXQuaternion temp; - temp.x = q1.x + add * q2.x; - temp.y = q1.y + add * q2.y; - temp.z = q1.z + add * q2.z; - temp.w = q1.w + add * q2.w; -//--- - return(temp); - } -//+------------------------------------------------------------------+ -//| Sets up control points for spherical quadrangle interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSquadSetup(DXQuaternion &paout,DXQuaternion &pbout,DXQuaternion &pcout,DXQuaternion &pq0,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3) - { - DXQuaternion q,temp1,temp2,temp3,zero; - DXQuaternion aout,cout; - zero.x = 0.0f; - zero.y = 0.0f; - zero.z = 0.0f; - zero.w = 0.0f; -//--- - if(DXQuaternionDot(pq0,pq1) < 0.0f) - temp2 = add_diff(zero,pq0,-1.0f); - else - temp2 = pq0; -//--- - if(DXQuaternionDot(pq1,pq2) < 0.0f) - cout = add_diff(zero,pq2,-1.0f); - else - cout = pq2; -//--- - if(DXQuaternionDot(cout,pq3) < 0.0f) - temp3 = add_diff(zero,pq3,-1.0f); - else - temp3 = pq3; -//--- - DXQuaternionInverse(temp1,pq1); - DXQuaternionMultiply(temp2,temp1,temp2); - DXQuaternionLn(temp2,temp2); - DXQuaternionMultiply(q,temp1,cout); - DXQuaternionLn(q,q); - temp1 = add_diff(temp2,q,1.0f); - temp1.x *= -0.25f; - temp1.y *= -0.25f; - temp1.z *= -0.25f; - temp1.w *= -0.25f; - DXQuaternionExp(temp1,temp1); - DXQuaternionMultiply(aout,pq1,temp1); -//--- - DXQuaternionInverse(temp1,cout); - DXQuaternionMultiply(temp2,temp1,pq1); - DXQuaternionLn(temp2,temp2); - DXQuaternionMultiply(q,temp1,temp3); - DXQuaternionLn(q,q); - temp1 = add_diff(temp2,q,1.0f); - temp1.x *= -0.25f; - temp1.y *= -0.25f; - temp1.z *= -0.25f; - temp1.w *= -0.25f; - DXQuaternionExp(temp1,temp1); - DXQuaternionMultiply(pbout,cout,temp1); - paout = aout; - pcout = cout; - } -//+------------------------------------------------------------------+ -//| Computes a quaternion's axis and angle of rotation. | -//+------------------------------------------------------------------+ -void DXQuaternionToAxisAngle(const DXQuaternion &pq,DXVector3 &paxis,float &pangle) - { -//--- paxis - paxis.x = pq.x; - paxis.y = pq.y; - paxis.z = pq.z; -//--- pangle - pangle = 2.0f*(float)acos(pq.w); - } -//+------------------------------------------------------------------+ -//| DXMatrixIdentity creates an identity matrix | -//+------------------------------------------------------------------+ -void DXMatrixIdentity(DXMatrix &out) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - if(i==j) - out.m[j,i]=1.0f; - else - out.m[j,i]=0.0f; - } - } -//+------------------------------------------------------------------+ -//| Determines if a matrix is an identity matrix. | -//+------------------------------------------------------------------+ -bool DXMatrixIsIdentity(DXMatrix &pm) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - if(i==j) - { - if(fabs(pm.m[j,i]-1.0f)>1e-6f) - return(false); - } - else - if(fabs(pm.m[j,i])>1e-6f) - return(false); - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Builds a 3D affine transformation matrix. | -//+------------------------------------------------------------------+ -//| This function calculates the affine transformation matrix | -//| with the following formula, with matrix concatenation | -//| evaluated in left-to-right order: | -//| Mout = Ms * (Mrc)-1 * Mr * Mrc * Mt | -//| where: | -//| Mout = output matrix (pOut) | -//| Ms = scaling matrix (Scaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (pRotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixAffineTransformation(DXMatrix &out,float scaling,const DXVector3 &rotationcenter,const DXQuaternion &rotation,const DXVector3 &translation) - { - DXMatrixIdentity(out); -//--- rotation - float temp00 = 1.0f - 2.0f*(rotation.y*rotation.y + rotation.z*rotation.z); - float temp01 = 2.0f * (rotation.x*rotation.y + rotation.z*rotation.w); - float temp02 = 2.0f * (rotation.x*rotation.z - rotation.y*rotation.w); - float temp10 = 2.0f * (rotation.x*rotation.y - rotation.z*rotation.w); - float temp11 = 1.0f - 2.0f*(rotation.x*rotation.x + rotation.z*rotation.z); - float temp12 = 2.0f * (rotation.y*rotation.z + rotation.x*rotation.w); - float temp20 = 2.0f * (rotation.x*rotation.z + rotation.y*rotation.w); - float temp21 = 2.0f * (rotation.y*rotation.z - rotation.x*rotation.w); - float temp22 = 1.0f - 2.0f*(rotation.x*rotation.x + rotation.y*rotation.y); -//--- scaling - out.m[0][0] = scaling*temp00; - out.m[0][1] = scaling*temp01; - out.m[0][2] = scaling*temp02; - out.m[1][0] = scaling*temp10; - out.m[1][1] = scaling*temp11; - out.m[1][2] = scaling*temp12; - out.m[2][0] = scaling*temp20; - out.m[2][1] = scaling*temp21; - out.m[2][2] = scaling*temp22; -//--- rotationcenter - out.m[3][0] = rotationcenter.x*(1.0f - temp00) - rotationcenter.y*temp10 - rotationcenter.z*temp20; - out.m[3][1] = rotationcenter.y*(1.0f - temp11) - rotationcenter.x*temp01 - rotationcenter.z*temp21; - out.m[3][2] = rotationcenter.z*(1.0f - temp22) - rotationcenter.x*temp02 - rotationcenter.y*temp12; -//--- translation - out.m[3][0] += translation.x; - out.m[3][1] += translation.y; - out.m[3][2] += translation.z; - } -//+------------------------------------------------------------------+ -//| Builds a 2D affine transformation matrix in the xy plane. | -//+------------------------------------------------------------------+ -//| This function calculates the affine transformation matrix | -//| with the following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| Mout = Ms * (Mrc)^(-1) * Mr * Mrc * Mt | -//| where: | -//| Mout = output matrix (pOut) | -//| Ms = scaling matrix (Scaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (Rotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixAffineTransformation2D(DXMatrix &out,float scaling,const DXVector2 &rotationcenter,float rotation,const DXVector2 &translation) - { - float s = (float)sin(rotation/2.0f); - float tmp1 = 1.0f - 2.0f*s*s; - float tmp2 = 2.0f*s*(float)cos(rotation/2.0f); -//--- - DXMatrixIdentity(out); - out.m[0][0] = scaling*tmp1; - out.m[0][1] = scaling*tmp2; - out.m[1][0] = -scaling*tmp2; - out.m[1][1] = scaling*tmp1; -//--- rotationcenter - float x = rotationcenter.x; - float y = rotationcenter.y; - out.m[3][0] = y*tmp2 - x*tmp1 + x; - out.m[3][1] = -x*tmp2 - y*tmp1 + y; -//--- translation - out.m[3][0] += translation.x; - out.m[3][1] += translation.y; - } -#define D3DERR_INVALIDCALL -2005530516 -//#define S_OK 0; -//+------------------------------------------------------------------+ -//| Breaks down a general 3D transformation matrix into its scalar, | -//| rotational, and translational components. | -//+------------------------------------------------------------------+ -int DXMatrixDecompose(DXVector3 &poutscale,DXQuaternion &poutrotation,DXVector3 &pouttranslation,const DXMatrix &pm) - { - DXMatrix normalized; - DXVector3 vec; -//--- Compute the scaling part - vec.x=pm.m[0][0]; - vec.y=pm.m[0][1]; - vec.z=pm.m[0][2]; - poutscale.x=DXVec3Length(vec); - vec.x=pm.m[1][0]; - vec.y=pm.m[1][1]; - vec.z=pm.m[1][2]; - poutscale.y=DXVec3Length(vec); - vec.x=pm.m[2][0]; - vec.y=pm.m[2][1]; - vec.z=pm.m[2][2]; - poutscale.z=DXVec3Length(vec); -//--- compute the translation part - pouttranslation.x=pm.m[3][0]; - pouttranslation.y=pm.m[3][1]; - pouttranslation.z=pm.m[3][2]; -//--- let's calculate the rotation now - if((poutscale.x == 0.0f) || (poutscale.y == 0.0f) || (poutscale.z == 0.0f)) - return(D3DERR_INVALIDCALL); -//--- - normalized.m[0][0]=pm.m[0][0]/poutscale.x; - normalized.m[0][1]=pm.m[0][1]/poutscale.x; - normalized.m[0][2]=pm.m[0][2]/poutscale.x; - normalized.m[1][0]=pm.m[1][0]/poutscale.y; - normalized.m[1][1]=pm.m[1][1]/poutscale.y; - normalized.m[1][2]=pm.m[1][2]/poutscale.y; - normalized.m[2][0]=pm.m[2][0]/poutscale.z; - normalized.m[2][1]=pm.m[2][1]/poutscale.z; - normalized.m[2][2]=pm.m[2][2]/poutscale.z; - DXQuaternionRotationMatrix(poutrotation,normalized); -//--- - return(0); - } -//+------------------------------------------------------------------+ -//| Returns the determinant of a matrix. | -//+------------------------------------------------------------------+ -float DXMatrixDeterminant(const DXMatrix &pm) - { - float t[3],v[4]; - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3]*pm.m[3][2]; - t[2] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3]*pm.m[2][2]; - v[0] = pm.m[1][1]*t[0] - pm.m[2][1] * t[1] + pm.m[3][1]*t[2]; - v[1] = -pm.m[1][0]*t[0] + pm.m[2][0] * t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[1][0]*pm.m[2][1] - pm.m[2][0]*pm.m[1][1]; - t[1] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0]*pm.m[1][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0]*pm.m[2][1]; - v[2] = pm.m[3][3]*t[0] - pm.m[2][3]*t[1] + pm.m[1][3]*t[2]; - v[3] = -pm.m[3][2]*t[0] + pm.m[2][2]*t[1] - pm.m[1][2]*t[2]; -//--- - return(pm.m[0][0]*v[0] + pm.m[0][1]*v[1] + pm.m[0][2]*v[2] + pm.m[0][3]*v[3]); - } -//+------------------------------------------------------------------+ -//| Calculates the inverse of a matrix. | -//+------------------------------------------------------------------+ -void DXMatrixInverse(DXMatrix &pout,float &pdeterminant,const DXMatrix &pm) - { - float t[3],v[16]; - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3]*pm.m[3][2]; - t[2] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3]*pm.m[2][2]; - v[0] = pm.m[1][1]*t[0] - pm.m[2][1]*t[1] + pm.m[3][1]*t[2]; - v[4] = -pm.m[1][0]*t[0] + pm.m[2][0]*t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[1][0]*pm.m[2][1] - pm.m[2][0]*pm.m[1][1]; - t[1] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0]*pm.m[1][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0]*pm.m[2][1]; - v[8] = pm.m[3][3]*t[0] - pm.m[2][3]*t[1] + pm.m[1][3]*t[2]; - v[12] = -pm.m[3][2]*t[0] + pm.m[2][2]*t[1] - pm.m[1][2]*t[2]; -//--- - float det = pm.m[0][0]*v[0] + pm.m[0][1]*v[4] + pm.m[0][2]*v[8] + pm.m[0][3]*v[12]; - if(det == 0.0f) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - pout.m[j,i]=0.0; - } - //--- - return; - } - if(pdeterminant) - pdeterminant = det; -//--- - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[0][2]*pm.m[3][3] - pm.m[0][3]*pm.m[3][2]; - t[2] = pm.m[0][2]*pm.m[2][3] - pm.m[0][3]*pm.m[2][2]; - v[1] = -pm.m[0][1]*t[0] + pm.m[2][1]*t[1] - pm.m[3][1]*t[2]; - v[5] = pm.m[0][0]*t[0] - pm.m[2][0]*t[1] + pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[0][0]*pm.m[2][1] - pm.m[2][0] * pm.m[0][1]; - t[1] = pm.m[3][0]*pm.m[0][1] - pm.m[0][0] * pm.m[3][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0] * pm.m[2][1]; - v[9] = -pm.m[3][3]*t[0] - pm.m[2][3]*t[1]- pm.m[0][3]*t[2]; - v[13] = pm.m[3][2]*t[0] + pm.m[2][2]*t[1] + pm.m[0][2]*t[2]; -//--- - t[0] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3] * pm.m[3][2]; - t[1] = pm.m[0][2]*pm.m[3][3] - pm.m[0][3] * pm.m[3][2]; - t[2] = pm.m[0][2]*pm.m[1][3] - pm.m[0][3] * pm.m[1][2]; - v[2] = pm.m[0][1]*t[0] - pm.m[1][1]*t[1] + pm.m[3][1]*t[2]; - v[6] = -pm.m[0][0]*t[0] + pm.m[1][0]*t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[0][0]*pm.m[1][1] - pm.m[1][0] * pm.m[0][1]; - t[1] = pm.m[3][0]*pm.m[0][1] - pm.m[0][0] * pm.m[3][1]; - t[2] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0] * pm.m[1][1]; - v[10] = pm.m[3][3]*t[0] + pm.m[1][3]*t[1] + pm.m[0][3]*t[2]; - v[14] = -pm.m[3][2]*t[0] - pm.m[1][2]*t[1] - pm.m[0][2]*t[2]; -//--- - t[0] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3] * pm.m[2][2]; - t[1] = pm.m[0][2]*pm.m[2][3] - pm.m[0][3] * pm.m[2][2]; - t[2] = pm.m[0][2]*pm.m[1][3] - pm.m[0][3] * pm.m[1][2]; - v[3] = -pm.m[0][1]*t[0] + pm.m[1][1]*t[1] - pm.m[2][1]*t[2]; - v[7] = pm.m[0][0]*t[0] - pm.m[1][0]*t[1] + pm.m[2][0]*t[2]; -//--- - v[11] = -pm.m[0][0]*(pm.m[1][1]*pm.m[2][3] - pm.m[1][3]*pm.m[2][1]) + - pm.m[1][0]*(pm.m[0][1]*pm.m[2][3] - pm.m[0][3]*pm.m[2][1]) - - pm.m[2][0]*(pm.m[0][1]*pm.m[1][3] - pm.m[0][3]*pm.m[1][1]); -//--- - v[15] = pm.m[0][0]*(pm.m[1][1]*pm.m[2][2] - pm.m[1][2]*pm.m[2][1]) - - pm.m[1][0]*(pm.m[0][1]*pm.m[2][2] - pm.m[0][2]*pm.m[2][1]) + - pm.m[2][0]*(pm.m[0][1]*pm.m[1][2] - pm.m[0][2]*pm.m[1][1]); -//--- - det = 1.0f/det; - for(int i=0; i<4; i++) - for(int j=0; j<4; j++) - pout.m[i][j] = v[4*i + j]*det; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed,look-at matrix. | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| | -//| zaxis = normal(At - Eye) | -//| xaxis = normal(cross(Up,zaxis)) | -//| yaxis = cross(zaxis,xaxis) | -//| | -//| xaxis.x yaxis.x zaxis.x 0 | -//| xaxis.y yaxis.y zaxis.y 0 | -//| xaxis.z yaxis.z zaxis.z 0 | -//| -dot(xaxis,eye) -dot(yaxis,eye) -dot(zaxis,eye) 1 | -//+------------------------------------------------------------------+ -void DXMatrixLookAtLH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up) - { - DXVector3 right,upn,vec; - DXVec3Subtract(vec,at,eye); - DXVec3Normalize(vec,vec); - DXVec3Cross(right,up,vec); - DXVec3Cross(upn,vec,right); - DXVec3Normalize(right,right); - DXVec3Normalize(upn,upn); -//--- - out.m[0][0] = right.x; - out.m[1][0] = right.y; - out.m[2][0] = right.z; - out.m[3][0] = -DXVec3Dot(right,eye); - out.m[0][1] = upn.x; - out.m[1][1] = upn.y; - out.m[2][1] = upn.z; - out.m[3][1] = -DXVec3Dot(upn,eye); - out.m[0][2] = vec.x; - out.m[1][2] = vec.y; - out.m[2][2] = vec.z; - out.m[3][2] = -DXVec3Dot(vec,eye); - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed, look-at matrix. | -//+------------------------------------------------------------------+ -//| This function uses the following formula to compute | -//| the returned matrix. | -//| | -//| zaxis = normal(Eye - At) | -//| xaxis = normal(cross(Up,zaxis)) | -//| yaxis = cross(zaxis,xaxis) | -//| | -//| xaxis.x yaxis.x zaxis.x 0 | -//| xaxis.y yaxis.y zaxis.y 0 | -//| xaxis.z yaxis.z zaxis.z 0 | -//| dot(xaxis,eye) dot(yaxis,eye) dot(zaxis,eye) 1 | -//+------------------------------------------------------------------+ -void DXMatrixLookAtRH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up) - { - DXVector3 right,upn,vec; - DXVec3Subtract(vec,at,eye); - DXVec3Normalize(vec,vec); - DXVec3Cross(right,up,vec); - DXVec3Cross(upn,vec,right); - DXVec3Normalize(right,right); - DXVec3Normalize(upn,upn); -//--- - out.m[0][0] = -right.x; - out.m[1][0] = -right.y; - out.m[2][0] = -right.z; - out.m[3][0] = DXVec3Dot(right,eye); - out.m[0][1] = upn.x; - out.m[1][1] = upn.y; - out.m[2][1] = upn.z; - out.m[3][1] = -DXVec3Dot(upn,eye); - out.m[0][2] = -vec.x; - out.m[1][2] = -vec.y; - out.m[2][2] = -vec.z; - out.m[3][2] = DXVec3Dot(vec,eye); - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Determines the product of two matrices. | -//+------------------------------------------------------------------+ -void DXMatrixMultiply(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2) - { - DXMatrix out= {}; - for(int i=0; i<4; i++) - { - for(int j=0; j<4; j++) - { - out.m[i][j] = pm1.m[i][0]*pm2.m[0][j] + pm1.m[i][1]*pm2.m[1][j] + pm1.m[i][2]*pm2.m[2][j] + pm1.m[i][3]*pm2.m[3][j]; - } - } - pout = out; - } -//+------------------------------------------------------------------+ -//| Calculates the transposed product of two matrices. | -//+------------------------------------------------------------------+ -void DXMatrixMultiplyTranspose(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2) - { - DXMatrix temp= {}; - for(int i = 0; i < 4; i++) - for(int j = 0; j < 4; j++) - temp.m[j][i] = pm1.m[i][0]*pm2.m[0][j] + pm1.m[i][1]*pm2.m[1][j] + pm1.m[i][2]*pm2.m[2][j] + pm1.m[i][3]*pm2.m[3][j]; - pout = temp; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoLH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/w; - pout.m[1][1] = 2.0f/h; - pout.m[2][2] = 1.0f/(zf - zn); - pout.m[3][2] = zn/(zn - zf); - } -//+------------------------------------------------------------------+ -//| Builds a customized,left-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/(r - l); - pout.m[1][1] = 2.0f/(t - b); - pout.m[2][2] = 1.0f/(zf -zn); - pout.m[3][0] = -1.0f -2.0f*l/(r - l); - pout.m[3][1] = 1.0f + 2.0f*t/(b - t); - pout.m[3][2] = zn/(zn -zf); - } -//+------------------------------------------------------------------+ -//| Builds a customized,right-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/(r - l); - pout.m[1][1] = 2.0f/(t - b); - pout.m[2][2] = 1.0f/(zn -zf); - pout.m[3][0] = -1.0f -2.0f*l/(r - l); - pout.m[3][1] = 1.0f + 2.0f*t/(b - t); - pout.m[3][2] = zn/(zn -zf); - } -//+------------------------------------------------------------------+ -//| Builds a right-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixOrthoRH function | -//| are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix: | -//| 2/w 0 0 0 | -//| 0 2/h 0 0 | -//| 0 0 1/(zn-zf) 0 | -//| 0 0 zn/(zn-zf) 1 | -//+------------------------------------------------------------------+ -void DXMatrixOrthoRH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); - pout.m[0][0] = 2.0f/w; - pout.m[1][1] = 2.0f/h; - pout.m[2][2] = 1.0f/(zn - zf); - pout.m[3][2] = zn/(zn - zf); - } -//+------------------------------------------------------------------+ -//| Builds a left-handed perspective projection matrix | -//| based on a field of view. | -//+------------------------------------------------------------------+ -//| This function computes the returned matrix as shown: | -//| xScale 0 0 0 | -//| 0 yScale 0 0 | -//| 0 0 zf/(zf-zn) 1 | -//| 0 0 -zn*zf/(zf-zn) 0 | -//| where: | -//| yScale = cot(fovY/2) | -//| xScale = yScale / aspect ratio | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveFovLH(DXMatrix &pout,float fovy,float aspect,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f/(aspect*(float)tan(fovy/2.0f)); - pout.m[1][1] = 1.0f/(float)tan(fovy/2.0f); - pout.m[2][2] = zf/(zf - zn); - pout.m[2][3] = 1.0f; - pout.m[3][2] = (zf*zn)/(zn - zf); - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed perspective projection matrix | -//| based on a field of view. | -//+------------------------------------------------------------------+ -//| This function computes the returned matrix as shown. | -//| xScale 0 0 0 | -//| 0 yScale 0 0 | -//| 0 0 zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//| where: | -//| yScale = cot(fovY/2) | -//| xScale = yScale / aspect ratio | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveFovRH(DXMatrix &pout,float fovy,float aspect,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f/(aspect*(float)tan(fovy/2.0f)); - pout.m[1][1] = 1.0f/(float)tan(fovy/2.0f); - pout.m[2][2] = zf/(zn - zf); - pout.m[2][3] = -1.0f; - pout.m[3][2] = (zf*zn)/(zn - zf); - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed perspective projection matrix | -//+------------------------------------------------------------------+ -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/w 0 0 0 | -//| 0 2*zn/h 0 0 | -//| 0 0 zf/(zf-zn) 1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveLH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); - pout.m[0][0] = 2.0f*zn/w; - pout.m[1][1] = 2.0f*zn/h; - pout.m[2][2] = zf/(zf - zn); - pout.m[3][2] = (zn*zf)/(zn - zf); - pout.m[2][3] = 1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a customized, left-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveOffCenterLH | -//| function are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/(r-l) 0 0 0 | -//| 0 2*zn/(t-b) 0 0 | -//| (l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/(r - l); - pout.m[1][1] = -2.0f*zn/(b - t); - pout.m[2][0] = -1.0f - 2.0f*l/(r - l); - pout.m[2][1] = 1.0f + 2.0f*t/(b - t); - pout.m[2][2] = - zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn -zf); - pout.m[2][3] = 1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a customized, right-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveOffCenterRH | -//| function are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/(r-l) 0 0 0 | -//| 0 2*zn/(t-b) 0 0 | -//| (l+r)/(r-l) (t+b)/(t-b) zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/(r - l); - pout.m[1][1] = -2.0f*zn/(b - t); - pout.m[2][0] = 1.0f + 2.0f*l/(r - l); - pout.m[2][1] = -1.0f -2.0f*t/(b - t); - pout.m[2][2] = zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn -zf); - pout.m[2][3] = -1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveRH function | -//| are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/w 0 0 0 | -//| 0 2*zn/h 0 0 | -//| 0 0 zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveRH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/w; - pout.m[1][1] = 2.0f*zn/h; - pout.m[2][2] = zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn - zf); - pout.m[2][3] = -1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that reflects the coordinate system about a plane| -//| This function normalizes the plane equation before it creates | -//| the reflected matrix. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| P = normalize(Plane); | -//| -2 * P.a * P.a + 1 -2 * P.b * P.a -2 * P.c * P.a 0 | -//| -2 * P.a * P.b -2 * P.b * P.b + 1 -2 * P.c * P.b 0 | -//| -2 * P.a * P.c -2 * P.b * P.c -2 * P.c * P.c + 1 0 | -//| -2 * P.a * P.d -2 * P.b * P.d -2 * P.c * P.d 1 | -//+------------------------------------------------------------------+ -void DXMatrixReflect(DXMatrix &pout,const DXPlane &pplane) - { - DXPlane Nplane; - DXPlaneNormalize(Nplane,pplane); - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f - 2.0f*Nplane.a*Nplane.a; - pout.m[0][1] = -2.0f*Nplane.a*Nplane.b; - pout.m[0][2] = -2.0f*Nplane.a*Nplane.c; - pout.m[1][0] = -2.0f*Nplane.a*Nplane.b; - pout.m[1][1] = 1.0f - 2.0f*Nplane.b*Nplane.b; - pout.m[1][2] = -2.0f*Nplane.b*Nplane.c; - pout.m[2][0] = -2.0f*Nplane.c*Nplane.a; - pout.m[2][1] = -2.0f*Nplane.c*Nplane.b; - pout.m[2][2] = 1.0f - 2.0f*Nplane.c*Nplane.c; - pout.m[3][0] = -2.0f*Nplane.d*Nplane.a; - pout.m[3][1] = -2.0f*Nplane.d*Nplane.b; - pout.m[3][2] = -2.0f*Nplane.d*Nplane.c; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around an arbitrary axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationAxis(DXMatrix &out,const DXVector3 &v,float angle) - { - DXVector3 nv; - DXVec3Normalize(nv,v); -//--- - float sangle = (float)sin(angle); - float cangle = (float)cos(angle); - float cdiff = 1.0f - cangle; -//--- - out.m[0][0] = cdiff*nv.x*nv.x + cangle; - out.m[1][0] = cdiff*nv.x*nv.y - sangle*nv.z; - out.m[2][0] = cdiff*nv.x*nv.z + sangle*nv.y; - out.m[3][0] = 0.0f; - out.m[0][1] = cdiff*nv.y*nv.x + sangle*nv.z; - out.m[1][1] = cdiff*nv.y*nv.y + cangle; - out.m[2][1] = cdiff*nv.y*nv.z - sangle*nv.x; - out.m[3][1] = 0.0f; - out.m[0][2] = cdiff*nv.z*nv.x - sangle*nv.y; - out.m[1][2] = cdiff*nv.z*nv.y + sangle*nv.x; - out.m[2][2] = cdiff*nv.z*nv.z + cangle; - out.m[3][2] = 0.0f; - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a rotation matrix from a quaternion. | -//+------------------------------------------------------------------+ -void DXMatrixRotationQuaternion(DXMatrix &pout,const DXQuaternion &pq) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f - 2.0f*(pq.y*pq.y + pq.z*pq.z); - pout.m[0][1] = 2.0f*(pq.x*pq.y + pq.z*pq.w); - pout.m[0][2] = 2.0f*(pq.x*pq.z - pq.y*pq.w); - pout.m[1][0] = 2.0f*(pq.x*pq.y - pq.z*pq.w); - pout.m[1][1] = 1.0f - 2.0f * (pq.x*pq.x + pq.z*pq.z); - pout.m[1][2] = 2.0f*(pq.y*pq.z + pq.x*pq.w); - pout.m[2][0] = 2.0f*(pq.x*pq.z + pq.y*pq.w); - pout.m[2][1] = 2.0f*(pq.y*pq.z - pq.x*pq.w); - pout.m[2][2] = 1.0f - 2.0f*(pq.x*pq.x + pq.y*pq.y); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the x-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationX(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[1][1] = (float)cos(angle); - pout.m[2][2] = (float)cos(angle); - pout.m[1][2] = (float)sin(angle); - pout.m[2][1] = -(float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the y-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationY(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = (float)cos(angle); - pout.m[2][2] = (float)cos(angle); - pout.m[0][2] = -(float)sin(angle); - pout.m[2][0] = (float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix with a specified yaw, pitch, and roll. | -//+------------------------------------------------------------------+ -//| The order of transformations is roll first, then pitch, then yaw.| -//| Relative to the object's local coordinate axis, this is | -//| equivalent to rotation around the z-axis, followed by rotation | -//| around the x-axis, followed by rotation around the y-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationYawPitchRoll(DXMatrix &out,float yaw,float pitch,float roll) - { - float sroll = (float)sin(roll); - float croll = (float)cos(roll); - float spitch = (float)sin(pitch); - float cpitch = (float)cos(pitch); - float syaw = (float)sin(yaw); - float cyaw = (float)cos(yaw); -//--- - out.m[0][0] = sroll * spitch * syaw + croll * cyaw; - out.m[0][1] = sroll * cpitch; - out.m[0][2] = sroll * spitch * cyaw - croll * syaw; - out.m[0][3] = 0.0f; - out.m[1][0] = croll * spitch * syaw - sroll * cyaw; - out.m[1][1] = croll * cpitch; - out.m[1][2] = croll * spitch * cyaw + sroll * syaw; - out.m[1][3] = 0.0f; - out.m[2][0] = cpitch * syaw; - out.m[2][1] = -spitch; - out.m[2][2] = cpitch * cyaw; - out.m[2][3] = 0.0f; - out.m[3][0] = 0.0f; - out.m[3][1] = 0.0f; - out.m[3][2] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the z-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationZ(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = (float)cos(angle); - pout.m[1][1] = (float)cos(angle); - pout.m[0][1] = (float)sin(angle); - pout.m[1][0] = -(float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that scales along the x-axis, | -//| the y-axis,and the z-axis. | -//+------------------------------------------------------------------+ -void DXMatrixScaling(DXMatrix &pout,float sx,float sy,float sz) - { - DXMatrixIdentity(pout); - pout.m[0][0] = sx; - pout.m[1][1] = sy; - pout.m[2][2] = sz; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that flattens geometry into a plane. | -//+------------------------------------------------------------------+ -//| The DXMatrixShadow function flattens geometry into a plane, as | -//| if casting a shadow from a light. | -//| This function uses the following formula to compute the returned | -//| matrix. | -//| | -//| P = normalize(Plane); | -//| L = Light; | -//| d = -dot(P,L) | -//| | -//| P.a * L.x + d P.a * L.y P.a * L.z P.a * L.w | -//| P.b * L.x P.b * L.y + d P.b * L.z P.b * L.w | -//| P.c * L.x P.c * L.y P.c * L.z + d P.c * L.w | -//| P.d * L.x P.d * L.y P.d * L.z P.d * L.w + d | -//| | -//| If the light's w-component is 0, the ray from the origin to the | -//| light represents a directional light. If it is 1,the light is | -//| a point light. | -//+------------------------------------------------------------------+ -void DXMatrixShadow(DXMatrix &pout,const DXVector4 &plight,const DXPlane &pplane) - { - DXPlane Nplane; - DXPlaneNormalize(Nplane,pplane); - float dot = DXPlaneDot(Nplane,plight); -//--- - pout.m[0][0] = dot - Nplane.a*plight.x; - pout.m[0][1] = -Nplane.a*plight.y; - pout.m[0][2] = -Nplane.a*plight.z; - pout.m[0][3] = -Nplane.a*plight.w; - pout.m[1][0] = -Nplane.b*plight.x; - pout.m[1][1] = dot - Nplane.b*plight.y; - pout.m[1][2] = -Nplane.b*plight.z; - pout.m[1][3] = -Nplane.b*plight.w; - pout.m[2][0] = -Nplane.c*plight.x; - pout.m[2][1] = -Nplane.c*plight.y; - pout.m[2][2] = dot - Nplane.c*plight.z; - pout.m[2][3] = -Nplane.c*plight.w; - pout.m[3][0] = -Nplane.d*plight.x; - pout.m[3][1] = -Nplane.d*plight.y; - pout.m[3][2] = -Nplane.d*plight.z; - pout.m[3][3] = dot - Nplane.d*plight.w; - } -//+------------------------------------------------------------------+ -//| Builds a transformation matrix. | -//+------------------------------------------------------------------+ -//| This function calculates the transformation matrix with the | -//| following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| | -//| Mout = (Msc)^(-1)*(Msr)^(-1)*Ms*Msr*Msc*(Mrc)^(-1)*Mr*Mrc*Mt | -//| | -//| where: | -//| Mout = output matrix (pOut) | -//| Msc = scaling center matrix (pScalingCenter) | -//| Msr = scaling rotation matrix (pScalingRotation) | -//| Ms = scaling matrix (pScaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (pRotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixTransformation(DXMatrix &pout,const DXVector3 &pscalingcenter,const DXQuaternion &pscalingrotation,const DXVector3 &pscaling,const DXVector3 &protationcenter,const DXQuaternion &protation,const DXVector3 &ptranslation) - { - DXMatrix m1,m2,m3,m4,m5,m6,m7; - DXQuaternion prc; - DXVector3 psc,pt; -//--- pscalingcenter - psc.x = pscalingcenter.x; - psc.y = pscalingcenter.y; - psc.z = pscalingcenter.z; -//--- protationcenter - prc.x = protationcenter.x; - prc.y = protationcenter.y; - prc.z = protationcenter.z; -//--- ptranslation - pt.x = ptranslation.x; - pt.y = ptranslation.y; - pt.z = ptranslation.z; - DXMatrixTranslation(m1,-psc.x,-psc.y,-psc.z); -//--- - DXQuaternion temp; - DXMatrixRotationQuaternion(m4,pscalingrotation); - temp.w = pscalingrotation.w; - temp.x = -pscalingrotation.x; - temp.y = -pscalingrotation.y; - temp.z = -pscalingrotation.z; - DXMatrixRotationQuaternion(m2,temp); -//--- pscaling - DXMatrixScaling(m3,pscaling.x,pscaling.y,pscaling.z); -//--- protation - DXMatrixRotationQuaternion(m6,protation); -//--- - DXMatrixTranslation(m5,psc.x - prc.x,psc.y - prc.y,psc.z - prc.z); - DXMatrixTranslation(m7,prc.x + pt.x,prc.y + pt.y,prc.z + pt.z); - DXMatrixMultiply(m1,m1,m2); - DXMatrixMultiply(m1,m1,m3); - DXMatrixMultiply(m1,m1,m4); - DXMatrixMultiply(m1,m1,m5); - DXMatrixMultiply(m1,m1,m6); - DXMatrixMultiply(pout,m1,m7); - } -//+------------------------------------------------------------------+ -//| Builds a 2D transformation matrix that represents | -//| transformations in the xy plane. | -//+------------------------------------------------------------------+ -//| This function calculates the transformation matrix with the | -//| following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| | -//| Mout = (Msc)^(-1)*(Msr)^(-1)*Ms*Msr*Msc*(Mrc)^(-1)*Mr*Mrc*Mt | -//| | -//| where: | -//| Mout = output matrix (pOut) | -//| Msc = scaling center matrix (pScalingCenter) | -//| Msr = scaling rotation matrix (pScalingRotation) | -//| Ms = scaling matrix (pScaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (Rotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixTransformation2D(DXMatrix &pout,const DXVector2 &pscalingcenter,float scalingrotation,const DXVector2 &pscaling,const DXVector2 &protationcenter,float rotation,const DXVector2 &ptranslation) - { - DXQuaternion rot,sca_rot; - DXVector3 rot_center,sca,sca_center,trans; -//--- pscalingcenter - sca_center.x=pscalingcenter.x; - sca_center.y=pscalingcenter.y; - sca_center.z=0.0f; -//--- pscaling - sca.x=pscaling.x; - sca.y=pscaling.y; - sca.z=1.0f; -//--- protationcenter - rot_center.x=protationcenter.x; - rot_center.y=protationcenter.y; - rot_center.z=0.0f; -//--- ptranslation - trans.x=ptranslation.x; - trans.y=ptranslation.y; - trans.z=0.0f; -//--- - rot.w=(float)cos(rotation/2.0f); - rot.x=0.0f; - rot.y=0.0f; - rot.z=(float)sin(rotation/2.0f); -//--- - sca_rot.w=(float)cos(scalingrotation/2.0f); - sca_rot.x=0.0f; - sca_rot.y=0.0f; - sca_rot.z=(float)sin(scalingrotation/2.0f); - DXMatrixTransformation(pout,sca_center,sca_rot,sca,rot_center,rot,trans); - } -//+------------------------------------------------------------------+ -//| Builds a matrix using the specified offsets. | -//+------------------------------------------------------------------+ -void DXMatrixTranslation(DXMatrix &pout,float x,float y,float z) - { - DXMatrixIdentity(pout); -//--- - pout.m[3][0] = x; - pout.m[3][1] = y; - pout.m[3][2] = z; - } -//+------------------------------------------------------------------+ -//| Returns the matrix transpose of a matrix. | -//+------------------------------------------------------------------+ -void DXMatrixTranspose(DXMatrix &pout,const DXMatrix &pm) - { - const DXMatrix m = pm; - for(int i=0; i<4; i++) - for(int j=0; j<4; j++) - pout.m[i][j] = m.m[j][i]; - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 4D vector. | -//+------------------------------------------------------------------+ -float DXPlaneDot(const DXPlane &p1,const DXVector4 &p2) - { - return(p1.a*p2.x + p1.b*p2.y + p1.c*p2.z + p1.d*p2.w); - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 3D vector. | -//| The w parameter of the vector is assumed to be 1. | -//+------------------------------------------------------------------+ -float DXPlaneDotCoord(const DXPlane &pp,const DXVector4 &pv) - { - return(pp.a*pv.x + pp.b*pv.y + pp.c*pv.z + pp.d); - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 3D vector. | -//| The w parameter of the vector is assumed to be 0. | -//+------------------------------------------------------------------+ -float DXPlaneDotNormal(const DXPlane &pp,const DXVector4 &pv) - { - return(pp.a*pv.x + pp.b*pv.y + pp.c*pv.z); - } -//+------------------------------------------------------------------+ -//| Constructs a plane from a point and a normal. | -//+------------------------------------------------------------------+ -void DXPlaneFromPointNormal(DXPlane &pout,const DXVector3 &pvpoint,const DXVector3 &pvnormal) - { - pout.a = pvnormal.x; - pout.b = pvnormal.y; - pout.c = pvnormal.z; - pout.d = -DXVec3Dot(pvpoint,pvnormal); - } -//+------------------------------------------------------------------+ -//| Constructs a plane from three points. | -//+------------------------------------------------------------------+ -void DXPlaneFromPoints(DXPlane &pout,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3) - { - DXVector3 edge1,edge2,normal,Nnormal; -//--- - edge1.x = 0.0f; - edge1.y = 0.0f; - edge1.z = 0.0f; - edge2.x = 0.0f; - edge2.y = 0.0f; - edge2.z = 0.0f; -//--- - DXVec3Subtract(edge1,pv2,pv1); - DXVec3Subtract(edge2,pv3,pv1); - DXVec3Cross(normal,edge1,edge2); - DXVec3Normalize(Nnormal,normal); - DXPlaneFromPointNormal(pout,pv1,Nnormal); - } -//+------------------------------------------------------------------+ -//| Finds the intersection between a plane and a line. | -//| If the line is parallel to the plane, null vector is returned. | -//+------------------------------------------------------------------+ -void DXPlaneIntersectLine(DXVector3 &pout,const DXPlane &pp,const DXVector3 &pv1,const DXVector3 &pv2) - { - DXVector3 direction,normal; - normal.x = pp.a; - normal.y = pp.b; - normal.z = pp.c; - direction.x = pv2.x - pv1.x; - direction.y = pv2.y - pv1.y; - direction.z = pv2.z - pv1.z; -//--- - float dot = DXVec3Dot(normal,direction); - if(!dot) - { - pout.x=0.0f; - pout.y=0.0f; - pout.z=0.0f; - } - float temp = (pp.d + DXVec3Dot(normal,pv1))/dot; - pout.x = pv1.x - temp*direction.x; - pout.y = pv1.y - temp*direction.y; - pout.z = pv1.z - temp*direction.z; - } -//+------------------------------------------------------------------+ -//| Normalizes the plane coefficients so that the plane normal | -//| has unit length. | -//| This function normalizes a plane so that |a,b,c| == 1. | -//+------------------------------------------------------------------+ -void DXPlaneNormalize(DXPlane &out,const DXPlane &p) - { - float norm = (float)sqrt(p.a*p.a + p.b*p.b + p.c*p.c); - if(norm) - { - out.a = p.a/norm; - out.b = p.b/norm; - out.c = p.c/norm; - out.d = p.d/norm; - } - else - { - out.a = 0.0f; - out.b = 0.0f; - out.c = 0.0f; - out.d = 0.0f; - } - } -//+------------------------------------------------------------------+ -//| Scale the plane with the given scaling factor. | -//+------------------------------------------------------------------+ -void DXPlaneScale(DXPlane &pout,const DXPlane &p,float s) - { - pout.a = p.a*s; - pout.b = p.b*s; - pout.c = p.c*s; - pout.d = p.d*s; - }; -//+------------------------------------------------------------------+ -//| Transforms a plane by a matrix. | -//| The input matrix is the inverse transpose of the actual | -//| transformation. | -//+------------------------------------------------------------------+ -void DXPlaneTransform(DXPlane &pout,const DXPlane &pplane,const DXMatrix &pm) - { - DXPlane plane = pplane; -//--- - pout.a = pm.m[0][0]*plane.a + pm.m[1][0]*plane.b + pm.m[2][0]*plane.c + pm.m[3][0]*plane.d; - pout.b = pm.m[0][1]*plane.a + pm.m[1][1]*plane.b + pm.m[2][1]*plane.c + pm.m[3][1]*plane.d; - pout.c = pm.m[0][2]*plane.a + pm.m[1][2]*plane.b + pm.m[2][2]*plane.c + pm.m[3][2]*plane.d; - pout.d = pm.m[0][3]*plane.a + pm.m[1][3]*plane.b + pm.m[2][3]*plane.c + pm.m[3][3]*plane.d; - } -//+------------------------------------------------------------------+ -//| Adds two spherical harmonic (SH) vectors; in other words, | -//| out[i] = a[i] + b[i]. | -//+------------------------------------------------------------------+ -//| Each coefficient of the basis function Y(l,m) is stored | -//| at memory location l^2 + m + l,where: | -//| l is the degree of the basis function. | -//| m is the basis function index for the given l value | -//| and ranges from -l to l, inclusive. | -//+------------------------------------------------------------------+ -void DXSHAdd(float &out[],int order,const float &a[],const float &b[]) - { - for(int i = 0; i DX_PI/2.0f) ? (DX_PI/2.0f) : radius; - float norm = (float)sin(clamped_angle)*(float)sin(clamped_angle); - if(order > DXSH_MAXORDER) - { - //--- order clamped at DXSH_MAXORDER - order = DXSH_MAXORDER; - } -//--- - weightedcapintegrale(cap,order,radius); - DXSHEvalDirection(rout,order,dir); -//--- - for(int i = 0; i DXSH_MAXORDER)) - return; - - out[0] = 0.5f/(float)sqrt(DX_PI); - out[1] = -0.5f/(float)sqrt(DX_PI/3.0f)*dir.y; - out[2] = 0.5f/(float)sqrt(DX_PI/3.0f)*dir.z; - out[3] = -0.5f/(float)sqrt(DX_PI/3.0f)*dir.x; - if(order == 2) - return; - - out[4] = 0.5f/(float)sqrt(DX_PI/15.0f)*dirxy; - out[5] = -0.5f/(float)sqrt(DX_PI/15.0f)*diryz; - out[6] = 0.25f/(float)sqrt(DX_PI/5.0f)*(3.0f*dirzz - 1.0f); - out[7] = -0.5f/(float)sqrt(DX_PI/15.0f)*dirxz; - out[8] = 0.25f/(float)sqrt(DX_PI/15.0f)*(dirxx - diryy); - if(order == 3) - return; - - out[9] = -(float)sqrt(70.0f/DX_PI)/8.0f*dir.y*(3.0f*dirxx - diryy); - out[10] = (float)sqrt(105.0f/DX_PI)/2.0f*dirxy*dir.z; - out[11] = -(float)sqrt(42.0f/DX_PI)/8.0f*dir.y*(-1.0f + 5.0f*dirzz); - out[12] = (float)sqrt(7.0f/DX_PI)/4.0f*dir.z*(5.0f*dirzz - 3.0f); - out[13] = (float)sqrt(42.0f/DX_PI)/8.0f*dir.x*(1.0f - 5.0f*dirzz); - out[14] = (float)sqrt(105.0f/DX_PI)/4.0f*dir.z*(dirxx - diryy); - out[15] = -(float)sqrt(70.0f/DX_PI)/8.0f*dir.x*(dirxx - 3.0f*diryy); - if(order == 4) - return; - - out[16] = 0.75f*float(sqrt(35.0f/DX_PI))*dirxy*(dirxx - diryy); - out[17] = 3.0f*dir.z*out[9]; - out[18] = 0.75f*(float)sqrt(5.0f/DX_PI)*dirxy*(7.0f*dirzz - 1.0f); - out[19] = 0.375f*(float)sqrt(10.0f/DX_PI)*diryz*(3.0f - 7.0f*dirzz); - out[20] = 3.0f/(16.0f*(float)sqrt(DX_PI))*(35.0f*dirzzzz - 30.f*dirzz + 3.0f); - out[21] = 0.375f*(float)sqrt(10.0f/DX_PI)*dirxz*(3.0f - 7.0f*dirzz); - out[22] = 0.375f*(float)sqrt(5.0f/DX_PI)*(dirxx - diryy)*(7.0f*dirzz - 1.0f); - out[23] = 3.0f*dir.z*out[15]; - out[24] = 3.0f / 16.0f*float(sqrt(35.0f/DX_PI))*(dirxxxx - 6.0f*dirxyxy + diryyyy); - if(order == 5) - return; - - out[25] = -3.0f/32.0f*(float)sqrt(154.0f/DX_PI)*dir.y*(5.0f*dirxxxx - 10.0f*dirxyxy + diryyyy); - out[26] = 0.75f*(float)sqrt(385.0f/DX_PI)*dirxy*dir.z*(dirxx - diryy); - out[27] = (float)sqrt(770.0f/DX_PI)/32.0f*dir.y*(3.0f*dirxx - diryy)*(1.0f - 9.0f*dirzz); - out[28] = (float)sqrt(1155.0f/DX_PI)/4.0f*dirxy*dir.z*(3.0f*dirzz - 1.0f); - out[29] = (float)sqrt(165.0f/DX_PI)/16.0f*dir.y*(14.0f*dirzz - 21.0f*dirzzzz - 1.0f); - out[30] = (float)sqrt(11.0f/DX_PI)/16.0f*dir.z*(63.0f*dirzzzz - 70.0f*dirzz + 15.0f); - out[31] = (float)sqrt(165.0f/DX_PI)/16.0f*dir.x*(14.0f*dirzz - 21.0f*dirzzzz - 1.0f); - out[32] = (float)sqrt(1155.0f/DX_PI)/8.0f*dir.z*(dirxx - diryy)*(3.0f*dirzz - 1.0f); - out[33] = (float)sqrt(770.0f/DX_PI)/32.0f*dir.x*(dirxx - 3.0f*diryy)*(1.0f - 9.0f*dirzz); - out[34] = 3.0f/16.0f*(float)sqrt(385.0f/DX_PI)*dir.z*(dirxxxx - 6.0f*dirxyxy + diryyyy); - out[35] = -3.0f/32.0f*(float)sqrt(154.0f/DX_PI)*dir.x*(dirxxxx - 10.0f*dirxyxy + 5.0f*diryyyy); - } -//+------------------------------------------------------------------+ -//| Evaluates a directional light and | -//| returns spectral spherical harmonic (SH) data. | -//+------------------------------------------------------------------+ -//| The output vector is computed so that if the intensity ratio | -//| R/G/B is equal to 1 ,the resulting exit radiance of a point | -//| directly under the light on a diffuse object with an albedo | -//| of 1 would be 1.0. This will compute three spectral samples; | -//| rout[], gout[] and bout[] will be returned. | -//+------------------------------------------------------------------+ -int DXSHEvalDirectionalLight(int order,const DXVector3 &dir,float Rintensity,float Gintensity,float Bintensity,float &rout[],float &gout[],float &bout[]) - { - float s = 0.75f; - if(order > 2) - s += 5.0f/16.0f; - if(order > 4) - s -= 3.0f/32.0f; - s /= DX_PI; - - DXSHEvalDirection(rout,order,dir); - for(int j=0; j DXSH_MAXORDER) - order = DXSH_MAXORDER; -//--- check radius - if(radius < 0.0f) - radius = -radius; - - float dist = DXVec3Length(dir); - float clamped_angle = (dist <= radius) ? DX_PI/2.0f : (float)asin(radius / dist); - - weightedcapintegrale(cap,order,clamped_angle); - DXVec3Normalize(normal,dir); - DXSHEvalDirection(rout,order,normal); - - for(int i=0; iDXSH_MAXORDER) || (order0; j--) - { - out[sum - j] = 0.0f; - out[sum - j] = c[j - 1]*in[sum - j]; - out[sum - j] += s[j - 1]*in[sum + j]; - } - out[sum] = in[sum]; - //--- - for(int j=1; j(); - if(m_buffer_object!=NULL) - { - m_buffer_object.AddRef(); - //--- use default vertex shader - m_shader_vertex=dispatcher.ShaderCreateDefault(DX_SHADER_VERTEX); - if(m_shader_vertex!=NULL) - { - m_shader_vertex.AddRef(); - //--- use default pixel shader - m_shader_pixel=dispatcher.ShaderCreateDefault(DX_SHADER_PIXEL); - if(m_shader_pixel!=NULL) - { - m_shader_pixel.AddRef(); - //--- create vertex buffer - m_buffer_vertex=dispatcher.VertexBufferCreate(vertices); - if(m_buffer_vertex!=NULL) - { - m_buffer_vertex.AddRef(); - //--- create index buffer - m_buffer_index=dispatcher.IndexBufferCreate(indices); - if(m_buffer_index!=NULL) - m_buffer_index.AddRef(); - } - } - } - } - //--- set object buffer to shaders - if(m_buffer_object==NULL || m_shader_vertex==NULL || m_shader_pixel==NULL || m_buffer_vertex==NULL || m_buffer_index==NULL) - { - Shutdown(); - return(false); - } - //--- save scene buffer - m_buffer_scene=buffer_scene; - m_buffer_scene.AddRef(); - //--- save topology - m_topology=topology; - //--- - return(true); - } - //+------------------------------------------------------------------+ - //| Create mesh object from OBJ mesh file | - //+------------------------------------------------------------------+ - bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,string obj_path,float scale=1.0f,bool inverse_winding=false) - { - DXVertex vertices[]; - uint indices[]; - //--- load model - if(!DXLoadObjModel(obj_path,vertices,indices,scale)) - return(false); - //--- set white vertices color - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - int count=ArraySize(vertices); - for(int i=0; imre#bi0kB6YdJF>rUz4D%)hIXtY)d7R9!JM)0SrZ?+v+N`n{@(`*XU zc6R2?o43>NuPUmjV7maTf_1DBO%)?J|GG|ajbpSB!Gnt~Uh%;EqZRNp@q!-S5yHnk zqs5H3haK$V09&+AnJH$*OZ4d(^Dg4kE82Iw8}d!aXAUGz$Ve{jRq!m&r(lhlF+$Ds zVn{T@l$8Mcv^vDpoxxKi{cMo&XJQPibX@8F<-7OM&RezKCMUSG2 zCPbfh4XV}UyZU#}soILfkMwmJUTWm6M+LO$@3Zg1qRpU88sX%_sG!F)mYhOSh)3Pj z%=3gb(UY9tMXQS&b1uZw!yA9=#$WTuzm3O^KOn-8JNm3F$j$P(Km#QVh}|dVvW0nC zn~i#w0|%R|EJ54AS!$ISr=E$FWlwerXC8AmaFJU1J4MmS*Tpdz?2{RDGJ2dPGIs+` zK8KfdLZ(ZLm-H?oGs>dY;?u80PGolnPedRLB;1F5qg9pXIME2|;acdmqP+Tl%Q)Se Z?Sf`h57%N^QOsu?Pih{g-6-03`UfF0>bC#@ diff --git a/Include/Canvas/DX/DXShader.mqh b/Include/Canvas/DX/DXShader.mqh deleted file mode 100644 index 34ce5cc1178b86c9001afbf6e648f5bce7f8bf57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16984 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 CdqPYA diff --git a/Include/Canvas/DX/DXSurface.mqh b/Include/Canvas/DX/DXSurface.mqh deleted file mode 100644 index d636aa1..0000000 --- a/Include/Canvas/DX/DXSurface.mqh +++ /dev/null @@ -1,162 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXSurface.mqh | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019, MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//--- -#include "DXMesh.mqh" -#include "DXMath.mqh" -#include "DXUtils.mqh" -//+------------------------------------------------------------------+ -//| 3D Box object | -//+------------------------------------------------------------------+ -class CDXSurface : public CDXMesh - { -public: - //--- surface creation flags - enum EN_SURFACE_FLAGS - { - SF_NONE =0x0, - SF_TWO_SIDED =0x1, - SF_USE_NORMALS =0x2, - }; - //--- surface color scheme - enum EN_COLOR_SCHEME - { - CS_NONE =0, - CS_JET =1, - CS_COLD_TO_HOT =2, - CS_RED_TO_GREEN=3 - }; - -protected: - uint m_data_width; - uint m_data_height; - uint m_flags; - EN_COLOR_SCHEME m_color_scheme; - -public: - CDXSurface(); - ~CDXSurface(); - //--- create bon in specified context - bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,double &data[],uint m_data_widht,uint m_data_height,float data_range,const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,uint flags=SF_NONE,EN_COLOR_SCHEME color_scheme=CS_NONE); - //--- update box - bool Update(double &data[],uint m_data_widht,uint m_data_height,float data_range,const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,uint flags=0,EN_COLOR_SCHEME color_scheme=CS_NONE); - -private: - //--- - void PrepareColors(DXVertex &vertices[],const DXVector3 &from,const DXVector3 &to); - }; -//+------------------------------------------------------------------+ -//| Class constructor | -//+------------------------------------------------------------------+ -void CDXSurface::CDXSurface() : CDXMesh() - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CDXSurface::~CDXSurface(void) - { - } -//+------------------------------------------------------------------+ -//| Create box in specified context | -//+------------------------------------------------------------------+ -bool CDXSurface::Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene, - double &data[],uint data_width,uint data_height,float data_range, - const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size, - uint flags=SF_NONE,EN_COLOR_SCHEME color_scheme=CS_NONE) - { -//--- release previous buffers - Shutdown(); -//--- save parameters - m_data_width =data_width; - m_data_height =data_height; - m_flags =flags; - m_color_scheme=color_scheme; -//--- - DXVertex vertices[]; - uint indices[]; -//--- prepare surface vertices and indices - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - if(!DXComputeSurface(data,data_width,data_height,data_range,from,to,texture_size,flags&SF_TWO_SIDED,flags&SF_USE_NORMALS,vertices,indices)) - return(false); -//--- calculate colors - PrepareColors(vertices,from,to); -//--- create mesh - return(CDXMesh::Create(dispatcher,buffer_scene,vertices,indices)); - } -//+------------------------------------------------------------------+ -//| Update box bounds | -//+------------------------------------------------------------------+ -bool CDXSurface::Update(double &data[],uint data_width,uint data_height,float data_range, - const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size, - uint flags=0,EN_COLOR_SCHEME color_scheme=CS_NONE) - { -//--- - DXVertex vertices[]; - uint indices[]; -//--- prepare surface vertices and indices - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - if(!DXComputeSurface(data,data_width,data_height,data_range,from,to,texture_size,flags&SF_TWO_SIDED,flags&SF_USE_NORMALS,vertices,indices)) - return(false); -//--- calculate colors - m_color_scheme=color_scheme; - PrepareColors(vertices,from,to); -//--- update vertices - bool res=CDXMesh::VerticesSet(vertices); -//--- do not update indices if vertices relations are the same - if(m_data_width!=data_width || m_data_height!=data_height || (m_flags&SF_TWO_SIDED)!=(flags&SF_TWO_SIDED)) - res=res && CDXMesh::IndicesSet(indices); -//--- check result - if(!res) - { - Shutdown(); - return(false); - } -//--- save parameters - m_data_width =data_width; - m_data_height =data_height; - m_flags =flags; -//--- success - return(true); - } -//+------------------------------------------------------------------+ -//| Update box bounds | -//+------------------------------------------------------------------+ -void CDXSurface::PrepareColors(DXVertex &vertices[],const DXVector3 &from,const DXVector3 &to) - { - uint count=ArraySize(vertices); - float scale=1.0f/(fmax(FLT_EPSILON,to.y-from.y)); - switch(m_color_scheme) - { - case CS_JET: - { - for(uint i=0; i^$y0_uR+q_ixLxEQ_*Kg3qE{mP?RkS^;QX`Skf$y^Ig$}}Y|B1&OR?Wgxh^;4u2j)}j+0Vp%1fNuLu*g^7~Mkq1A0R| zp)84TpJVKF4ej5NXLdX(Yl;*5vSMs8gfzo3Djm6v)-Gf^4CE;jf35)WE@bQg*_Od@ zUTEc~z_g2z4#u2~=Z%H4EA9h#&OX6!U)}{hxAwt=9c9wqc~2dBQg*VcZuAdXK06=I zJJYkZO!$x&({Wh=Vn^W44raE&BZr^n&lWt|dT7hAfEb;cmR`9sd6pPYDiaRYs*WwI zCjO*|Gy`aynwWE5yPt2JWs8@pd{~`;4adM{0Lyn^@9gJmuBTNHMS57vO3Ywks>zNmiLa<|pRv8rxzSQGj%lQr?}qBX=nM|{Rjkn@hmIb{b( zrN}N#_#nsIz?!Si_bETCcA$5!fKN_mjbjCfbb(M}vM^f~$tof}{g+So@$?7?reISQ zd~z#VW~?awamW7>klB2t9dx<=d904_*UL$c%LXuyc|{N=+BFN z#l~G*+a^G{2LxI`r)?OvZOb0heaxgsK+Z+0B5ZlWpGGo7pbz9vfIB^;3k%Tu7-`A$7J7$h+wq?Hx7y`n z@q*&AAMzHpq5bqkpq##7#AbR6Yf zp&^gu1^nr`JjCs=A&=yaJi&Jp--q}%WLq}IGm8DE3iKI;n_!u1G4|@-DCl|g^&E{Y znG{DkjpV;k5%7jgt8{RKPUIGD&P%Ar>1)hvZD7dAK_2jS%xWP8?-P6ncz$F?$r*Y; z`1zkIf;Dh-8ys$!`(McE5IbE7Xbw96Pl7C49oHVLICNINI$=5Ux875;zqoR^_{t-U zIP|k!`3RlzqGlXZY7Y0lZQ=jvlV5MnKRu}V$bsx O>6dYoA{J$Or}qPl=t=GX diff --git a/Include/Canvas/DX/DXUtils.mqh b/Include/Canvas/DX/DXUtils.mqh deleted file mode 100644 index 9168473..0000000 --- a/Include/Canvas/DX/DXUtils.mqh +++ /dev/null @@ -1,942 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXUtils.mqh | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019, MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//--- -#include "DXMath.mqh" -#include "DXData.mqh" -//--- data types in Wavefront OBJ file format -#define OBJ_DATA_UNKNOWN 0 -#define OBJ_DATA_V 1 -#define OBJ_DATA_VT 2 -#define OBJ_DATA_VN 3 -#define OBJ_DATA_F 4 -//+------------------------------------------------------------------+ -//| OBJFaceType | -//+------------------------------------------------------------------+ -struct OBJFaceType - { - int total; - int v[4]; - int t[4]; - int n[4]; - }; -//+------------------------------------------------------------------+ -//| Transforms right to left hand system, or backward | -//| TVertex must have | -//| DXVector4 normal and DXVector2 tcoord members | -//+------------------------------------------------------------------+ -template -void DXInverseWinding(TVertex &vertices[],uint &indices[]) - { -//--- proccess vertices - uint count=ArraySize(vertices); - for(uint i=0; i0) - faces[idx].v[i]=(int)StringToInteger(str_parsed_faces[0]); - if(elements>1) - faces[idx].t[i]=(int)StringToInteger(str_parsed_faces[1]); - if(elements>2) - faces[idx].n[i]=(int)StringToInteger(str_parsed_faces[2]); - } - //--- debug message - if(show_debug) - printf("%face d: %d vertex(%d,%d,%d,%d) texture(%d,%d,%d,%d) normal(%d,%d,%d,%d)",idx+1, - faces[idx].v[0],faces[idx].v[1],faces[idx].v[2],faces[idx].v[3], - faces[idx].t[0],faces[idx].t[1],faces[idx].t[2],faces[idx].t[3], - faces[idx].n[0],faces[idx].n[1],faces[idx].n[2],faces[idx].n[3]); - //--- - break; - } - - default: - { - break; - } - } - } -//--- close the file - FileClose(file_handle); -//--- - if(show_debug) - { - printf("File %s loaded successfully. Total lines: %d",filename,total_lines); - printf("total v_positions=%d",total_positions); - printf("total v_normals=%d",total_normals); - printf("total v_tcoords=%d",total_tcoords); - printf("total faces=%d",total_faces); - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Load static 3D models from Maya 2011 | -//| https://en.wikibooks.org/wiki/DirectX/10.0/Direct3D/Loading_Maya | -//| TVertex must have | -//| DXVector4 position, normal and DXVector2 tcoord members | -//+------------------------------------------------------------------+ -template -bool DXLoadObjModel(const string filename,TVertex &vertices[],uint &indices[],float scale=1.0f) - { -//--- intermediate data arrays - DXVector4 v_positions[]; - DXVector2 v_tcoords[]; - DXVector4 v_normals[]; - OBJFaceType faces[]; -//--- load data - if(!DXLoadObjData(filename,v_positions,v_tcoords,v_normals,faces,false)) - { - printf("Error loading model data from %s",filename); - return(false); - } -//--- - int total_v_positions=ArraySize(v_positions); - int total_v_tcoords =ArraySize(v_tcoords); - int total_v_normals =ArraySize(v_normals); - int total_faces =ArraySize(faces); -//--- check faces - if(total_faces==0) - { - printf("No model data."); - return(false); - } -//--- check consistency of the indices - int vertices_count=0; - int indices_count =0; - bool split_vertices=false; - for(int i=0; i4) - { - printf("Error in %d face, face vertices count is %d",i,faces[i].total); - return(false); - } - //--- - for(int j=0; jtotal_v_positions) - { - printf("Error in %d face, %d vertext index is %d. Total posiitons=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(total_v_tcoords>0) - { - if(faces[i].t[j]<=0 || faces[i].t[j]>total_v_tcoords) - { - printf("Error in %d face, %d tcoord index is %d. Total tcoords=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(faces[i].t[j]!=faces[i].v[j]) - split_vertices=true; - } - if(total_v_normals>0) - { - if(faces[i].n[j]<=0 || faces[i].n[j]>total_v_normals) - { - printf("Error in %d face, %d normal index is %d. Total normals=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(faces[i].n[j]!=faces[i].v[j]) - split_vertices=true; - } - } - //--- calc counts - vertices_count+=faces[i].total; - if(faces[i].total<4) - indices_count+=3; - else - indices_count+=6; - } - printf("Data consistency checked."); -//--- prepare arrays - if(!split_vertices) - vertices_count=total_v_positions; - ArrayResize(vertices,vertices_count); - ArrayResize(indices, indices_count); - int v_idx=0,i_idx=0; - for(int i=0; i -bool DXComputeBox(const DXVector3 &from,const DXVector3 &to,TVertex &vertices[],uint &indices[]) - { -//--- prepare arrays - const int faces=6; - if(ArrayResize(vertices,4*faces)!=4*faces) - return(false); -//--- set indices - uint ind[]= {0,1,2, 2,3,0, 4,5,6, 6,7,4, 8,9,10, 10,11,8, 12,13,14, 14,15,12, 16,17,18, 18,19,16, 20,21,22, 22,23,20}; - ArrayResize(indices,0); - if(ArrayCopy(indices,ind)!=ArraySize(ind)) - return(false); -//--- prepare boundaries - float left=from.x,right=to.x,bottom=from.y,top=to.y,near=from.z,far=to.z; - if(from.x>to.x) - { - right=from.x; - left= to.x; - } - if(from.y>to.y) - { - top= from.y; - bottom=to.y; - } - if(from.z>to.z) - { - far=from.z; - near=to.z; - } -//--- left face - vertices[0].position=DXVector4(left,top, far, 1.0); - vertices[1].position=DXVector4(left,top, near,1.0); - vertices[2].position=DXVector4(left,bottom,near,1.0); - vertices[3].position=DXVector4(left,bottom,far, 1.0); - for(int i=0; i<4; i++) - vertices[i].normal=DXVector4(-1.0,0.0,0.0,0.0); -//--- right face - vertices[4].position=DXVector4(right,top, near,1.0); - vertices[5].position=DXVector4(right,top, far, 1.0); - vertices[6].position=DXVector4(right,bottom,far, 1.0); - vertices[7].position=DXVector4(right,bottom,near,1.0); - for(int i=4; i<8; i++) - vertices[i].normal=DXVector4(1.0,0.0,0.0,0.0); -//--- front face - vertices[8].position =DXVector4(left, top, near,1.0); - vertices[9].position =DXVector4(right,top, near,1.0); - vertices[10].position=DXVector4(right,bottom,near,1.0); - vertices[11].position=DXVector4(left, bottom,near,1.0); - for(int i=8; i<12; i++) - vertices[i].normal=DXVector4(0.0,0.0,-1.0,0.0); -//--- back face - vertices[12].position=DXVector4(right,top, far,1.0); - vertices[13].position=DXVector4(left, top, far,1.0); - vertices[14].position=DXVector4(left, bottom,far,1.0); - vertices[15].position=DXVector4(right,bottom,far,1.0); - for(int i=12; i<16; i++) - vertices[i].normal=DXVector4(0.0,0.0,1.0,0.0); -//--- top face - vertices[16].position=DXVector4(left, top,far, 1.0); - vertices[17].position=DXVector4(right,top,far, 1.0); - vertices[18].position=DXVector4(right,top,near,1.0); - vertices[19].position=DXVector4(left, top,near,1.0); - for(int i=16; i<20; i++) - vertices[i].normal=DXVector4(0.0,1.0,0.0,0.0); -//--- bottom face - vertices[20].position=DXVector4(left, bottom,near,1.0); - vertices[21].position=DXVector4(right,bottom,near,1.0); - vertices[22].position=DXVector4(right,bottom,far, 1.0); - vertices[23].position=DXVector4(left, bottom,far, 1.0); - for(int i=20; i<24; i++) - vertices[i].normal=DXVector4(0.0,-1.0,0.0,0.0); -//--- texture coordinates - for(int i=0; i -bool DXComputeSphere(float radius,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; - uint segments_y =tessellation; - uint segments_xz=tessellation*2; -//--- prepare arrays - uint count=(segments_y+1)*(segments_xz+1); - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*segments_y*(segments_xz); - if(ArrayResize(indices,count)!=count) - return(false); -//--- create rings of vertices at progressively higher latitudes. - for(uint i=0,idx=0; i<=segments_y; i++) - { - DXVector2 tcoord=DXVector2(0.0f,1.0f-(float)i/segments_y); - float latitude=(i*DX_PI/segments_y)-DX_PI_DIV2; - float dy =(float)sin(latitude); - float dxz=(float)cos(latitude); - //--- create a single ring of vertices at this latitude. - for(uint j=0; j<=segments_xz; j++,idx++) - { - float longitude=(j%segments_xz)*DX_PI_MUL2/segments_xz; - //--- normal - DXVector3 normal=DXVector3((float)sin(longitude)*dxz,dy,(float)cos(longitude)*dxz); - vertices[idx].normal =DXVector4(normal.x,normal.y,normal.z,0.0); - //--- position - DXVec3Scale(normal,normal,radius); - vertices[idx].position=DXVector4(normal.x,normal.y,normal.z,1.0); - //--- texture coords - tcoord.x = float(j)/segments_xz; - vertices[idx].tcoord =tcoord; - } - } -//--- fill the index buffer with triangles joining each pair of latitude rings. - uint stride=segments_xz+1; - uint idx=0; - for(uint i=0; i -bool DXComputeTorus(float outer_radius,float inner_radius,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=(tessellation+1)*(tessellation+1); - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*tessellation*tessellation; - if(ArrayResize(indices,count)!=count) - return(false); -//--- - uint v=0,idx=0; - uint stride=tessellation+1; -//--- first we loop around the main ring of the torus. - for(uint i=0; i<=tessellation; i++) - { - DXVector2 tcoord=DXVector2(float(i)/tessellation,0.0f); - //--- create a transform matrix that will align geometry to slice perpendicularly though the current ring position. - DXMatrix rotation,transform; - DXMatrixRotationY(rotation,-1.0f*(i%tessellation)*DX_PI_MUL2/tessellation-DX_PI_DIV2); - DXMatrixTranslation(transform,outer_radius,0.0f,0.0f); - DXMatrixMultiply(transform,transform,rotation); - //--- now we loop along the other axis, around the side of the tube. - for(uint j=0; j<=tessellation; j++) - { - //--- calc normal and position - float angle=(j%tessellation)*DX_PI_MUL2/tessellation+DX_PI; - vertices[v].normal=DXVector4((float)cos(angle),(float)sin(angle),0.0f,0.0f); - vertices[v].position=DXVector4(vertices[v].normal.x*inner_radius,vertices[v].normal.y*inner_radius,0.0f,1.0f); - DXVec4Transform(vertices[v].normal, vertices[v].normal, transform); - DXVec4Transform(vertices[v].position,vertices[v].position,transform); - //--- calc texture coord - tcoord.y=1-float(j)/tessellation; - vertices[v].tcoord=tcoord; - v++; - //--- create indices for two triangles. - if(i -bool DXComputeCylinder(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - return(DXComputeTruncatedCone(radius,radius,height,tessellation,vertices,indices)); - } -//+------------------------------------------------------------------+ -//| Truncated Cone | -//| TVertex must have | -//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members| -//+------------------------------------------------------------------+ -template -bool DXComputeTruncatedCone(float radius_top,float radius_bottom,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=2*(tessellation+1)+2*tessellation; - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*tessellation+6*(tessellation-1); - if(ArrayResize(indices,count)!=count) - return(false); -//--- prepare normal - DXVector2 normal=DXVector2(height,radius_bottom-radius_top); - DXVec2Normalize(normal,normal); - float dy=height/2.0f; - uint v=0,idx=0; - uint stride=2; -//--- create top and bottom rings of vertices - for(uint i=0; i<=tessellation; i++) - { - float u=1.0f-(float)i/tessellation; - float angle=(i*DX_PI_MUL2/tessellation); - float dx=(float)sin(angle); - float dz=(float)cos(angle); - //--- - vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f); - vertices[v].position=DXVector4(dx*radius_bottom,-dy,dz*radius_bottom,1.0f); - vertices[v].tcoord =DXVector2(u,1.0f); - v++; - vertices[v].normal =vertices[v-1].normal; - vertices[v].position=DXVector4(dx*radius_top,dy,dz*radius_top,1.0f); - vertices[v].tcoord =DXVector2(u,0.0f); - v++; - //--- creater side surface - if(i0 && i -bool DXComputeCone(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=2*(tessellation+1)+tessellation; - if(ArrayResize(vertices,count)!=count) - return(false); - count=3*tessellation+3*(tessellation-1); - if(ArrayResize(indices,count)!=count) - return(false); -//--- prepare normal - DXVector2 normal=DXVector2(height,radius); - DXVec2Normalize(normal,normal); - float dy=height/2.0f; - uint v=0,idx=0; - uint stride=2; -//--- create top and bottom rings of vertices - for(uint i=0; i<=tessellation; i++) - { - float u=1.0f-(float)i/tessellation; - float angle=(i*DX_PI_MUL2/tessellation); - float dx=(float)sin(angle); - float dz=(float)cos(angle); - //--- - vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f); - vertices[v].position=DXVector4(dx*radius,-dy,dz*radius,1.0f); - vertices[v].tcoord =DXVector2(u,1.0f); - v++; - vertices[v].normal =vertices[v-1].normal; - vertices[v].position=DXVector4(0.0f,dy,0.0f,1.0f); - vertices[v].tcoord =DXVector2(u,0.0f); - v++; - //--- creater side surface - if(i0 && i -bool DXComputeSurface(double &data[],uint data_width,uint data_height,double data_range, - const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size, - bool two_sided,bool use_normals, - TVertex &vertices[],uint &indices[]) - { -//--- - if(data_width<2 || data_height<2) - return(false); -//--- prepare arrays for vertices and triangles - uint count=data_width*data_height*(two_sided?2:1); - if(!ArrayResize(vertices,count)) - return(false); - count=6*(data_width-1)*(data_height-1)*(two_sided?2:1); - if(!ArrayResize(indices,count)) - return(false); -//--- find min and max value - float min_value=+FLT_MAX; - float max_value=-FLT_MAX; - for(uint j=0; jvalue) - min_value=value; - if(max_value=data_width-1) - DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i].position); - else - DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i+1].position); - //--- v2 - if(j<=0) - DXVec4Subtract(v2,vertices[j*data_width+i].position,vertices[(j+1)*data_width+i].position); - else - if(j>=data_height-1) - DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[j*data_width+i].position); - else - DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[(j+1)*data_width+i].position); - //--- normal - DXVec4Cross(normal,v2,v1,DXVector4(0.0f,0.0f,0.0f,1.0f)); - float inv_len=(float)(1.0/sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z)); - vertices[j*data_width+i].normal.x=normal.x*inv_len; - vertices[j*data_width+i].normal.y=normal.y*inv_len; - vertices[j*data_width+i].normal.z=normal.z*inv_len; - vertices[j*data_width+i].normal.w=0.0f; - } - } - } - else - { - DXVector4 n=DXVector4(0.0f,0.0f,0.0f,0.0f); - for(int i=0; i blue > light blue > green > yellow > red > dark red | -//+---------------------------------------------------------------------+ -void DXComputeColorJet(const float value,DXColor &cout) - { - float v=value*1.1f-0.05f; - cout.r = fmin(fmax(v<0.75f ? 4*v-1.5f : 4.5f-4*v,0.0f),1.0f); - cout.g = fmin(fmax(v<0.5f ? 4*v-0.5f : 3.5f-4*v,0.0f),1.0f); - cout.b = fmin(fmax(v<0.25f ? 4*v+0.5f : 2.5f-4*v,0.0f),1.0f); - cout.a = 1.0; - } -//+---------------------------------------------------------------------+ -//| Computes hot to cold color scheme colors on [0;1] range | -//| blue > light blue > green > yellow > red | -//+---------------------------------------------------------------------+ -void DXComputeColorColdToHot(const float value,DXColor &cout) - { - float v=2*value-1.0f; - cout.r = fmin(fmax(2*v,0.0f),1.0f); - cout.g = fmin(fmax(2.0f-2*fabs(v),0.0f),1.0f); - cout.b = fmin(fmax(-2*v,0.0f),1.0f); - cout.a = 1.0; - } -//+---------------------------------------------------------------------+ -//| Computes red to green color scheme colors on [0;1] range | -//| red > yellow > dark green | -//+---------------------------------------------------------------------+ -void DXComputeColorRedToGreen(const float value,DXColor &cout) - { - if(value<=0.5) - { - cout.r=1.0f; - cout.g=DXScalarLerp(0.01f,0.95f,fmin(fmax(2*value,0.0f),1.0f)); - } - else - { - cout.r=DXScalarLerp(0.1f,1.0f, fmin(fmax(2.0f-2*value,0.0f),1.0f)); - cout.g=DXScalarLerp(0.6f,0.95f,fmin(fmax(2.0f-2*value,0.0f),1.0f)); - } - cout.b=0.0f; - cout.a=1.0f; - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl b/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl deleted file mode 100644 index ce90df8..0000000 --- a/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl +++ /dev/null @@ -1,71 +0,0 @@ -//+------------------------------------------------------------------+ -//| Default Pixel Shader | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Inputs for whole scene | -//+------------------------------------------------------------------+ -cbuffer InputScene : register(b0) - { - matrix view; - matrix projection; - float4 light_direction; - float4 light_color; - float4 ambient_color; - }; -//+------------------------------------------------------------------+ -//| Inputs for single object | -//+------------------------------------------------------------------+ -cbuffer InputObject : register(b1) - { - matrix transform; - float4 diffuse_color; - float4 emission_color; - float4 specular_color; - float specular_power; - float dummy[3]; - }; -//+------------------------------------------------------------------+ -//| Input texture | -//+------------------------------------------------------------------+ -Texture2D diffuse_tex : register(t0); -//+------------------------------------------------------------------+ -//| Texture sampler | -//+------------------------------------------------------------------+ -SamplerState diffuse_samp - { - Filter =MIN_MAG_MIP_LINEAR; - AddressU=Wrap; - AddressV=Wrap; - }; -//+------------------------------------------------------------------+ -//| Pixel shader input type | -//+------------------------------------------------------------------+ -struct PSInput - { - float4 position : SV_POSITION; - float4 camera : CAMERA; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Pixel shader entry point | -//+------------------------------------------------------------------+ -float4 PSMain(PSInput input) : SV_TARGET - { - float3 diffuse =saturate(-dot(light_direction.xyz,input.normal.xyz))*light_color.rgb*light_color.a; - float3 ambient =ambient_color.rgb *ambient_color.a; - float3 light =(diffuse+ambient)*diffuse_color.rgb*diffuse_color.a+emission_color.rgb*emission_color.a; - float4 specular=float4(light_color.rgb*specular_color.rgb,pow(saturate(dot(reflect(normalize(light_direction.xyz),input.normal.xyz),normalize(input.camera.xyz))),specular_power)*light_color.a*specular_color.a); - float4 clr=input.color; - //--- use texture if it exist - uint width,height; - diffuse_tex.GetDimensions(width,height); - if(width*height>0) - clr*=diffuse_tex.Sample(diffuse_samp,frac(input.tcoord)); - //--- combine light with colors - return(lerp(float4(light*clr.rgb,clr.a),float4(specular.rgb,1.0),specular.a)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl b/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl deleted file mode 100644 index 14cae19..0000000 --- a/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl +++ /dev/null @@ -1,72 +0,0 @@ -//+------------------------------------------------------------------+ -//| Default Vertex Shader | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| Inputs for whole scene | -//+------------------------------------------------------------------+ -cbuffer InputScene : register(b0) - { - matrix view; - matrix projection; - float4 light_direction; - float4 light_color; - float4 ambient_color; - }; -//+------------------------------------------------------------------+ -//| Inputs for single object | -//+------------------------------------------------------------------+ -cbuffer InputObject : register(b1) - { - matrix transform; - float4 diffuse_color; - float4 emission_color; - float4 specular_color; - float specular_power; - float dummy[3]; - }; -//+------------------------------------------------------------------+ -//| Vertex shader input type | -//+------------------------------------------------------------------+ -struct VSInput - { - float4 position : POSITION; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Pixel shader input type | -//+------------------------------------------------------------------+ -struct PSInput - { - float4 position : SV_POSITION; - float4 camera : CAMERA; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Vertex shader entry point | -//+------------------------------------------------------------------+ -PSInput VSMain(VSInput input) - { - PSInput output; - //--- posiiton and camera direction - output.position=mul(input .position,transform); - output.position=mul(output.position,view); - output.camera =-output.position; - output.position=mul(output.position,projection); - //--- transform normals - output.normal = mul(input.normal, transform); - output.normal = mul(output.normal, view); - output.normal = normalize(output.normal); - //--- color and texture coordinates - output.tcoord =input.tcoord; - output.color =input.color; -//--- - return(output); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/FlameCanvas.mqh b/Include/Canvas/FlameCanvas.mqh deleted file mode 100644 index 543133b..0000000 --- a/Include/Canvas/FlameCanvas.mqh +++ /dev/null @@ -1,751 +0,0 @@ -//+------------------------------------------------------------------+ -//| FlameCanvas.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Canvas.mqh" -#include -//+------------------------------------------------------------------+ -//| Gradient descriptors | -//+------------------------------------------------------------------+ -struct GRADIENT_COLOR - { - uint clr; // color in ARGB format - uint pos; // position of color in percentage of gradient range - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -struct GRADIENT_SIZE - { - uint size; // width of gradient fill in percentage of base fill - uint pos; // position of color in percentage of gradient length - }; -//+------------------------------------------------------------------+ -//| Class CFlameCanvas | -//| Usage: generates flame | -//+------------------------------------------------------------------+ -class CFlameCanvas : public CCanvas - { -private: - //--- parameters - uint m_bar_gap; - uint m_bar_width; - uint m_chart_scale; - double m_chart_price_min; - double m_chart_price_max; - ENUM_TIMEFRAMES m_timeframe; - string m_symbol; - int m_future_bars; - int m_back_bars; - int m_rates_total; - uint m_palette[256]; // flame palette - uchar m_flame[]; // buffer for calculation of flame - uint m_time_redraw; - uint m_delay; - // bool m_resize_flag; - // int m_tick_cnt; - //--- flame parameters - datetime m_tb1; - double m_pb1; - datetime m_te1; - double m_pe1; - datetime m_tb2; - double m_pb2; - datetime m_te2; - double m_pe2; - //--- equation parameters for flame - int m_cloud_axis[100]; - double m_a1; - double m_b1; - double m_a2; - double m_b2; - int m_xb1; - int m_yb1; - int m_xe1; - int m_ye1; - int m_xb2; - int m_yb2; - int m_xe2; - int m_ye2; - -public: - CFlameCanvas(void); - ~CFlameCanvas(void); - //--- create - bool FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars=0); - void RatesTotal(const int value); - //--- setting - void PaletteSet(uint clr=0xFF0000); - //--- draw - void FlameDraw(const double &prices[],const int width,const int lenght); - void FlameSet(datetime xb1,double yb1,datetime xe1,double ye1,datetime xb2,double yb2,datetime xe2,double ye2); - //--- event handler - void ChartEventHandler(const int id,const long &lparam,const double &dparam,const string &sparam); - -protected: - bool Resize(void); - void ChartScale(void); - void FlameSet(void); - void CloudDraw(const double &prices[],const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[],const uchar t_level=255,const bool custom_gradient=true); - void FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[]); - void GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[]); - void GradientVerticalLine(int x,int y1,int y2,const GRADIENT_COLOR &gradient[]); - void GradientVerticalLineMonochrome(int x,int y1,int y2,uint clr1,uint clr2); - void FlameCreate(void); - void FlameCalculate(void); - void Delay(const uint value); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CFlameCanvas::CFlameCanvas(void) : m_bar_gap(16), - m_bar_width(8), - m_chart_scale(1), - m_chart_price_min(0.0), - m_chart_price_max(0.0), - m_timeframe(PERIOD_CURRENT), - m_symbol(NULL), - m_future_bars(0), - m_back_bars(0), - m_rates_total(0), - m_time_redraw(0), - m_delay(50), - m_tb1(0), - m_pb1(0), - m_te1(0), - m_pe1(0), - m_tb2(0), - m_pb2(0), - m_te2(0), - m_pe2(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFlameCanvas::~CFlameCanvas(void) - { - Destroy(); - } -//+------------------------------------------------------------------+ -//| Creates dynamic resource with object | -//+------------------------------------------------------------------+ -bool CFlameCanvas::FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars) - { -//--- get chart parameters - ChartScale(); -//--- create - int width =(int)m_bar_gap*(future_bars+back_bars); - int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); - if(!CreateBitmap(0,0,name,time-back_bars*PeriodSeconds(),m_chart_price_max,width,height,COLOR_FORMAT_ARGB_NORMALIZE)) - return(false); - ArrayResize(m_flame,width*height); -//--- save parameters - m_future_bars=future_bars; - m_back_bars =back_bars; -//--- settings - PaletteSet(); - m_timeframe =Period(); - m_symbol =Symbol(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Resize | -//+------------------------------------------------------------------+ -bool CFlameCanvas::Resize(void) - { - int x,y; -//--- get limits - double min=ChartGetDouble(0,CHART_PRICE_MIN); - double max=ChartGetDouble(0,CHART_PRICE_MAX); - if(m_chart_price_max!=max) - { - //--- move object - ObjectSetDouble(0,m_objname,OBJPROP_PRICE,0,max); - } -//--- check - if(m_chart_price_min==min && m_chart_price_max==max) - return(false); - m_chart_price_min=min; - m_chart_price_max=max; -//--- grt size - ChartTimePriceToXY(0,0,m_tb1,min,x,y); - int width =(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-x; - int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); -//--- resize - if(width80) g+=dg; - if(i>160) b+=db; - } - } -//+------------------------------------------------------------------+ -//| Draws the flame | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameDraw(const double &prices[],const int width,const int lenght) - { - static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}}; - static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}}; -//--- draw - CloudDraw(prices,width,lenght,sword,flame); -//--- copy flame buffer - FlameCalculate(); -//--- start timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[]) - { -//--- check - int total=ArraySize(m_cloud_axis); - if(total<2) - return; - if(total>lenght) - total=lenght; -//--- draw - int xb,xe; // coordinates of the segment - int ybm,yem; // coordinates of the center line - int yb1,ye1; // coordinates of the first line - int yb2,ye2; // coordinates of the second line -//--- for implementation of variable width - int w_total=ArraySize(size); - if(w_total<2) - return; - int w_i =0; - int w_is=(int)size[w_i].pos*total/100; - int w_ie=(int)size[w_i+1].pos*total/100; - double w =size[w_i].size*width/100; - double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is); -//--- draw from left to right - xb=0; - ybm=m_cloud_axis[0]; - yb1=ybm-(int)(w/2); - yb2=ybm+(int)(w/2); -//--- draw - for(int i=1;i=m_width) - break; - yb1=ye1; - yb2=ye2; - while(i>=w_ie-1 && i!=total-1) - { - w_i++; - w_is=(int)size[w_i].pos*total/100; - w_ie=(int)size[w_i+1].pos*total/100; - w =size[w_i].size*width/100; - if(w_ie==w_is) - { - //--- for "instant" resize - dw=size[w_i+1].size*width/100-w; - w+=dw; - ye1=yem-(int)(w/2); - ye2=yem+(int)(w/2); - //--- draw the segment of 'cloud' - GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient); - yb1=ye1; - yb2=ye2; - } - else - { - dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is); - break; - } - } - } -//--- copy flame buffer - FlameCalculate(); - } -//+------------------------------------------------------------------+ -//| Sets parameters of the flame and starts to draw | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameSet(void) - { - m_a1=m_bar_gap*((m_ye1-m_yb1)/((double)m_xe1-m_xb1)); - m_a2=m_bar_gap*((m_ye2-m_yb2)/((double)m_xe2-m_xb2)); - } -//+------------------------------------------------------------------+ -//| Sets parameters of the flame and starts to draw | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameSet(datetime tb1,double pb1, - datetime te1,double pe1, - datetime tb2,double pb2, - datetime te2,double pe2) - { - datetime obj_time =(datetime)ObjectGetInteger(0,m_objname,OBJPROP_TIME); - double obj_price=ObjectGetDouble(0,m_objname,OBJPROP_PRICE); - int dx,dy; -//--- save parameters - m_tb1=tb1; - m_pb1=pb1; - m_te1=te1; - m_pe1=pe1; - m_tb2=tb2; - m_pb2=pb2; - m_te2=te2; - m_pe2=pe2; -//--- resize - Resize(); -//--- convert - if(ChartTimePriceToXY(0,0,obj_time,obj_price,dx,dy)) - { - dy=m_yb1; - if(ChartTimePriceToXY(0,0,tb1,pb1,m_xb1,m_yb1)) - if(ChartTimePriceToXY(0,0,te1,pe1,m_xe1,m_ye1)) - if(ChartTimePriceToXY(0,0,tb2,pb2,m_xb2,m_yb2)) - if(ChartTimePriceToXY(0,0,te2,pe2,m_xe2,m_ye2)) - { - //--- convert to canvas coordinates - m_xb1-=dx; - m_xe1-=dx; - m_xb2-=dx; - m_xe2-=dx; - //--- - FlameSet(); - } - } -//--- start timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - } -//+------------------------------------------------------------------+ -//| Generate array that describes the body of flame | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameCreate(void) - { - static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}}; - static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}}; -//--- - double a=rand(); // parameter of line a*x+b - double b=rand(); // parameter of line a*x+b - double c=rand(); // parameter of sine c*Sin(d*x) - double d=rand(); // parameter of sine c*Sin(d*x) - int w=rand(); // width at the base - int l=rand(); // length -//--- normalize - a=fmod(a,(m_a2-m_a1))+m_a1; - b=(m_yb1+m_yb2)/2; - c=fmod(c,20); - d=fmod(d,3*M_PI)+M_PI; -//--- shape - w%=150; - if(w<10) - w=10; // but no less than 10 - sword[1].size=w; - w=rand(); - l%=50; - sword[1].pos=l+30; - l=rand(); -//--- sizes - w=(m_yb2-m_yb1!=0) ? w%(m_yb2-m_yb1) : 10; // proportional to the starting width - if(w<10) - w=10; // but no less than 10 - l=l%((m_xe1-m_xb1)/(int)m_bar_gap-20)+20; // proportional to length -//--- create - int total=ArraySize(m_cloud_axis); - for(int i=0;ilenght) - total=lenght; -//--- draw - int xb,xe; // coordinates of the segment - int ybm,yem; // coordinates of the center line - int yb1,ye1; // coordinates of the first line - int yb2,ye2; // coordinates of the second line - int xx; -//--- for implementation of variable width - int w_total=ArraySize(size); - if(w_total<2) - return; - int w_i =0; - int w_is=(int)size[w_i].pos*total/100; - int w_ie=(int)size[w_i+1].pos*total/100; - double w =size[w_i].size*width/100; - double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is); -//--- draw from left to right - xb=0; - ChartTimePriceToXY(0,0,0,prices[0],xx,ybm); - yb1=ybm-(int)(w/2); - yb2=ybm+(int)(w/2); -//--- draw - for(int i=1;i=m_width) - break; - yb1=ye1; - yb2=ye2; - while(i>=w_ie-1 && i!=total-1) - { - w_i++; - w_is=(int)size[w_i].pos*total/100; - w_ie=(int)size[w_i+1].pos*total/100; - w =size[w_i].size*width/100; - if(w_ie==w_is) - { - //--- for "instant" resize - dw=size[w_i+1].size*width/100-w; - w+=dw; - ye1=yem-(int)(w/2); - ye2=yem+(int)(w/2); - //--- draw the segment of 'cloud' - GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient); - yb1=ye1; - yb2=ye2; - } - else - { - dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is); - break; - } - } - } - } -//+------------------------------------------------------------------+ -//| Draws area with vertical fill using specified gradient | -//+------------------------------------------------------------------+ -void CFlameCanvas::GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[]) - { -//--- it is assumed that the colors array has sufficient size and positions are already sorted in ascending order -//--- get length by X and Y - int x1 =xb; - int y1 =yb1; - int x2 =xb; - int y2 =yb2; - int dx =(xe>xb)? xe-xb : xb-xe; - int dy1=(ye1>yb1)? ye1-yb1 : yb1-ye1; - int dy2=(ye2>yb2)? ye2-yb2 : yb2-ye2; -//--- get direction by X and Y - int sx =(xb-dy1) - { - //--- try to change X coordinate of the first line - //--- draw the second line - while(x2!=xe || y2!=ye2) - { - //--- calculate coordinates of next pixel of the second line - if((er2<<1)>-dy2) - { - //--- try to change X coordinate of the second line - //--- gradient fill - GradientVerticalLine(x1,y1,y2,gradient); - er2-=dy2; - if(x2!=xe) - x2+=sx; - } - if((er2<<1)0) - { - dd=dy; - dy=1; - } - else - { - dd=-dy; - dy=-1; - } -//--- increments for the color components - dc=(double)((uchar)clr2-clr)/dd; -//--- draw - for(int i=0;y1!=y2;i++,y1+=dy) - { - int idx=y1*m_width+x; - //--- check range - if(idx<0 || idx>=ArraySize(m_flame)) - continue; - if(x>=0 && x=0 && y1m_time_redraw) - { - //--- add the body of flame - FlameCreate(); - //--- draw frame - FlameCalculate(); - Update(); - //--- calculate time for the next frame - m_time_redraw=GetTickCount()+m_delay; - } - //--- generate next event for custom timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - break; - } - } -//+------------------------------------------------------------------+ -//| Delay | -//+------------------------------------------------------------------+ -void CFlameCanvas::Delay(const uint value) - { -//--- too small - if(value<10) - return; -//--- start delay - uint cnt=GetTickCount()+value; -//--- delay - while(cnt>=GetTickCount()); - } -//+------------------------------------------------------------------+ diff --git a/Include/ChartObjects/ChartObject.mqh b/Include/ChartObjects/ChartObject.mqh deleted file mode 100644 index 9e1566e..0000000 --- a/Include/ChartObjects/ChartObject.mqh +++ /dev/null @@ -1,1000 +0,0 @@ -//+------------------------------------------------------------------+ -//| ChartObject.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CChartObject. | -//| Pupose: Base class of chart objects. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CChartObject : public CObject - { -protected: - long m_chart_id; // identifier of chart the object belongs to - int m_window; // number of subwindow (0 - main window) - string m_name; // unique name object name - int m_num_points; // number of anchor points of object - -public: - CChartObject(void); - ~CChartObject(void); - //--- method of identifying the object - virtual int Type(void) const { return(0x8888); } - //--- methods of access to protected data - long ChartId(void) const { return(m_chart_id); } - int Window(void) const { return(m_window); } - string Name(void) const { return(m_name); } - bool Name(const string name); - int NumPoints(void) const { return(m_num_points); } - //--- methods of filling the object - bool Attach(long chart_id,const string name,const int window,const int points); - bool SetPoint(const int point,const datetime time,const double price) const; - //--- methods of deleting - bool Delete(void); - void Detach(void); - //--- methods of access to properties of the object - datetime Time(const int point) const; - bool Time(const int point,const datetime time) const; - double Price(const int point) const; - bool Price(const int point,const double price) const; - color Color(void) const; - bool Color(const color new_color) const; - ENUM_LINE_STYLE Style(void) const; - bool Style(const ENUM_LINE_STYLE new_style) const; - int Width(void) const; - bool Width(const int new_width) const; - bool Background(void) const; - bool Background(const bool new_back) const; - bool Fill(void) const; - bool Fill(const bool new_fill) const; - long Z_Order(void) const; - bool Z_Order(const long value) const; - bool Selected(void) const; - bool Selected(const bool new_sel) const; - bool Selectable(void) const; - bool Selectable(const bool new_sel) const; - string Description(void) const; - bool Description(const string new_text) const; - string Tooltip(void) const; - bool Tooltip(const string new_text) const; - int Timeframes(void) const; - virtual bool Timeframes(const int timeframes) const; - datetime CreateTime(void) const; - int LevelsCount(void) const; - bool LevelsCount(const int new_count) const; - //--- methods to access the properties of levels of objects - color LevelColor(const int level) const; - bool LevelColor(const int level,const color new_color) const; - ENUM_LINE_STYLE LevelStyle(const int level) const; - bool LevelStyle(const int level,const ENUM_LINE_STYLE new_style) const; - int LevelWidth(const int level) const; - bool LevelWidth(const int level,const int new_width) const; - double LevelValue(const int level) const; - bool LevelValue(const int level,const double new_value) const; - string LevelDescription(const int level) const; - bool LevelDescription(const int level,const string new_text) const; - //--- access methods to the API functions of MQL5 - long GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier=-1) const; - bool GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,long &value) const; - bool SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,const long value) const; - bool SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const long value) const; - double GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier=-1) const; - bool GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,double &value) const; - bool SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,const double value) const; - bool SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const double value) const; - string GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier=-1) const; - bool GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,string &value) const; - bool SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,const string value) const; - bool SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const string value) const; - //--- methods of moving - bool ShiftObject(const datetime d_time,const double d_price) const; - bool ShiftPoint(const int point,const datetime d_time,const double d_price) const; - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChartObject::CChartObject(void) - { -//--- initialize protected data - Detach(); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChartObject::~CChartObject(void) - { - if(m_chart_id!=-1) - ObjectDelete(m_chart_id,m_name); - } -//+------------------------------------------------------------------+ -//| Changing name of the object | -//+------------------------------------------------------------------+ -bool CChartObject::Name(const string name) - { -//--- check - if(m_chart_id==-1) - return(false); -//--- change - if(ObjectSetString(m_chart_id,m_name,OBJPROP_NAME,name)) - { - m_name=name; - return(true); - } -//--- failure - return(false); - }; -//+------------------------------------------------------------------+ -//| Attach object | -//+------------------------------------------------------------------+ -bool CChartObject::Attach(long chart_id,const string name,const int window,const int points) - { -//--- check - if(ObjectFind(chart_id,name)<0) - return(false); -//--- attach - if(chart_id==0) - chart_id=ChartID(); - m_chart_id =chart_id; - m_window =window; - m_name =name; - m_num_points=points; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Setting new coordinates of anchor point of an object | -//+------------------------------------------------------------------+ -bool CChartObject::SetPoint(const int point,const datetime time,const double price) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectMove(m_chart_id,m_name,point,time,price)); - } -//+------------------------------------------------------------------+ -//| Delete an object | -//+------------------------------------------------------------------+ -bool CChartObject::Delete(void) - { -//--- checki - if(m_chart_id==-1) - return(false); -//--- actions - bool result=ObjectDelete(m_chart_id,m_name); - Detach(); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Detach object | -//+------------------------------------------------------------------+ -void CChartObject::Detach(void) - { - m_chart_id =-1; - m_window =-1; - m_name =NULL; - m_num_points=0; - } -//+------------------------------------------------------------------+ -//| Get the time coordinate of the specified anchor point of object | -//+------------------------------------------------------------------+ -datetime CChartObject::Time(const int point) const - { -//--- check - if(m_chart_id==-1) - return(0); - if(point>=m_num_points) - return(0); -//--- result - return((datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIME,point)); - } -//+------------------------------------------------------------------+ -//| Set the time coordinate of the specified anchor point of object | -//+------------------------------------------------------------------+ -bool CChartObject::Time(const int point,const datetime time) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_TIME,point,time)); - } -//+------------------------------------------------------------------+ -//| Get the price coordinate of the specified anchor point of object.| -//+------------------------------------------------------------------+ -double CChartObject::Price(const int point) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); - if(point>=m_num_points) - return(EMPTY_VALUE); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_PRICE,point)); - } -//+------------------------------------------------------------------+ -//| Set the price coordinate of the specified anchor point of object.| -//+------------------------------------------------------------------+ -bool CChartObject::Price(const int point,const double price) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_PRICE,point,price)); - } -//+------------------------------------------------------------------+ -//| Get object color | -//+------------------------------------------------------------------+ -color CChartObject::Color(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_COLOR)); - } -//+------------------------------------------------------------------+ -//| Set object color | -//+------------------------------------------------------------------+ -bool CChartObject::Color(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_COLOR,new_color)); - } -//+------------------------------------------------------------------+ -//| Get style of line of object | -//+------------------------------------------------------------------+ -ENUM_LINE_STYLE CChartObject::Style(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_LINE_STYLE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STYLE)); - } -//+------------------------------------------------------------------+ -//| Set style of line of object | -//+------------------------------------------------------------------+ -bool CChartObject::Style(const ENUM_LINE_STYLE new_style) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_STYLE,new_style)); - } -//+------------------------------------------------------------------+ -//| Get width of line of object | -//+------------------------------------------------------------------+ -int CChartObject::Width(void) const - { -//--- check - if(m_chart_id==-1) - return(-1); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_WIDTH)); - } -//+------------------------------------------------------------------+ -//| Set width of line of object | -//+------------------------------------------------------------------+ -bool CChartObject::Width(const int new_width) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_WIDTH,new_width)); - } -//+------------------------------------------------------------------+ -//| Get the "Draw object as background" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Background(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BACK)); - } -//+------------------------------------------------------------------+ -//| Set the "Draw object as background" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Background(const bool new_back) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BACK,new_back)); - } -//+------------------------------------------------------------------+ -//| Get the "Filling" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Fill(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_FILL)); - } -//+------------------------------------------------------------------+ -//| Set the "Filling" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Fill(const bool new_fill) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_FILL,new_fill)); - } -//+------------------------------------------------------------------+ -//| Get the "Z-order" property | -//+------------------------------------------------------------------+ -long CChartObject::Z_Order(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,OBJPROP_ZORDER)); - } -//+------------------------------------------------------------------+ -//| Set the "Z-order" property | -//+------------------------------------------------------------------+ -bool CChartObject::Z_Order(const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ZORDER,value)); - } -//+------------------------------------------------------------------+ -//| Get the "selected" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selected(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTED)); - } -//+------------------------------------------------------------------+ -//| Set the "selected" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selected(const bool new_sel) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_SELECTED,new_sel)); - } -//+------------------------------------------------------------------+ -//| Get the "selectable" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selectable(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE)); - } -//+------------------------------------------------------------------+ -//| Set flag the "selectable" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selectable(const bool new_sel) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE,new_sel)); - } -//+------------------------------------------------------------------+ -//| Get comment of object | -//+------------------------------------------------------------------+ -string CChartObject::Description(void) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_TEXT)); - } -//+------------------------------------------------------------------+ -//| Set comment of object | -//+------------------------------------------------------------------+ -bool CChartObject::Description(const string new_text) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- tune - if(new_text=="") - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TEXT," ")); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TEXT,new_text)); - } -//+------------------------------------------------------------------+ -//| Get tooltip of object | -//+------------------------------------------------------------------+ -string CChartObject::Tooltip(void) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_TOOLTIP)); - } -//+------------------------------------------------------------------+ -//| Set tooltip of object | -//+------------------------------------------------------------------+ -bool CChartObject::Tooltip(const string new_text) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- tune - if(new_text=="") - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TOOLTIP," ")); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TOOLTIP,new_text)); - } -//+------------------------------------------------------------------+ -//| Get the "Timeframes" (visibility) flag | -//+------------------------------------------------------------------+ -int CChartObject::Timeframes(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES)); - } -//+------------------------------------------------------------------+ -//| Set the "Timeframes" (visibility) flag | -//+------------------------------------------------------------------+ -bool CChartObject::Timeframes(const int timeframes) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES,timeframes)); - } -//+------------------------------------------------------------------+ -//| Get time of object creation | -//+------------------------------------------------------------------+ -datetime CChartObject::CreateTime(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CREATETIME)); - } -//+------------------------------------------------------------------+ -//| Get number of levels of object | -//+------------------------------------------------------------------+ -int CChartObject::LevelsCount(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELS)); - } -//+------------------------------------------------------------------+ -//| Set number of levels of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelsCount(const int new_count) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELS,new_count)); - } -//+------------------------------------------------------------------+ -//| Get color of the specified level of object | -//+------------------------------------------------------------------+ -color CChartObject::LevelColor(const int level) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); - if(level>=LevelsCount()) - return(CLR_NONE); -//--- result - return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELCOLOR,level)); - } -//+------------------------------------------------------------------+ -//| Set color of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelColor(const int level,const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELCOLOR,level,new_color)); - } -//+------------------------------------------------------------------+ -//| Get line style of the specified level of object | -//+------------------------------------------------------------------+ -ENUM_LINE_STYLE CChartObject::LevelStyle(const int level) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); - if(level>=LevelsCount()) - return(WRONG_VALUE); -//--- result - return((ENUM_LINE_STYLE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELSTYLE,level)); - } -//+------------------------------------------------------------------+ -//| Set line style of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelStyle(const int level,const ENUM_LINE_STYLE new_style) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELSTYLE,level,new_style)); - } -//+------------------------------------------------------------------+ -//| Get line width of the specified level of object | -//+------------------------------------------------------------------+ -int CChartObject::LevelWidth(const int level) const - { -//--- check - if(m_chart_id==-1) - return(-1); - if(level>=LevelsCount()) - return(-1); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELWIDTH,level)); - } -//+------------------------------------------------------------------+ -//| Set line width of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelWidth(const int level,const int new_width) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELWIDTH,level,new_width)); - } -//+------------------------------------------------------------------+ -//| Get value of the specified level of object | -//+------------------------------------------------------------------+ -double CChartObject::LevelValue(const int level) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); - if(level>=LevelsCount()) - return(EMPTY_VALUE); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_LEVELVALUE,level)); - } -//+------------------------------------------------------------------+ -//| Set value of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelValue(const int level,const double new_value) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_LEVELVALUE,level,new_value)); - } -//+------------------------------------------------------------------+ -//| Get comment of of the specified level of object | -//+------------------------------------------------------------------+ -string CChartObject::LevelDescription(const int level) const - { -//--- check - if(m_chart_id==-1) - return(""); - if(level>=LevelsCount()) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_LEVELTEXT,level)); - } -//+------------------------------------------------------------------+ -//| Set comment to the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelDescription(const int level,const string new_text) const - { -//--- checking - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_LEVELTEXT,level,new_text)); - } -//+------------------------------------------------------------------+ -//| Access function long ObjectGetInteger(...) | -//+------------------------------------------------------------------+ -long CChartObject::GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- - if(modifier==-1) - return(ObjectGetInteger(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetInteger(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,long &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetInteger(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetInteger(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function double ObjectGetDouble(...) | -//+------------------------------------------------------------------+ -double CChartObject::GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- - if(modifier==-1) - return(ObjectGetDouble(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetDouble(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,double &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetDouble(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetDouble(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function string ObjectGetString (...) | -//+------------------------------------------------------------------+ -string CChartObject::GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- - if(modifier==-1) - return(ObjectGetString(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetString(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetString(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,string &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetString(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetString(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetString(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Relative movement of object | -//+------------------------------------------------------------------+ -bool CChartObject::ShiftObject(const datetime d_time,const double d_price) const - { - bool result=true; - int i; -//--- check - if(m_chart_id==-1) - return(false); -//--- move - for(i=0;i=m_num_points) - return(false); -//--- move - datetime time=(datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIME,point); - double price=ObjectGetDouble(m_chart_id,m_name,OBJPROP_PRICE,point); -//--- result - return(ObjectMove(m_chart_id,m_name,point,time+d_time,price+d_price)); - } -//+------------------------------------------------------------------+ -//| Writing object parameters to file | -//+------------------------------------------------------------------+ -bool CChartObject::Save(const int file_handle) - { - int i,len; - int levels; - string str; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write object type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write object name - str=ObjectGetString(m_chart_id,m_name,OBJPROP_NAME); - len=StringLen(str); - if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE) - return(false); - if(len!=0) if(FileWriteString(file_handle,str,len)!=len) - return(false); -//--- write object color - if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_COLOR))!=sizeof(long)) - return(false); -//--- write object line style - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STYLE))!=sizeof(int)) - return(false); -//--- write object line width - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_WIDTH))!=sizeof(int)) - return(false); -//--- write the property value "Background" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BACK),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write the property value "Selectable" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write the property value "Timeframes" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES),INT_VALUE)!=sizeof(int)) - return(false); -//--- write comment - str=ObjectGetString(m_chart_id,m_name,OBJPROP_TEXT); - len=StringLen(str); - if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE) - return(false); - if(len!=0) if(FileWriteString(file_handle,str,len)!=len) - return(false); -//--- write number of points - if(FileWriteInteger(file_handle,m_num_points,INT_VALUE)!=INT_VALUE) - return(false); -//--- write points - for(i=0;i -#include -#include -//+------------------------------------------------------------------+ -//| Class CChartObjectPanel. | -//| Purpose: Class for grouping objects for managing a chart | -//+------------------------------------------------------------------+ -class CChartObjectPanel : public CChartObjectButton - { -protected: - CArrayObj m_attachment; // array of attached objects - CArrayInt m_dX; // array of dX attached objects - CArrayInt m_dY; // array of dY attached objects - bool m_expanded; // collapsed/expanded flag - -public: - CChartObjectPanel(); - ~CChartObjectPanel(); - //--- method for attaching objects - bool Attach(CChartObjectLabel *chart_object); - bool X_Distance(const int X); - int X_Distance(void) const { return(CChartObjectButton::X_Distance()); } - bool Y_Distance(const int Y); - int Y_Distance(void) const { return(CChartObjectButton::Y_Distance()); } - int X_Size() const; - int X_Size(const int Y) const { return(CChartObjectButton::X_Size()); } - int Y_Size() const; - int Y_Size(const int Y) const { return(CChartObjectButton::Y_Size()); } - - int Timeframes(void) const { return(CChartObjectButton::Timeframes()); } - virtual bool Timeframes(const int timeframes); - bool State(const bool state); - bool State(void) const { return(CChartObjectButton::State()); } - bool CheckState(); - -protected: - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CChartObjectPanel::CChartObjectPanel(void) : m_expanded(true) - { - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -void CChartObjectPanel::~CChartObjectPanel(void) - { -//--- All objects added by the method Add(), deleted automatically - } -//+------------------------------------------------------------------+ -//| Method Attach | -//+------------------------------------------------------------------+ -bool CChartObjectPanel::Attach(CChartObjectLabel *chart_object) - { - if(m_attachment.Add(chart_object)) - { - int x,y; - x=chart_object.X_Distance(); - m_dX.Add(chart_object.X_Distance()); - x+=X_Distance(); - chart_object.X_Distance(X_Distance()+chart_object.X_Distance()); - y=CChartObjectButton::Y_Size(); - y+=chart_object.Y_Distance(); - m_dY.Add(chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2); - chart_object.Y_Distance(Y_Distance()+chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2); - return(true); - } -//--- - return(false); - } -//+------------------------------------------------------------------+ -//| Method X_Distance | -//+------------------------------------------------------------------+ -bool CChartObjectPanel::X_Distance(const int X) - { - CChartObjectLabel *chart_object; -//--- - for(int i=0;i -//+------------------------------------------------------------------+ -//| Class CChart. | -//| Purpose: Class of the "Chart" object. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CChart : public CObject - { -protected: - long m_chart_id; // chart identifier -public: - CChart(void); - ~CChart(void); - //--- methods of access to protected data - long ChartId(void) const { return(m_chart_id); } - //--- method of identifying the object - virtual int Type(void) const { return(0x1111); } - //--- methods of access to properties of the chart - //--- common properties - ENUM_CHART_MODE Mode(void) const; - bool Mode(const ENUM_CHART_MODE mode) const; - bool Foreground(void) const; - bool Foreground(const bool foreground) const; - bool Shift(void) const; - bool Shift(const bool shift) const; - double ShiftSize(void) const; - bool ShiftSize(double shift) const; - bool AutoScroll(void) const; - bool AutoScroll(const bool auto_scroll) const; - int Scale(void) const; - bool Scale(int scale) const; - bool ScaleFix(void) const; - bool ScaleFix(const bool scale_fix) const; - bool ScaleFix_11(void) const; - bool ScaleFix_11(const bool scale_fix_11) const; - double FixedMax(void) const; - bool FixedMax(const double fixed_max) const; - double FixedMin(void) const; - bool FixedMin(const double fixed_min) const; - bool ScalePPB(void) const; - bool ScalePPB(const bool scale_ppb) const; - double PointsPerBar(void) const; - bool PointsPerBar(const double points_per_bar) const; - //--- show properties - bool ShowOHLC(void) const; - bool ShowOHLC(const bool show) const; - bool ShowLineBid(void) const; - bool ShowLineBid(const bool show) const; - bool ShowLineAsk(void) const; - bool ShowLineAsk(const bool show) const; - bool ShowLastLine(void) const; - bool ShowLastLine(const bool show) const; - bool ShowPeriodSep(void) const; - bool ShowPeriodSep(const bool show) const; - bool ShowGrid(void) const; - bool ShowGrid(const bool show) const; - ENUM_CHART_VOLUME_MODE ShowVolumes(void) const; - bool ShowVolumes(const ENUM_CHART_VOLUME_MODE show) const; - bool ShowObjectDescr(void) const; - bool ShowObjectDescr(const bool show) const; - bool ShowDateScale(const bool show) const; - bool ShowPriceScale(const bool show) const; - //--- color properties - color ColorBackground(void) const; - bool ColorBackground(const color new_color) const; - color ColorForeground(void) const; - bool ColorForeground(const color new_color) const; - color ColorGrid(void) const; - bool ColorGrid(const color new_color) const; - color ColorBarUp(void) const; - bool ColorBarUp(const color new_color) const; - color ColorBarDown(void) const; - bool ColorBarDown(const color new_color) const; - color ColorCandleBull(void) const; - bool ColorCandleBull(const color new_color) const; - color ColorCandleBear(void) const; - bool ColorCandleBear(const color new_color) const; - color ColorChartLine(void) const; - bool ColorChartLine(const color new_color) const; - color ColorVolumes(void) const; - bool ColorVolumes(const color new_color) const; - color ColorLineBid(void) const; - bool ColorLineBid(const color new_color) const; - color ColorLineAsk(void) const; - bool ColorLineAsk(const color new_color) const; - color ColorLineLast(void) const; - bool ColorLineLast(const color new_color) const; - color ColorStopLevels(void) const; - bool ColorStopLevels(const color new_color) const; - //--- other properties - bool BringToTop(void) const; - bool EventObjectCreate(const bool flag=true) const; - bool EventObjectDelete(const bool flag=true) const; - bool EventMouseMove(const bool flag=true) const; - bool MouseScroll(const bool flag=true) const; - //--- methods of access to READ ONLY properties of the chart - int VisibleBars(void) const; - int WindowsTotal(void) const; - bool WindowIsVisible(const int num) const; - int WindowHandle(void) const; - int FirstVisibleBar(void) const; - int WidthInBars(void) const; - int WidthInPixels(void) const; - int HeightInPixels(const int num) const; - int SubwindowY(const int num) const; - double PriceMin(const int num) const; - double PriceMax(const int num) const; - bool IsObject(void) const; - //--- methods of binding chart - void Attach(void) { m_chart_id=ChartID(); } - void Attach(const long chart) { m_chart_id=chart; } - void FirstChart(void) { m_chart_id=ChartFirst(); } - void NextChart(void) { m_chart_id=ChartNext(m_chart_id); } - long Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe); - void Detach(void) { m_chart_id=-1; } - void Close(void); - //--- navigation method - bool Navigate(const ENUM_CHART_POSITION position,const int shift=0) const; - //--- methods of access to the API functions of MQL5 - string Symbol(void) const { return(ChartSymbol(m_chart_id)); } - ENUM_TIMEFRAMES Period(void) const { return(ChartPeriod(m_chart_id)); } - void Redraw(void) const { ChartRedraw(m_chart_id); } - long GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int sub_window=0) const; - bool GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int sub_window,long &value) const; - bool SetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const long value) const; - double GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int sub_window=0) const; - bool GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int sub_window,double &value) const; - bool SetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const double value) const; - string GetString(const ENUM_CHART_PROPERTY_STRING prop_id) const; - bool GetString(const ENUM_CHART_PROPERTY_STRING prop_id,string &value) const; - bool SetString(const ENUM_CHART_PROPERTY_STRING prop_id,const string value) const; - bool SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) const; - bool ApplyTemplate(const string filename) const; - bool ScreenShot(const string filename,const int width,const int height, - const ENUM_ALIGN_MODE align_mode=ALIGN_RIGHT) const; - int WindowOnDropped(void) const; - double PriceOnDropped(void) const; - datetime TimeOnDropped(void) const; - int XOnDropped(void) const; - int YOnDropped(void) const; - //--- methods for working with indicators - bool IndicatorAdd(const int subwin,const int handle) const; - bool IndicatorDelete(const int subwin,const string name) const; - int IndicatorsTotal(const int subwin) const; - string IndicatorName(const int subwin,const int index) const; - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChart::CChart(void) : m_chart_id(-1) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChart::~CChart(void) - { - if(m_chart_id!=-1) - Close(); - } -//+------------------------------------------------------------------+ -//| Opening chart | -//+------------------------------------------------------------------+ -long CChart::Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe) - { - m_chart_id=ChartOpen(symbol_name,timeframe); - if(m_chart_id==0) - m_chart_id=-1; - return(m_chart_id); - } -//+------------------------------------------------------------------+ -//| Get the type of representation of chart | -//+------------------------------------------------------------------+ -ENUM_CHART_MODE CChart::Mode(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_CHART_MODE)ChartGetInteger(m_chart_id,CHART_MODE)); - } -//+------------------------------------------------------------------+ -//| Set the type of representation chart | -//+------------------------------------------------------------------+ -bool CChart::Mode(const ENUM_CHART_MODE mode) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_MODE,mode)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::Foreground(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_FOREGROUND)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::Foreground(const bool foreground) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_FOREGROUND,foreground)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Shift" property | -//+------------------------------------------------------------------+ -bool CChart::Shift(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHIFT)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Shift"property | -//+------------------------------------------------------------------+ -bool CChart::Shift(const bool shift) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHIFT,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShiftSize" property | -//+------------------------------------------------------------------+ -double CChart::ShiftSize(void) const - { -//--- check - if(m_chart_id==-1) - return(DBL_MAX); -//--- result - return(ChartGetDouble(m_chart_id,CHART_SHIFT_SIZE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShiftSize" property | -//+------------------------------------------------------------------+ -bool CChart::ShiftSize(double shift) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(shift<10) - shift=10; - if(shift>50) - shift=50; -//--- result - return(ChartSetDouble(m_chart_id,CHART_SHIFT_SIZE,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "AutoScroll" property | -//+------------------------------------------------------------------+ -bool CChart::AutoScroll(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_AUTOSCROLL)); - } -//+------------------------------------------------------------------+ -//| Set value of the "AutoScroll" property | -//+------------------------------------------------------------------+ -bool CChart::AutoScroll(const bool auto_scroll) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,auto_scroll)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Scale" property | -//+------------------------------------------------------------------+ -int CChart::Scale(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_SCALE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Scale" property | -//+------------------------------------------------------------------+ -bool CChart::Scale(int shift) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(shift<0) - shift=0; - if(shift>32) - shift=32; -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALE,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScaleFix" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALEFIX)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScaleFix" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix(const bool scale_fix) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALEFIX,scale_fix)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScaleFix_11" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix_11(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALEFIX_11)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScaleFix_11" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix_11(const bool scale_fix_11) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALEFIX_11,scale_fix_11)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FixedMax" property | -//+------------------------------------------------------------------+ -double CChart::FixedMax(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_FIXED_MAX)); - } -//+------------------------------------------------------------------+ -//| Set value of the "FixedMax" property | -//+------------------------------------------------------------------+ -bool CChart::FixedMax(const double fixed_max) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_FIXED_MAX,fixed_max)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FixedMin" property | -//+------------------------------------------------------------------+ -double CChart::FixedMin(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_FIXED_MIN)); - } -//+------------------------------------------------------------------+ -//| Set value of the "FixedMin" property | -//+------------------------------------------------------------------+ -bool CChart::FixedMin(const double fixed_min) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_FIXED_MIN,fixed_min)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScalePointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::ScalePPB(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScalePointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::ScalePPB(const bool scale_ppb) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR,scale_ppb)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PointsPerBar" property | -//+------------------------------------------------------------------+ -double CChart::PointsPerBar(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_POINTS_PER_BAR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "PointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::PointsPerBar(const double points_per_bar) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_POINTS_PER_BAR,points_per_bar)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowOHLC" property | -//+------------------------------------------------------------------+ -bool CChart::ShowOHLC(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_OHLC)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowOHLC" property | -//+------------------------------------------------------------------+ -bool CChart::ShowOHLC(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_OHLC,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLineBid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineBid(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_BID_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLineBid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineBid(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_BID_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLineAsk" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineAsk(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_ASK_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLineAsk" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineAsk(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_ASK_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLastLine" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLastLine(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_LAST_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLastLine" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLastLine(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_LAST_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowPeriodSep" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPeriodSep(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowPeriodSep" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPeriodSep(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowGrid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowGrid(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_GRID)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowGrid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowGrid(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_GRID,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowVolumes" property | -//+------------------------------------------------------------------+ -ENUM_CHART_VOLUME_MODE CChart::ShowVolumes(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_CHART_VOLUME_MODE)ChartGetInteger(m_chart_id,CHART_SHOW_VOLUMES)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowVolumes" property | -//+------------------------------------------------------------------+ -bool CChart::ShowVolumes(const ENUM_CHART_VOLUME_MODE show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_VOLUMES,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowObjectDescr" property | -//+------------------------------------------------------------------+ -bool CChart::ShowObjectDescr(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowObjectDescr" property | -//+------------------------------------------------------------------+ -bool CChart::ShowObjectDescr(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR,show)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowDateScale" property | -//+------------------------------------------------------------------+ -bool CChart::ShowDateScale(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_DATE_SCALE,show)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowPriceScale" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPriceScale(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_PRICE_SCALE,show)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Background" property | -//+------------------------------------------------------------------+ -color CChart::ColorBackground(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_BACKGROUND)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Background" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBackground(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_BACKGROUND,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Foreground" property | -//+------------------------------------------------------------------+ -color CChart::ColorForeground(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_FOREGROUND)); - } -//+------------------------------------------------------------------+ -//| Set color value for the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::ColorForeground(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_FOREGROUND,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Grid" property | -//+------------------------------------------------------------------+ -color CChart::ColorGrid(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_GRID)); - } -//+------------------------------------------------------------------+ -//| Set color value for the "Grid" property | -//+------------------------------------------------------------------+ -bool CChart::ColorGrid(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_GRID,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Bar Up" property | -//+------------------------------------------------------------------+ -color CChart::ColorBarUp(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_UP)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Bar Up" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBarUp(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_UP,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Bar Down" property | -//+------------------------------------------------------------------+ -color CChart::ColorBarDown(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_DOWN)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Bar Down" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBarDown(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_DOWN,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Candle Bull" property | -//+------------------------------------------------------------------+ -color CChart::ColorCandleBull(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CANDLE_BULL)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Candle Bull" property | -//+------------------------------------------------------------------+ -bool CChart::ColorCandleBull(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CANDLE_BULL,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Candle Bear" property | -//+------------------------------------------------------------------+ -color CChart::ColorCandleBear(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CANDLE_BEAR)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Candle Bear" property | -//+------------------------------------------------------------------+ -bool CChart::ColorCandleBear(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CANDLE_BEAR,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Chart Line" property | -//+------------------------------------------------------------------+ -color CChart::ColorChartLine(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_LINE)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Chart Line" property | -//+------------------------------------------------------------------+ -bool CChart::ColorChartLine(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_LINE,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Volumes" property | -//+------------------------------------------------------------------+ -color CChart::ColorVolumes(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Volumes" property | -//+------------------------------------------------------------------+ -bool CChart::ColorVolumes(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_VOLUME,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Bid" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineBid(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_BID)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Bid" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineBid(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_BID,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Ask" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineAsk(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_ASK)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Ask" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineAsk(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_ASK,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Last" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineLast(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_LAST)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Last" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineLast(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_LAST,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Stop Levels" property | -//+------------------------------------------------------------------+ -color CChart::ColorStopLevels(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_STOP_LEVEL)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Stop Levels" property | -//+------------------------------------------------------------------+ -bool CChart::ColorStopLevels(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_STOP_LEVEL,new_color)); - } -//+------------------------------------------------------------------+ -//| Shows chart always on top | -//+------------------------------------------------------------------+ -bool CChart::BringToTop(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_BRING_TO_TOP,true)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of creating objects | -//+------------------------------------------------------------------+ -bool CChart::EventObjectCreate(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_OBJECT_CREATE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of deleting objects | -//+------------------------------------------------------------------+ -bool CChart::EventObjectDelete(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_OBJECT_DELETE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of moving mouse cursor | -//+------------------------------------------------------------------+ -bool CChart::EventMouseMove(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_MOUSE_MOVE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to mouse scrolling | -//+------------------------------------------------------------------+ -bool CChart::MouseScroll(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,flag)); - } -//+------------------------------------------------------------------+ -//| Get value of the "VisibleBars" property | -//+------------------------------------------------------------------+ -int CChart::VisibleBars(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_BARS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowsTotal" property | -//+------------------------------------------------------------------+ -int CChart::WindowsTotal(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOWS_TOTAL)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowIsVisible" property | -//+------------------------------------------------------------------+ -bool CChart::WindowIsVisible(const int num) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_WINDOW_IS_VISIBLE,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowHandle" property | -//+------------------------------------------------------------------+ -int CChart::WindowHandle(void) const - { -//--- check - if(m_chart_id==-1) - return(INVALID_HANDLE); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOW_HANDLE)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FirstVisibleBar" property | -//+------------------------------------------------------------------+ -int CChart::FirstVisibleBar(void) const - { -//--- check - if(m_chart_id==-1) - return(-1); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_FIRST_VISIBLE_BAR)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WidthInBars" property | -//+------------------------------------------------------------------+ -int CChart::WidthInBars(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_BARS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WidthInPixels" property | -//+------------------------------------------------------------------+ -int CChart::WidthInPixels(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_PIXELS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "HeightInPixels" property | -//+------------------------------------------------------------------+ -int CChart::HeightInPixels(const int num) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_HEIGHT_IN_PIXELS,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowYDistance" property | -//+------------------------------------------------------------------+ -int CChart::SubwindowY(const int num) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOW_YDISTANCE,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PriceMin" property | -//+------------------------------------------------------------------+ -double CChart::PriceMin(const int num) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_PRICE_MIN,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PriceMax" property | -//+------------------------------------------------------------------+ -double CChart::PriceMax(const int num) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_PRICE_MAX,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "IsObject" property | -//+------------------------------------------------------------------+ -bool CChart::IsObject(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_IS_OBJECT)); - } -//+------------------------------------------------------------------+ -//| Chart close | -//+------------------------------------------------------------------+ -void CChart::Close(void) - { - if(m_chart_id!=-1) - { - ChartClose(m_chart_id); - m_chart_id=-1; - } - } -//+------------------------------------------------------------------+ -//| Chart navigation | -//+------------------------------------------------------------------+ -bool CChart::Navigate(const ENUM_CHART_POSITION position,const int shift) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartNavigate(m_chart_id,position,shift)); - } -//+------------------------------------------------------------------+ -//| Access functions long ChartGetInteger(...) | -//+------------------------------------------------------------------+ -long CChart::GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int subwindow) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartGetInteger(m_chart_id,prop_id,subwindow)); - } -//+------------------------------------------------------------------+ -//| Access function bool ChartGetInteger(...) | -//+------------------------------------------------------------------+ -bool CChart::GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int subwindow,long &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetInteger(m_chart_id,prop_id,subwindow,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetInteger(...) | -//+------------------------------------------------------------------+ -bool CChart::SetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- - return(ChartSetInteger(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function double ChartGetDouble(...) | -//+------------------------------------------------------------------+ -double CChart::GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int subwindow) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,prop_id,subwindow)); - } -//+------------------------------------------------------------------+ -//| Access function bool ChartGetDouble(...) | -//+------------------------------------------------------------------+ -bool CChart::GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int subwindow,double &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetDouble(m_chart_id,prop_id,subwindow,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetDouble(...) | -//+------------------------------------------------------------------+ -bool CChart::SetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function string ChartGetString(...) | -//+------------------------------------------------------------------+ -string CChart::GetString(const ENUM_CHART_PROPERTY_STRING prop_id) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ChartGetString(m_chart_id,prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions bool ChartGetString(...) | -//+------------------------------------------------------------------+ -bool CChart::GetString(const ENUM_CHART_PROPERTY_STRING prop_id,string &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetString(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetString(...) | -//+------------------------------------------------------------------+ -bool CChart::SetString(const ENUM_CHART_PROPERTY_STRING prop_id,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetString(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetSymbolPeriod(...) | -//+------------------------------------------------------------------+ -bool CChart::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetSymbolPeriod(m_chart_id,symbol,period)); - } -//+------------------------------------------------------------------+ -//| Access function ChartApplyTemplate(...) | -//+------------------------------------------------------------------+ -bool CChart::ApplyTemplate(const string filename) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartApplyTemplate(m_chart_id,filename)); - } -//+------------------------------------------------------------------+ -//| Access function ChartScreenShot(...) | -//+------------------------------------------------------------------+ -bool CChart::ScreenShot(const string filename,const int width,const int height,const ENUM_ALIGN_MODE align_mode) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartScreenShot(m_chart_id,filename,width,height,align_mode)); - } -//+------------------------------------------------------------------+ -//| Access function WindowOnDropped() | -//+------------------------------------------------------------------+ -int CChart::WindowOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartWindowOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access function PriceOnDropped() | -//+------------------------------------------------------------------+ -double CChart::PriceOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartPriceOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access function TimeOnDropped() | -//+------------------------------------------------------------------+ -datetime CChart::TimeOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartTimeOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access functions XOnDropped() | -//+------------------------------------------------------------------+ -int CChart::XOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartXOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access functions YOnDropped() | -//+------------------------------------------------------------------+ -int CChart::YOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartYOnDropped()); - } -//+------------------------------------------------------------------+ -//| Adds indicator to chart | -//+------------------------------------------------------------------+ -bool CChart::IndicatorAdd(const int subwin,const int handle) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartIndicatorAdd(m_chart_id,subwin,handle)); - } -//+------------------------------------------------------------------+ -//| Deletes indicator from chart | -//+------------------------------------------------------------------+ -bool CChart::IndicatorDelete(const int subwin,const string name) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartIndicatorDelete(m_chart_id,subwin,name)); - } -//+------------------------------------------------------------------+ -//| Gets number of indicators in chart subwindow | -//+------------------------------------------------------------------+ -int CChart::IndicatorsTotal(const int subwin) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartIndicatorsTotal(m_chart_id,subwin)); - } -//+------------------------------------------------------------------+ -//| Gets short name of indicator | -//+------------------------------------------------------------------+ -string CChart::IndicatorName(const int subwin,const int index) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ChartIndicatorName(m_chart_id,subwin,index)); - } -//+------------------------------------------------------------------+ -//| Writing parameters of chart to file | -//+------------------------------------------------------------------+ -bool CChart::Save(const int file_handle) - { - string work_str; - int work_int; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write chart type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write chart symbol - work_str=Symbol(); - work_int=StringLen(work_str); - if(FileWriteInteger(file_handle,work_int,INT_VALUE)!=INT_VALUE) - return(false); - if(work_int!=0) if(FileWriteString(file_handle,work_str,work_int)!=work_int) - return(false); -//--- write period of chart - if(FileWriteInteger(file_handle,Period(),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "Mode" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_MODE),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "Foreground" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_FOREGROUND),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "Shift" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHIFT),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShiftSize" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHIFT),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "AutoScroll" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_AUTOSCROLL),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "Scale" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALE),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "ScaleFix" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALEFIX),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ScaleFix_11" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALEFIX_11),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "FixedMax" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_FIXED_MAX))!=sizeof(double)) - return(false); -//--- write value of the "FixedMin" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_FIXED_MIN))!=sizeof(double)) - return(false); -//--- write the "ScalePPB" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "PointsPerBar" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_POINTS_PER_BAR))!=sizeof(double)) - return(false); -//--- write value of the "ShowOHLC" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_OHLC),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLineBid" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_BID_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLineAsk" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_ASK_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLastLine" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_LAST_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowPeriodSep" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowGrid" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_GRID),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowVolumes" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_VOLUMES),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "ShowObjectDescr" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Reading parameters of chart from file | -//+------------------------------------------------------------------+ -bool CChart::Load(const int file_handle) - { - bool resutl=true; - string work_str; - int work_int; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- read and checking start marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)!=-1) return(false); -//--- read and checking chart type - if(FileReadInteger(file_handle,INT_VALUE)!=Type()) return(false); -//--- read chart symbol - work_int=FileReadInteger(file_handle); - if(work_int!=0) work_str=FileReadString(file_handle,work_int); - else work_str=""; -//--- read chart period - work_int=FileReadInteger(file_handle); - SetSymbolPeriod(work_str,(ENUM_TIMEFRAMES)work_int); -//--- read value of the "Mode" property - if(!ChartSetInteger(m_chart_id,CHART_MODE,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "Foreground" property - if(!ChartSetInteger(m_chart_id,CHART_FOREGROUND,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "Shift" property - if(!ChartSetInteger(m_chart_id,CHART_SHIFT,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShiftSize" property - if(!ChartSetInteger(m_chart_id,CHART_SHIFT,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "AutoScroll" property - if(!ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "Scale" property - if(!ChartSetInteger(m_chart_id,CHART_SCALE,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "ScaleFix" property - if(!ChartSetInteger(m_chart_id,CHART_SCALEFIX,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ScaleFix_11" property - if(!ChartSetInteger(m_chart_id,CHART_SCALEFIX_11,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "FixedMax" property - if(!ChartSetDouble(m_chart_id,CHART_FIXED_MAX,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "FixedMin" property - if(!ChartSetDouble(m_chart_id,CHART_FIXED_MIN,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "ScalePPB" property - if(!ChartSetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "PointsPerBar" property - if(!ChartSetDouble(m_chart_id,CHART_POINTS_PER_BAR,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "ShowOHLC" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_OHLC,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLineBid" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_BID_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLineAsk" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_ASK_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLastLine" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_LAST_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowPeriodSep" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowGrid" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_GRID,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowVolumes" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_VOLUMES,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "ShowObjectDescr" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- successful - return(resutl); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/BmpButton.mqh b/Include/Controls/BmpButton.mqh deleted file mode 100644 index 080541d..0000000 --- a/Include/Controls/BmpButton.mqh +++ /dev/null @@ -1,268 +0,0 @@ -//+------------------------------------------------------------------+ -//| BmpButton.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndObj.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CBmpButton | -//| Usage: control that is displayed by | -//| the CChartObjectBmpLabel object | -//+------------------------------------------------------------------+ -class CBmpButton : public CWndObj - { -private: - CChartObjectBmpLabel m_button; // chart object - //--- parameters of the chart object - int m_border; // border width - string m_bmp_off_name; // name of BMP file for the "OFF" state (default state) - string m_bmp_on_name; // name of BMP file for the "ON" state - string m_bmp_passive_name; - string m_bmp_active_name; - -public: - CBmpButton(void); - ~CBmpButton(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- parameters of the chart object - int Border(void) const { return(m_border); } - bool Border(const int value); - bool BmpNames(const string off="",const string on=""); - string BmpOffName(void) const { return(m_bmp_off_name); } - bool BmpOffName(const string name); - string BmpOnName(void) const { return(m_bmp_on_name); } - bool BmpOnName(const string name); - string BmpPassiveName(void) const { return(m_bmp_passive_name); } - bool BmpPassiveName(const string name); - string BmpActiveName(void) const { return(m_bmp_active_name); } - bool BmpActiveName(const string name); - //--- state - bool Pressed(void) const { return(m_button.State()); } - bool Pressed(const bool pressed) { return(m_button.State(pressed)); } - //--- properties - bool Locking(void) const { return(IS_CAN_LOCK); } - void Locking(const bool locking); - -protected: - //--- handlers of object settings - virtual bool OnSetZOrder(void) { return(m_button.Z_Order(m_zorder)); } - //--- internal event handlers - virtual bool OnCreate(void); - virtual bool OnShow(void); - virtual bool OnHide(void); - virtual bool OnMove(void); - virtual bool OnChange(void); - //--- íîâûå îáðàáîò÷èêè - virtual bool OnActivate(void); - virtual bool OnDeactivate(void); - virtual bool OnMouseDown(void); - virtual bool OnMouseUp(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CBmpButton::CBmpButton(void) : m_border(0), - m_bmp_off_name(NULL), - m_bmp_on_name(NULL), - m_bmp_passive_name(NULL), - m_bmp_active_name(NULL) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBmpButton::~CBmpButton(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CBmpButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create the chart object - if(!m_button.Create(chart,name,subwin,x1,y1)) - return(false); -//--- call the settings handler - return(OnChange()); - } -//+------------------------------------------------------------------+ -//| Set border width | -//+------------------------------------------------------------------+ -bool CBmpButton::Border(const int value) - { -//--- save new value of parameter - m_border=value; -//--- set up the chart object - return(m_button.Width(value)); - } -//+------------------------------------------------------------------+ -//| Set two images at once | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpNames(const string off,const string on) - { -//--- save new values of parameters - m_bmp_off_name=off; - m_bmp_on_name =on; -//--- set up the chart object - if(!m_button.BmpFileOff(off)) - return(false); - if(!m_button.BmpFileOn(on)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpOffName(const string name) - { -//--- save new value of parameter - m_bmp_off_name=name; -//--- set up the chart object - if(!m_button.BmpFileOff(name)) - return(false); -//--- set size by image dimensions - Width(m_button.X_Size()); - Height(m_button.Y_Size()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "ON" state | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpOnName(const string name) - { -//--- save new value of parameter - m_bmp_on_name=name; -//--- set up the chart object - if(!m_button.BmpFileOn(name)) - return(false); -//--- set size by image dimensions - Width(m_button.X_Size()); - Height(m_button.Y_Size()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state (passive) | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpPassiveName(const string name) - { -//--- save new value of parameter - m_bmp_passive_name=name; -//--- set up the chart object - if(!IS_ACTIVE) - return(BmpOffName(name)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state (active) | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpActiveName(const string name) - { -//--- save new value of parameter - m_bmp_active_name=name; -//--- set up the chart object - if(IS_ACTIVE) - return(BmpOffName(name)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Locking flag | -//+------------------------------------------------------------------+ -void CBmpButton::Locking(const bool flag) - { - if(flag) - PropFlagsSet(WND_PROP_FLAG_CAN_LOCK); - else - PropFlagsReset(WND_PROP_FLAG_CAN_LOCK); - } -//+------------------------------------------------------------------+ -//| Create object on chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnCreate(void) - { -//--- create the chart object by previously set parameters - return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Display object on chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnShow(void) - { - return(m_button.Timeframes(OBJ_ALL_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Hide object from chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnHide(void) - { - return(m_button.Timeframes(OBJ_NO_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Absolute movement of the chart object | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMove(void) - { -//--- position the chart object - return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Set up the chart object | -//+------------------------------------------------------------------+ -bool CBmpButton::OnChange(void) - { -//--- set up the chart object - return(m_button.Width(m_border) && m_button.BmpFileOff(m_bmp_off_name) && m_button.BmpFileOn(m_bmp_on_name)); - } -//+------------------------------------------------------------------+ -//| Handler of activating the group of controls | -//+------------------------------------------------------------------+ -bool CBmpButton::OnActivate(void) - { - if(m_bmp_active_name!=NULL) - BmpOffName(m_bmp_active_name); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of deactivating the group of controls | -//+------------------------------------------------------------------+ -bool CBmpButton::OnDeactivate(void) - { - if(m_bmp_passive_name!=NULL) - BmpOffName(m_bmp_passive_name); - if(!IS_CAN_LOCK) - Pressed(false); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMouseDown(void) - { - if(!IS_CAN_LOCK) - Pressed(!Pressed()); -//--- call of the method of the parent class - return(CWnd::OnMouseDown()); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMouseUp(void) - { -//--- depress the button if it is not fixed - if(m_button.State() && !IS_CAN_LOCK) - m_button.State(false); -//--- call of the method of the parent class - return(CWnd::OnMouseUp()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/Button.mqh b/Include/Controls/Button.mqh deleted file mode 100644 index 08d5a76..0000000 --- a/Include/Controls/Button.mqh +++ /dev/null @@ -1,146 +0,0 @@ -//+------------------------------------------------------------------+ -//| Button.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndObj.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CButton | -//| Usage: control that is displayed by | -//| the CChartObjectButton object | -//+------------------------------------------------------------------+ -class CButton : public CWndObj - { -private: - CChartObjectButton m_button; // chart object - -public: - CButton(void); - ~CButton(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- state - bool Pressed(void) const { return(m_button.State()); } - bool Pressed(const bool pressed) { return(m_button.State(pressed)); } - //--- properties - bool Locking(void) const { return(IS_CAN_LOCK); } - void Locking(const bool flag); - -protected: - //--- handlers of object settings - virtual bool OnSetText(void) { return(m_button.Description(m_text)); } - virtual bool OnSetColor(void) { return(m_button.Color(m_color)); } - virtual bool OnSetColorBackground(void) { return(m_button.BackColor(m_color_background)); } - virtual bool OnSetColorBorder(void) { return(m_button.BorderColor(m_color_border)); } - virtual bool OnSetFont(void) { return(m_button.Font(m_font)); } - virtual bool OnSetFontSize(void) { return(m_button.FontSize(m_font_size)); } - //--- internal event handlers - virtual bool OnCreate(void); - virtual bool OnShow(void); - virtual bool OnHide(void); - virtual bool OnMove(void); - virtual bool OnResize(void); - //--- íîâûå îáðàáîò÷èêè - virtual bool OnMouseDown(void); - virtual bool OnMouseUp(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CButton::CButton(void) - { - m_color =CONTROLS_BUTTON_COLOR; - m_color_background=CONTROLS_BUTTON_COLOR_BG; - m_color_border =CONTROLS_BUTTON_COLOR_BORDER; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CButton::~CButton(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create the chart object - if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height())) - return(false); -//--- call the settings handler - return(OnChange()); - } -//+------------------------------------------------------------------+ -//| Locking flag | -//+------------------------------------------------------------------+ -void CButton::Locking(const bool flag) - { - if(flag) - PropFlagsSet(WND_PROP_FLAG_CAN_LOCK); - else - PropFlagsReset(WND_PROP_FLAG_CAN_LOCK); - } -//+------------------------------------------------------------------+ -//| Create object on chart | -//+------------------------------------------------------------------+ -bool CButton::OnCreate(void) - { -//--- create the chart object by previously set parameters - return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height())); - } -//+------------------------------------------------------------------+ -//| Display object on chart | -//+------------------------------------------------------------------+ -bool CButton::OnShow(void) - { - return(m_button.Timeframes(OBJ_ALL_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Hide object from chart | -//+------------------------------------------------------------------+ -bool CButton::OnHide(void) - { - return(m_button.Timeframes(OBJ_NO_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Absolute movement of the chart object | -//+------------------------------------------------------------------+ -bool CButton::OnMove(void) - { -//--- position the chart object - return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Resize the chart object | -//+------------------------------------------------------------------+ -bool CButton::OnResize(void) - { -//--- resize the chart object - return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height())); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CButton::OnMouseDown(void) - { - if(!IS_CAN_LOCK) - Pressed(!Pressed()); -//--- call of the method of the parent class - return(CWnd::OnMouseDown()); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CButton::OnMouseUp(void) - { -//--- depress the button if it is not fixed - if(m_button.State() && !IS_CAN_LOCK) - m_button.State(false); -//--- call of the method of the parent class - return(CWnd::OnMouseUp()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/CheckBox.mqh b/Include/Controls/CheckBox.mqh deleted file mode 100644 index e8186fd..0000000 --- a/Include/Controls/CheckBox.mqh +++ /dev/null @@ -1,183 +0,0 @@ -//+------------------------------------------------------------------+ -//| CheckBox.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndContainer.mqh" -#include "BmpButton.mqh" -#include "Edit.mqh" -//+------------------------------------------------------------------+ -//| Resources | -//+------------------------------------------------------------------+ -#resource "res\\CheckBoxOn.bmp" -#resource "res\\CheckBoxOff.bmp" -//+------------------------------------------------------------------+ -//| Class CCheckBox | -//| Usage: class that implements the "CheckBox" control | -//+------------------------------------------------------------------+ -class CCheckBox : public CWndContainer - { -private: - //--- dependent controls - CBmpButton m_button; // button object - CEdit m_label; // label object - //--- data - int m_value; // value - -public: - CCheckBox(void); - ~CCheckBox(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- chart event handler - virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); - //--- settings - string Text(void) const { return(m_label.Text()); } - bool Text(const string value) { return(m_label.Text(value)); } - color Color(void) const { return(m_label.Color()); } - bool Color(const color value) { return(m_label.Color(value)); } - //--- state - bool Checked(void) const { return(m_button.Pressed()); } - bool Checked(const bool flag) { return(m_button.Pressed(flag)); } - //--- data - int Value(void) const { return(m_value); } - void Value(const int value) { m_value=value; } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - -protected: - //--- create dependent controls - virtual bool CreateButton(void); - virtual bool CreateLabel(void); - //--- handlers of the dependent controls events - virtual bool OnClickButton(void); - virtual bool OnClickLabel(void); - }; -//+------------------------------------------------------------------+ -//| Common handler of chart events | -//+------------------------------------------------------------------+ -EVENT_MAP_BEGIN(CCheckBox) - ON_EVENT(ON_CLICK,m_button,OnClickButton) - ON_EVENT(ON_CLICK,m_label,OnClickLabel) -EVENT_MAP_END(CWndContainer) -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCheckBox::CCheckBox(void) : m_value(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCheckBox::~CCheckBox(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CCheckBox::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create dependent controls - if(!CreateButton()) - return(false); - if(!CreateLabel()) - return(false); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| Create button | -//+------------------------------------------------------------------+ -bool CCheckBox::CreateButton(void) - { -//--- calculate coordinates - int x1=CONTROLS_CHECK_BUTTON_X_OFF; - int y1=CONTROLS_CHECK_BUTTON_Y_OFF; - int x2=x1+CONTROLS_BUTTON_SIZE; - int y2=y1+CONTROLS_BUTTON_SIZE-CONTROLS_BORDER_WIDTH; -//--- create - if(!m_button.Create(m_chart_id,m_name+"Button",m_subwin,x1,y1,x2,y2)) - return(false); - if(!m_button.BmpNames("::res\\CheckBoxOff.bmp","::res\\CheckBoxOn.bmp")) - return(false); - if(!Add(m_button)) - return(false); - m_button.Locking(true); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| Create label | -//+------------------------------------------------------------------+ -bool CCheckBox::CreateLabel(void) - { -//--- calculate coordinates - int x1=CONTROLS_CHECK_LABEL_X_OFF; - int y1=CONTROLS_CHECK_LABEL_Y_OFF; - int x2=Width(); - int y2=Height(); -//--- create - if(!m_label.Create(m_chart_id,m_name+"Label",m_subwin,x1,y1,x2,y2)) - return(false); - if(!m_label.Text(m_name)) - return(false); - if(!Add(m_label)) - return(false); - m_label.ReadOnly(true); - m_label.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG); - m_label.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BG); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckBox::Save(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- - FileWriteInteger(file_handle,Checked()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckBox::Load(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- - if(!FileIsEnding(file_handle)) - Checked(FileReadInteger(file_handle)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on button | -//+------------------------------------------------------------------+ -bool CCheckBox::OnClickButton(void) - { -//--- send the "changed state" event - EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on label | -//+------------------------------------------------------------------+ -bool CCheckBox::OnClickLabel(void) - { -//--- change button state - m_button.Pressed(!m_button.Pressed()); -//--- return the result of the button click handler - return(OnClickButton()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/CheckGroup.mqh b/Include/Controls/CheckGroup.mqh deleted file mode 100644 index 6d5de34..0000000 --- a/Include/Controls/CheckGroup.mqh +++ /dev/null @@ -1,377 +0,0 @@ -//+------------------------------------------------------------------+ -//| CheckGroup.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndClient.mqh" -#include "CheckBox.mqh" -#include -#include -#include -//+------------------------------------------------------------------+ -//| Class CCheckGroup | -//| Usage: view and edit group of flags | -//+------------------------------------------------------------------+ -class CCheckGroup : public CWndClient - { -private: - //--- dependent controls - CCheckBox m_rows[]; // array of the row objects - //--- set up - int m_offset; // index of first visible row in array of rows - int m_total_view; // number of visible rows - int m_item_height; // height of visible row - //--- data - CArrayString m_strings; // array of rows - CArrayLong m_values; // array of values - CArrayInt m_states; // array of states - long m_value; // current value - int m_current; // index of current row in array of rows - -public: - CCheckGroup(void); - ~CCheckGroup(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - virtual void Destroy(const int reason=0); - //--- chart event handler - virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); - //--- fill - virtual bool AddItem(const string item,const long value=0); - //--- data - long Value(void) const; - bool Value(const long value); - int Check(const int idx) const; - bool Check(const int idx,const int value); - //--- state - virtual bool Show(void); - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - -protected: - //--- create dependent controls - bool CreateButton(int index); - //--- handlers of the dependent controls events - virtual bool OnVScrollShow(void); - virtual bool OnVScrollHide(void); - virtual bool OnScrollLineDown(void); - virtual bool OnScrollLineUp(void); - virtual bool OnChangeItem(const int row_index); - //--- redraw - bool Redraw(void); - bool RowState(const int index,const bool select); - }; -//+------------------------------------------------------------------+ -//| Common handler of chart events | -//+------------------------------------------------------------------+ -EVENT_MAP_BEGIN(CCheckGroup) - ON_INDEXED_EVENT(ON_CHANGE,m_rows,OnChangeItem) -EVENT_MAP_END(CWndClient) -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCheckGroup::CCheckGroup(void) : m_offset(0), - m_total_view(0), - m_item_height(CONTROLS_LIST_ITEM_HEIGHT), - m_current(CONTROLS_INVALID_INDEX), - m_value(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCheckGroup::~CCheckGroup(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CCheckGroup::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- determine the number of visible rows - m_total_view=(y2-y1)/m_item_height; -//--- check the number of visible rows - if(m_total_view<1) - return(false); -//--- call method of the parent class - if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- set up - if(!m_background.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG)) - return(false); - if(!m_background.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BORDER)) - return(false); -//--- create dependent controls - ArrayResize(m_rows,m_total_view); - for(int i=0;i=m_values.Total()) - return(0); -//--- - return(m_states[idx]); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckGroup::Check(const int idx,const int value) - { -//--- check - if(idx>=m_values.Total()) - return(false); -//--- - bool res=(m_states.Update(idx,value) && Redraw()); -//--- change value - if(res && idx<64) - { - if(m_rows[idx].Checked()) - Value(m_value|m_values.At(idx)); - else - Value(m_value&(~m_values.At(idx))); - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Makes the group visible | -//+------------------------------------------------------------------+ -bool CCheckGroup::Show(void) - { -//--- call of the method of the parent class - if(!CWndClient::Show()) - return(false); -//--- loop by rows - int total=m_values.Total(); - for(int i=total;i=ArraySize(m_rows)) - return(true); -//--- change state - return(m_rows[index].Checked(select)); - } -//+------------------------------------------------------------------+ -//| Handler of the "Show vertical scrollbar" event | -//+------------------------------------------------------------------+ -bool CCheckGroup::OnVScrollShow(void) - { -//--- loop by "rows" - for(int i=0;i}tmYmvAs32IlRE5XvOf51)E-{CU5ECdAuiPlg9p>0}3OqwqO zb_}@EMX9t{#Y#=Vr0HZJ3CW~$`o6cFqOEmO$avw&$=tb|=iGDeOx~Rs^r$h8-%;QL zm%)Jg=kZ*?`zx0Y!L-xBN>AV~_%SyO27p`R8WK-|X>cDr01pA5#{laZ0j|{G^?L7^ zW?S0rwsgB)u`EkbEEY}Qbzc(RTSqlqb)yFQ8;yqKayiN8^NK>DAn|xy48xGofIkE8 zO~A7l0(~9uPuhOdG?kw{h(sc)53Io-2)u#x2DsQ)Ig%avjX(C!K7_+zRYNoyl~SqH z#nO9j`MJkzHmmLc-Mj~k>;uoD)9LKP&HH$2|G{8TVzHPc5{YB@%z3PL9NfQQ)Q`{J zz5~BU+|4un6wt>yHBD2I&yM1w1@zbJy7KcIpx2J}efZb@Z4aHPR7&;2p6eyjuj{%x ze|`feVLk9$$aUK(UnmsndEa&}`fIhCl*>Pbk-gx3;5X51Hl@{S_3XEEo+lPxNA|VM zqL7u$0+^R~WErIAM9VJ9`yAfAona69K9*)5|Jq*vAgP&0XR@_clJwlOy}rwlaOu_4 zs$Sj{QvIu&g8hC`oMmXnrK|Kl&7Y`Ee7 Hzc~*8n19Zv diff --git a/Include/Controls/res/Down.bmp b/Include/Controls/res/Down.bmp deleted file mode 100644 index 5dd180c423f190d9c70582381187e978e6f57bab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@883km8KzDaH@%k1lSg>{LRv<}? m7ND{{d-fbYd>BX))Y8(@0#vgc27qj!2r;&ds)2+60|Nkq^0+4e diff --git a/Include/Controls/res/DownTransp.bmp b/Include/Controls/res/DownTransp.bmp deleted file mode 100644 index ab50187d160e2cbabb695f09a5ece3c04cd28448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N(}lC=(;IR tK{Tmmfb{Iyv*-We!-v5%DQ2{^w1DkgzI^$A7zXJFiIeJ%QT4PA0RRAQFhc+U diff --git a/Include/Controls/res/DropOff.bmp b/Include/Controls/res/DropOff.bmp deleted file mode 100644 index ab50187d160e2cbabb695f09a5ece3c04cd28448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N(}lC=(;IR tK{Tmmfb{Iyv*-We!-v5%DQ2{^w1DkgzI^$A7zXJFiIeJ%QT4PA0RRAQFhc+U diff --git a/Include/Controls/res/DropOn.bmp b/Include/Controls/res/DropOn.bmp deleted file mode 100644 index 11b45f1e2a654eea69990f30f3aa0a1d6944a9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N({;nXlZHrzhJ?F|I3#zhhq>Q yBu=b@LF)JH+4KMK;lp4W#3xoSOdUwi)~#E?Zh?uBN_Tg6lWZ@kc8sd0Bm@9)Krll9 diff --git a/Include/Controls/res/Left.bmp b/Include/Controls/res/Left.bmp deleted file mode 100644 index 1de38acff966cb748ed6f408d37c4a499405278e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@88NQ&UrGXe`^C4~^$^8&5B!v$#J{^i`7#IMbySOI+ diff --git a/Include/Controls/res/LeftTransp.bmp b/Include/Controls/res/LeftTransp.bmp deleted file mode 100644 index dc8ed846c172b41f2d1891d102a74b46014f0529..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$O3)<)T3TBElWWm}1q=RzFgf}` z`u6PE^MCpB>FBo08cG2 ALjV8( diff --git a/Include/Controls/res/RadioButtonOff.bmp b/Include/Controls/res/RadioButtonOff.bmp deleted file mode 100644 index 0c39bbc58d9d7ee608effac793716078b438c63f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 632 zcmZuvO;5r=5Urk#|G>nfzre&RcmIn=e+f;vz_}dYAi?+nNQ(g_tbAA@2+|are$Y}V zczy1yt|rDNZ+ANTW@qNjrcTdy74aSO^@wBd8#~G&w-hDC&-MK;2nSyP2&~uZ1IE}{ zu~;l;G8vyhHu>mG@@RJ)=R{T2LN1qsuIuo9Uw~}#rPJvGafnN?D*w;t^N8aZ@3swR zJ{SBrijX7;G))sRvIe>%S}f3I43=eKwOV1b*@!&|0&t$lBkMI9ItEV+;};X2?;;38 zB-;;cw_8L!hwHj93MMi6g7^=WAOSRbs+xjWeLM>2P3nG zx5+EqxsAZ{;PbnCy`IP+HPa0p?N$S=dKClKhRNe5!)MH<6PSa(0BI%lrG5jRLTLG4J^z~*=|P|x Xve_(XmU3Ql&TGD7{;fr)m{o}iO}^R-2w|E&=iSal`b8uC6?+G-8y>clG#Nl)(WiY&y1Nt zvqT##gkp%!>@Fy=3I;-ZutU4!Fe}T{{nz(SeiqTd^UXW&`+nc|yw5WO7e@9P@zbr= z;|lwCu*Yaukzov|x|{foIH49GMifQIs@3YPLZR@{G|fODvE-zt`{Z4(*UuD-#rL*t z6N|m?KpX&R*Q`}Xc0p*3bAs8$$%!uyp?*Ee}P5KX_VHn0I#;YK; z*wo0p*3bAs8$$O3*9>T3TBEQ)2jn1q=RzFu7(d sU%veRo;`cWHUp&p@ZrP%w{G3~zq`AeWOq<%Kc)VsH2ld8_o1f`05&`@LjV8( diff --git a/Include/Controls/res/SpinDec.bmp b/Include/Controls/res/SpinDec.bmp deleted file mode 100644 index ad4d3d036ee90c672dcb37dc3bbf8128f033a4d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmZ?rwP0cZ12Z700mK48%mKuV3<^M!fq@AqFT@SOV1Xe(ba!|EC)b$^7A*L`b?esu rAevM&KzjD<+4KMK;lp5>6f;^{TEKQLU%vc541@H8#7T7r?bQPS_02Fh diff --git a/Include/Controls/res/SpinInc.bmp b/Include/Controls/res/SpinInc.bmp deleted file mode 100644 index ce0ae600964765232993b06d33d986be749a43b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmZ?rwP0cZ12Z700mK48%mKuV3<^M!fq@AqFT@SOV1YqOw6wJRU$9`o|K-bEA@L@0w;uEVErVgZM>(;Gcx4^_mrMtVkNw$|%J1A2R0A{W*Hvj+t diff --git a/Include/Controls/res/ThumbHor.bmp b/Include/Controls/res/ThumbHor.bmp deleted file mode 100644 index 8c9bed398c71bc8f057cdfd614e8df0420ae50f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmZ?rtzcmQ12Z700mNcJEC9re3=%++fx!tVFT@SOU;!X;jA8&be4ZN)`ZWq^%i~zyRnrOa`)p@w#I<7yy-HGDgi0p*3bAs8$$N}z;5dwcu)rAwFoU%q@fRt%B@ WsX@_%#GzC_l2N0~(GZ|h2mk=wFFNA@ diff --git a/Include/Controls/res/Up.bmp b/Include/Controls/res/Up.bmp deleted file mode 100644 index bfea4cda288065cc9b0e702b9dd8581cb0f46ff3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@883m+-Kub%@f&~kf!vK&C6v1x* qP|cn_dk!By3?zYU{E8v6KxJFEZY5GNL`!#fH!&uUszD0@1_l5;g}5gG diff --git a/Include/Controls/res/UpTransp.bmp b/Include/Controls/res/UpTransp.bmp deleted file mode 100644 index 11b45f1e2a654eea69990f30f3aa0a1d6944a9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N({;nXlZHrzhJ?F|I3#zhhq>Q yBu=b@LF)JH+4KMK;lp4W#3xoSOdUwi)~#E?Zh?uBN_Tg6lWZ@kc8sd0Bm@9)Krll9 diff --git a/Include/DL_CheckHistory.mqh b/Include/DL_CheckHistory.mqh deleted file mode 100644 index 992b7ab2ff7b4b75621eb251861bcb95bdd49785..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5140 zcmd5<+fGwa5S?ce|6vDT+JNFEzKED8MI`|twwmxnDju}4P;Czyg8r}kgu2$Aj(d7; z6fa40LOI=MpSi4Av-b4ok5yTfWx2Tk*RoufYlvo5zDoFyS4XzxKsMyPWO67UHT&%_t81S!av=kXr6~PcZI6=*Q9hM?5=D}L+8XFf0?f>7c91FP4eC2MXsb>vju;2o+5FYSUO zyptDp_OU`6gQ?coowr9lq;@6$6LiusJdEJO?<__c@a7r3XP4}vzR}0obRXHRk-vrB zRY%yxdOvn`00KdJ(;POC`xuwnB%%T5S&%)fFpCi?(8WEKi<&!;7M^X&OWBfL>EJZz zK$qJy5zn3qe4E%FB7zqF6uT79N<%EOc26U!JP+*R$-}&c$Z6JV2OhaTfpy!%?27p3 zvJ?5jxISY40Pl@qpBUXK;ky?xA^I&@a+U*-QGX%E7@$x7WDMBNvn$1Gk)+xkA5PnN}sNaDcAs4N;S*fehGx*IT3v6c#cH6ifp;uFnTh;l$ zoM}1Vl-qYi&1{(&v#@iH48MTyi?~Weu9BmAG)D8=Ix;TyV7rEyn)O!f}T;> zL2qqhzTwQ(L%;3doAE|{`%kYj%}BHNOrh#Mc4Z$PpPJYM!K?3IPPshWvUvJXg~(+3 zN?q$&K*m$I`J6qQ$1W{)s&a^ait6V3-}Ec3tw7V#IbsUeLq~BAr|On@#wXN4WAgzR zwgv28VPzBh+4HK<)lsUdB+jizo%UU#+&KVmU!j_u{P~M$o;SLPU^{ZX+Bb2kQ=K{t zO?in1b%7Ig@nqnhM_4CvrhkSewZ+zm8xiMkFIJS*)v8<-^A0qHc(-FMXtRsRY(g=s zo=N6A;b?r&dBvVvXJ#%sTRZ#h&3BS{^J~TdMYa4nL_Kfe&!#Xx&&_u11 zm*%N+0Z%7(Qybjne^c)&-}>Hs8F>uUlV8y|_om9N6UaT(jw>UawwzWCO^w>WZ51-L zWKS4=T1(4RS8YFMgESwO->T=HJt*KP%}KF( z9$bz}V-umbT)h8QnuYw1svOw;b#sn?_iuCXGp)B= TradingStartMin) - { - IsOperatingHours=true; - } - if(dt.hour > TradingHourStart) - { - IsOperatingHours=true; - } - } - - if(TradingHourStart>TradingHourEnd && ((dt.hour>=TradingHourStart && dt.hour<=23) || (dt.hour<=TradingHourEnd && dt.hour>=0)) && In_Trade) - { - IsOperatingHours=true; - } - - if(IsOperatingHours == false) - { - rangeUpdated = false; - } - } -//+------------------------------------------------------------------+ diff --git a/Include/DL_ClosePositions.mqh b/Include/DL_ClosePositions.mqh deleted file mode 100644 index b262b0f..0000000 --- a/Include/DL_ClosePositions.mqh +++ /dev/null @@ -1,67 +0,0 @@ -//+------------------------------------------------------------------+ -//| DL_ClosePositions.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -CTrade trade; - -// We declare a function CloseOpenPositions of type int and we want to return -// the number of positions that are closed. -void CloseOpenPositions() - { - - int TotalClose=0; // We want to count how many orders have been closed. - int c_slippage = Slippage; - -// Normalization of the slippage. - if(_Digits==3 || _Digits==5) - { - c_slippage=c_slippage*10; - } - - if(TimeToString(LastBarTraded, TIME_DATE) == TimeToString(TimeCurrent(), TIME_DATE)) - return; - -// We scan all the orders backwards. -// This is required as if we start from the first order, we will have problems with the counters and the loop. -// We select the order of index i, selecting by position and from the pool of market/pending trades. - - double accountProfit = AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE); - double accountProfitPercent = (fabs(accountProfit)*100)/AccountInfoDouble(ACCOUNT_BALANCE); - if(accountProfit < 0 && accountProfitPercent >= 10) - { - - - - for(int i=PositionsTotal()-1; i>=0; i--) - { - - ulong ticket = PositionGetTicket(i); - - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - - /*Print("Position profit is ", PositionGetDouble(POSITION_PROFIT)); - if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetDouble(POSITION_PRICE_CURRENT) < upper_boundary || PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetDouble(POSITION_PRICE_CURRENT) < upper_boundary) - { - - }*/ - - // We can use a delay if the execution is too fast. - // Sleep() will wait X milliseconds before proceeding with the code. - // Sleep(300); - } - } - } -//+------------------------------------------------------------------+ diff --git a/Include/DL_EntriesManagement.mqh b/Include/DL_EntriesManagement.mqh deleted file mode 100644 index 8cc157c66b9033d517fc84a1a3edfe3e02ac08bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17430 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 - LotSize=MaxLotSize; -//Limit the lot size in case it is greater than the maximum allowed by the broker - if(LotSize>SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)) - LotSize=SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX); - Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)); -//If the lot size is too small then set it to 0 and don't trade - if(LotSizeMaxStopLoss) - { - IsPreChecksOk=false; - Print("Default Stop Loss must be between Minimum and Maximum Stop Loss Allowed"); - return; - } -//Check if the default take profit you are setting in above the minimum and below the maximum - if(DefaultTakeProfitMaxTakeProfit) - { - IsPreChecksOk=false; - Print("Default Take Profit must be between Minimum and Maximum Take Profit Allowed"); - return; - } -//Check if the Lot Size is between the minimum and maximum - if(DefaultLotSizeMaxLotSize) - { - IsPreChecksOk=false; - Print("Default Lot Size must be between Minimum and Maximum Lot Size Allowed"); - return; - } -//Slippage must be >= 0 - if(Slippage<0) - { - IsPreChecksOk=false; - Print("Slippage must be a positive value"); - return; - } -//MaxSpread must be >= 0 - if(MaxSpread<0) - { - IsPreChecksOk=false; - Print("Maximum Spread must be a positive value"); - return; - } -//MaxRiskPerTrade is a % between 0 and 100 - if(MaxRiskPerTrade<0 || MaxRiskPerTrade>100) - { - IsPreChecksOk=false; - Print("Maximum Risk Per Trade must be a percentage between 0 and 100"); - return; - } - } diff --git a/Include/DL_ScanPositions.mqh b/Include/DL_ScanPositions.mqh deleted file mode 100644 index 4cb5d70..0000000 --- a/Include/DL_ScanPositions.mqh +++ /dev/null @@ -1,49 +0,0 @@ -//+------------------------------------------------------------------+ -//| DL_ScanPositions.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -//Scan all positions to find the ones submitted by the EA -//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails -bool ScanPositions() - { - -//Scan all the orders, retrieving some of the details - TotalOpenOrders = 0; - TotalOpenBuy = 0; - TotalOpenSell = 0; - for(int i=0; iLastBarTraded || LastBarTraded==0) - LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME); - } - Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell); - return true; - } \ No newline at end of file diff --git a/Include/DL_TradeManagement.mqh b/Include/DL_TradeManagement.mqh deleted file mode 100644 index 99524ff..0000000 --- a/Include/DL_TradeManagement.mqh +++ /dev/null @@ -1,20 +0,0 @@ -//+------------------------------------------------------------------+ -//| DL_TradeManagement.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -bool ShouldTrade() - { - //double minProfitAllow = ((AccountInfoDouble(ACCOUNT_BALANCE)*MaxRiskPerTrade)/100)*(TakeProfitPercent*MinStopTradeProfit); -Print("1 Profit ", lt.profit, " Hist time ", lt.time, " current time ", TimeToString(TimeCurrent(), TIME_DATE)); - if(lt.time == TimeToString(TimeCurrent(), TIME_DATE) && lt.profit > 0) - { - Print("2 Profit ", lt.profit); - return false; - } - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/DL_TradingBoundaries.mqh b/Include/DL_TradingBoundaries.mqh deleted file mode 100644 index d3b231b..0000000 --- a/Include/DL_TradingBoundaries.mqh +++ /dev/null @@ -1,112 +0,0 @@ -//+------------------------------------------------------------------+ -//| DL_TradingBoundaries.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -double newHigh, newLow; -bool rangeUpdated = false; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void drawRange() - { - string candles_times; - int time_to_string; - ushort a; - string d_time = TimeToString(iTime(Symb,PERIOD_M5,0), TIME_MINUTES); - string open_hour[]; - string obj_name = "Upper boundary", obj_name_l = "Lower boundary"; - - ArraySetAsSeries(High,true); - CopyHigh(_Symbol,_Period,0,MaxCandleIteration,High); - - ArraySetAsSeries(Low,true); - CopyLow(_Symbol,_Period,0,MaxCandleIteration,Low); - -//--- Get the separator code - a = StringGetCharacter(":",0); - - int k = StringSplit(d_time, a, open_hour); - - if(k>0) - { - server_time = "Server time on last 5 Min candle => Hour = " +open_hour[0]+ ", Minute = " +open_hour[1]; - } - -// Get trading range - for(int j = 0; j <= MaxCandleIteration; j++) - { - string result[]; - candles_times = TimeToString(iTime(Symb,_Period,j), TIME_MINUTES); - time_to_string = StringSplit(candles_times, a, result); - //Print("Is trading boundary "+(result[0] == TradingBoundaryHour && result[1] == TradingBoundaryMin)); - if(result[0] == TradingBoundaryHour && result[1] == TradingBoundaryMin) - { - if(!rangeUpdated) - { - upper_boundary = iHigh(Symb, _Period, j) + rangemargin; - lower_boundary = iLow(Symb, _Period, j)- rangemargin; - } - - UpdateRange(); - //Print("Iteration no "+iTime(Symb,PERIOD_M5,j)); - ObjectCreate(current_chart_id, obj_name, OBJ_HLINE, 0, iTime(Symb,_Period,j), upper_boundary); - - //--- set color to Red - ObjectSetInteger(current_chart_id, obj_name, OBJPROP_COLOR, clrRed); - //--- set object width - ObjectSetInteger(current_chart_id, obj_name, OBJPROP_WIDTH, 2); - //--- Move the line - ObjectMove(current_chart_id, obj_name, 0, iTime(Symb,_Period,j), upper_boundary); - - ObjectCreate(current_chart_id, obj_name_l, OBJ_HLINE, 0, iTime(Symb,_Period,j), lower_boundary); - - //--- set color to Red - ObjectSetInteger(current_chart_id, obj_name_l, OBJPROP_COLOR, clrRed); - //--- set object width - ObjectSetInteger(current_chart_id, obj_name_l, OBJPROP_WIDTH, 2); - //--- Move the line - ObjectMove(current_chart_id, obj_name_l, 0, iTime(Symb,_Period,j), lower_boundary); - - if(!rangedetection) - { - upper_boundary = upperboundary; - lower_boundary = lowerboundary; - } - - //Print("upper_boundary ", upper_boundary, " lower_boundary ", lower_boundary); - //Print("Real high ", iHigh(Symb, PERIOD_M5, j), " Real low ", iLow(Symb, PERIOD_M5, j), " as of ", TimeToString(iTime(Symb,PERIOD_M5, j))); - In_Trade = true; - rangeScope = fabs(upper_boundary-lower_boundary); - break; - } - ObjectDelete(current_chart_id, obj_name_l); - ObjectDelete(current_chart_id, obj_name); - In_Trade = false; - } - } -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void UpdateRange() - { - newHigh = iHigh(Symb, PERIOD_CURRENT, 0); - newLow = iLow(Symb, PERIOD_CURRENT, 0); - Print("Updating range high from ", upper_boundary, "to ", newHigh, " and low from ", lower_boundary, " to ", newLow); - if(newHigh > upper_boundary && TotalOpenBuy > 0) - { - upper_boundary = newHigh; - rangeUpdated = true; - } - if(lower_boundary > newLow && TotalOpenSell > 0) - { - lower_boundary = newLow; - rangeUpdated = true; - } - } -//+------------------------------------------------------------------+ diff --git a/Include/E_CheckHistory.mqh b/Include/E_CheckHistory.mqh deleted file mode 100644 index aa967ff0957a7cbffdf4a11b375ae5b73ff64be2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4886 zcmd5=T~8B16ur+T{)e$9rVW)36JJC~lvX7HA-0(CL@F%USSWV4ng;#9@+Z`D=JqIzMZSppr=uxHvL){&kz@HFucRxf zWYU*`jAU8PB(c<9mD4HoIQ(#pZl`5 zZ-yK=Z*egj6(HcYb5!w&nPx!`IJiL0<2+P6F6N1~%3ah-JpoEjy?;b&?BV~q50$z| zNHq3XB%A&RyUv&O#mw0!a6%WX>`MDXRcgM<>E+e0J10Z%G#Q<2t|Nma_Ll@Kv;pp4 zk5-fShw={JknK5?wOB`4VPyw1l+hjc2D^*pv464G1pO(P?;INX&=IdJTIulR2-=h1 ztYSZ+j?s7>(XE!Bpg&Ewu!Z@KXJLm3IBAc4*n;l^43)`|=&r^pSxU?%8SB zBU7p3T~pr3w(Lm*-MfK4TFY6S@8bNLu|0+bRs1w|!JhgITk>*;KC0~BHn>xuUp@Gg z*V=$a&Zm%WYv^4Ze^wxKkjbvc3~jr_Oc&n{po4K*%YCu$W5VcHr4mVYh>YrU-bROh z67OUjR&%cr>@`b5?oMIJ0CIzu-7!`v^J(<$IwW0>ZWt`vc50v7R-r3_aaSWtD)r4bRbWl_++OfZGFP zlP5KvVCVUw1q*gCoIJoVj?i6zlY3s%D$ZPGjHGca<0XCDgC)!O+5RE!#Pde10Y+f7 zEK(|Y@@l$tN1@#;&ogxGq#}%RS;~CB4q+L3b$C`C0T15WjNwL^Lxn>jdM3^z8 zp^g!?IpT}R}&&|%#*NL9Y$QNhBv)+*h7U`7q6A8y}DgXcg diff --git a/Include/E_ClosePositions.mqh b/Include/E_ClosePositions.mqh deleted file mode 100644 index 7b061e4..0000000 --- a/Include/E_ClosePositions.mqh +++ /dev/null @@ -1,81 +0,0 @@ -//+------------------------------------------------------------------+ -//| E_ClosePositions.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -CTrade trade; - -// We declare a function CloseOpenPositions of type int and we want to return -// the number of positions that are closed. -void CloseOpenPositions() - { - - int TotalClose=0; // We want to count how many orders have been closed. - int c_slippage = Slippage; -Print("Close position status ", ClosePosition); -// Normalization of the slippage. - if(_Digits==3 || _Digits==5) - { - c_slippage=c_slippage*10; - } - -// We scan all the orders backwards. -// This is required as if we start from the first order, we will have problems with the counters and the loop. - for(int i=PositionsTotal()-1; i>=0; i--) - { - - ulong ticket = PositionGetTicket(i); - - Print("Position profit is ", PositionGetDouble(POSITION_PROFIT)); - PositionProfit = PositionGetDouble(POSITION_PROFIT); - if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - - if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - - if(ClosePosition) - { - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - ClosePosition = false; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - // We can use a delay if the execution is too fast. - // Sleep() will wait X milliseconds before proceeding with the code. - // Sleep(300); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/E_EntriesManagement.mqh b/Include/E_EntriesManagement.mqh deleted file mode 100644 index d69973d97d3cdc9ef5640bd721ceb171be5e4681..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20382 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 F@L#s;__F{2 diff --git a/Include/E_ScanPositions.mqh b/Include/E_ScanPositions.mqh deleted file mode 100644 index 53f5789..0000000 --- a/Include/E_ScanPositions.mqh +++ /dev/null @@ -1,49 +0,0 @@ -//+------------------------------------------------------------------+ -//| E_ScanPositions.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -//Scan all positions to find the ones submitted by the EA -//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails -bool ScanPositions() - { - -//Scan all the orders, retrieving some of the details - TotalOpenOrders = 0; - TotalOpenBuy = 0; - TotalOpenSell = 0; - for(int i=0; iLastBarTraded || LastBarTraded==0) - LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME); - } - Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell); - return true; - } \ No newline at end of file diff --git a/Include/E_TradeManagement.mqh b/Include/E_TradeManagement.mqh deleted file mode 100644 index 9b95978..0000000 --- a/Include/E_TradeManagement.mqh +++ /dev/null @@ -1,57 +0,0 @@ -//+------------------------------------------------------------------+ -//| E_TradeManagement.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -//Done for the day after a profitable trade -//If closed trade was opened the day before, look for trade opportunities -double minProfitAllow = AccountInfoDouble(ACCOUNT_BALANCE)*(Breakevent/100); -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void TradeManager() - { - CanSell = true; - CanBuy = true; - - if(lt.time == TimeToString(TimeCurrent(), TIME_DATE)) - { - if(lt.type == DEAL_TYPE_BUY && lt.profit < 0) - { - CanBuy = false; - } - if(lt.type = DEAL_TYPE_SELL && lt.profit < 0) - { - CanSell = false; - } - } - } -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void ProfitRunner() - { - Print("Min acceptablbe profit ", minProfitAllow); - ClosePosition = false; - if(PositionProfit > minProfitAllow) - FollowProfit=true; - - if(FollowProfit) - { - if(Kijunsen > iClose(Symb, _Period, 1) && TotalOpenBuy > 0) - { - ClosePosition = true; - } - if(Kijunsen < iClose(Symb, _Period, 1) && TotalOpenSell > 0) - { - ClosePosition = true; - } - } - Print("Looking to close this position ", ClosePosition, " Follow profit ", FollowProfit); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Expert.mqh b/Include/Expert/Expert.mqh deleted file mode 100644 index 0b1e844e53cbb2332eaf87e5f1cb0fea7aa55b3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122604 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 diff --git a/Include/Expert/ExpertBase.mqh b/Include/Expert/ExpertBase.mqh deleted file mode 100644 index 2edde23..0000000 --- a/Include/Expert/ExpertBase.mqh +++ /dev/null @@ -1,715 +0,0 @@ -//+------------------------------------------------------------------+ -//| ExpertBase.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include -#include -#include -#include -#include -//+------------------------------------------------------------------+ -//| enumerations | -//+------------------------------------------------------------------+ -//--- constants of identification of trend -enum ENUM_TYPE_TREND - { - TYPE_TREND_HARD_DOWN =0, // strong down trend - TYPE_TREND_DOWN =1, // down trend - TYPE_TREND_SOFT_DOWN =2, // weak down trend - TYPE_TREND_FLAT =3, // no trend - TYPE_TREND_SOFT_UP =4, // weak up trend - TYPE_TREND_UP =5, // up trend - TYPE_TREND_HARD_UP =6 // strong up trend - }; -//--- flags of used timeseries -enum ENUM_USED_SERIES - { - USE_SERIES_OPEN =0x1, - USE_SERIES_HIGH =0x2, - USE_SERIES_LOW =0x4, - USE_SERIES_CLOSE =0x8, - USE_SERIES_SPREAD =0x10, - USE_SERIES_TIME =0x20, - USE_SERIES_TICK_VOLUME=0x40, - USE_SERIES_REAL_VOLUME=0x80 - }; -//--- phases of initialization of an object -enum ENUM_INIT_PHASE - { - INIT_PHASE_FIRST =0, // start phase (only Init(...) can be called) - INIT_PHASE_TUNING =1, // phase of tuning (set in Init(...)) - INIT_PHASE_VALIDATION =2, // phase of checking of parameters(set in ValidationSettings(...)) - INIT_PHASE_COMPLETE =3 // end phase (set in InitIndicators(...)) - }; -//+------------------------------------------------------------------+ -//| Macro definitions. | -//+------------------------------------------------------------------+ -//--- check the use of timeseries -#define IS_OPEN_SERIES_USAGE ((m_used_series&USE_SERIES_OPEN)!=0) -#define IS_HIGH_SERIES_USAGE ((m_used_series&USE_SERIES_HIGH)!=0) -#define IS_LOW_SERIES_USAGE ((m_used_series&USE_SERIES_LOW)!=0) -#define IS_CLOSE_SERIES_USAGE ((m_used_series&USE_SERIES_CLOSE)!=0) -#define IS_SPREAD_SERIES_USAGE ((m_used_series&USE_SERIES_SPREAD)!=0) -#define IS_TIME_SERIES_USAGE ((m_used_series&USE_SERIES_TIME)!=0) -#define IS_TICK_VOLUME_SERIES_USAGE ((m_used_series&USE_SERIES_TICK_VOLUME)!=0) -#define IS_REAL_VOLUME_SERIES_USAGE ((m_used_series&USE_SERIES_REAL_VOLUME)!=0) -//+------------------------------------------------------------------+ -//| Class CExpertBase. | -//| Purpose: Base class of component of Expert Advisor. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CExpertBase : public CObject - { -protected: - //--- variables - ulong m_magic; // expert magic number - ENUM_INIT_PHASE m_init_phase; // the phase (stage) of initialization of object - bool m_other_symbol; // flag of a custom work symbols (different from one of the Expert Advisor) - CSymbolInfo *m_symbol; // pointer to the object-symbol - bool m_other_period; // flag of a custom timeframe (different from one of the Expert Advisor) - ENUM_TIMEFRAMES m_period; // work timeframe - double m_adjusted_point; // "weight" 2/4 of a point - CAccountInfo m_account; // object-deposit - ENUM_ACCOUNT_MARGIN_MODE m_margin_mode; // netting or hedging - ENUM_TYPE_TREND m_trend_type; // identifier of trend - bool m_every_tick; // flag of starting the analysis from current (incomplete) bar - //--- timeseries - int m_used_series; // flags of using of series - CiOpen *m_open; // pointer to the object for access to open prices of bars - CiHigh *m_high; // pointer to the object for access to high prices of bars - CiLow *m_low; // pointer to the object for access to low prices of bars - CiClose *m_close; // pointer to the object for access to close prices of bars - CiSpread *m_spread; // pointer to the object for access to spreads - CiTime *m_time; // pointer to the object for access to time of closing of bars - CiTickVolume *m_tick_volume; // pointer to the object for access to tick volumes of bars - CiRealVolume *m_real_volume; // pointer to the object for access to real volumes of bars - -public: - CExpertBase(void); - ~CExpertBase(void); - //--- methods of access to protected data - ENUM_INIT_PHASE InitPhase(void) const { return(m_init_phase); } - void TrendType(ENUM_TYPE_TREND value) { m_trend_type=value; } - int UsedSeries(void) const; - void EveryTick(bool value) { m_every_tick=value; } - //--- methods of access to protected data - double Open(int ind) const; - double High(int ind) const; - double Low(int ind) const; - double Close(int ind) const; - int Spread(int ind) const; - datetime Time(int ind) const; - long TickVolume(int ind) const; - long RealVolume(int ind) const; - //--- methods of initialization of the object - virtual bool Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point); - bool Symbol(string name); - bool Period(ENUM_TIMEFRAMES value); - void Magic(ulong value) { m_magic=value; } - void SetMarginMode(void) { m_margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); } - //--- method of verification of settings - virtual bool ValidationSettings(); - //--- methods of creating the indicator and timeseries - virtual bool SetPriceSeries(CiOpen *open,CiHigh *high,CiLow *low,CiClose *close); - virtual bool SetOtherSeries(CiSpread *spread,CiTime *time,CiTickVolume *tick_volume,CiRealVolume *real_volume); - virtual bool InitIndicators(CIndicators *indicators=NULL); - -protected: - //--- methods initialization of timeseries - bool InitOpen(CIndicators *indicators); - bool InitHigh(CIndicators *indicators); - bool InitLow(CIndicators *indicators); - bool InitClose(CIndicators *indicators); - bool InitSpread(CIndicators *indicators); - bool InitTime(CIndicators *indicators); - bool InitTickVolume(CIndicators *indicators); - bool InitRealVolume(CIndicators *indicators); - //--- method of getting the measure units of price levels - virtual double PriceLevelUnit(void) { return(m_adjusted_point); } - //--- method of getting index of bar the analysis starts with - virtual int StartIndex(void) { return((m_every_tick?0:1)); } - virtual bool CompareMagic(ulong magic) { return(m_magic==magic); } - bool IsHedging(void) const { return(m_margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CExpertBase::CExpertBase(void) : m_magic(0), - m_margin_mode(ACCOUNT_MARGIN_MODE_RETAIL_NETTING), - m_init_phase(INIT_PHASE_FIRST), - m_other_symbol(false), - m_symbol(NULL), - m_other_period(false), - m_period(PERIOD_CURRENT), - m_adjusted_point(1.0), - m_trend_type(TYPE_TREND_FLAT), - m_every_tick(false), - m_used_series(0), - m_open(NULL), - m_high(NULL), - m_low(NULL), - m_close(NULL), - m_spread(NULL), - m_time(NULL), - m_tick_volume(NULL), - m_real_volume(NULL) - - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CExpertBase::~CExpertBase(void) - { -//--- if the symbol is "custom", delete it - if(m_other_symbol && m_symbol!=NULL) - delete m_symbol; -//--- release of "custom" timeseries - if(m_other_symbol || m_other_period) - { - if(IS_OPEN_SERIES_USAGE && CheckPointer(m_open)==POINTER_DYNAMIC) - delete m_open; - if(IS_HIGH_SERIES_USAGE && CheckPointer(m_high)==POINTER_DYNAMIC) - delete m_high; - if(IS_LOW_SERIES_USAGE && CheckPointer(m_low)==POINTER_DYNAMIC) - delete m_low; - if(IS_CLOSE_SERIES_USAGE && CheckPointer(m_close)==POINTER_DYNAMIC) - delete m_close; - if(IS_SPREAD_SERIES_USAGE && CheckPointer(m_spread)==POINTER_DYNAMIC) - delete m_spread; - if(IS_TIME_SERIES_USAGE && CheckPointer(m_time)==POINTER_DYNAMIC) - delete m_time; - if(IS_TICK_VOLUME_SERIES_USAGE && CheckPointer(m_tick_volume)==POINTER_DYNAMIC) - delete m_tick_volume; - if(IS_REAL_VOLUME_SERIES_USAGE && CheckPointer(m_real_volume)==POINTER_DYNAMIC) - delete m_real_volume; - } - } -//+------------------------------------------------------------------+ -//| Get flags of used timeseries | -//+------------------------------------------------------------------+ -int CExpertBase::UsedSeries(void) const - { - if(m_other_symbol || m_other_period) - return(0); -//--- - return(m_used_series); - } -//+------------------------------------------------------------------+ -//| Initialization of object. | -//+------------------------------------------------------------------+ -bool CExpertBase::Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point) - { -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_FIRST) - { - Print(__FUNCTION__+": attempt of re-initialization"); - return(false); - } -//--- check of pointer - if(symbol==NULL) - { - Print(__FUNCTION__+": error initialization"); - return(false); - } -//--- initialization - m_symbol =symbol; - m_period =period; - m_adjusted_point=point; - m_other_symbol =false; - m_other_period =false; - SetMarginMode(); -//--- primary initialization is successful, pass to the phase of tuning - m_init_phase=INIT_PHASE_TUNING; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Changing work symbol. | -//+------------------------------------------------------------------+ -bool CExpertBase::Symbol(string name) - { -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_TUNING) - { - Print(__FUNCTION__+": changing of symbol is forbidden"); - return(false); - } - if(m_symbol!=NULL) - { - //--- symbol has been already set - if(m_symbol.Name()==name) - return(true); - //--- symbol is not the one required, but is already "custom" - if(m_other_symbol) - { - if(!m_symbol.Name(name)) - { - //--- failed to initialize the symbol - delete m_symbol; - return(false); - } - return(true); - } - } - m_symbol=new CSymbolInfo; -//--- check of pointer - if(m_symbol==NULL) - { - Print(__FUNCTION__+": error of changing of symbol"); - return(false); - } - if(!m_symbol.Name(name)) - { - //--- failed to initialize the symbol - delete m_symbol; - return(false); - } - m_other_symbol=true; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Changing work timeframe. | -//+------------------------------------------------------------------+ -bool CExpertBase::Period(ENUM_TIMEFRAMES value) - { -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_TUNING) - { - Print(__FUNCTION__+": changing of timeframe is forbidden"); - return(false); - } - if(m_period==value) - return(true); -//--- change work timeframe - m_period=value; - m_other_period=true; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Checking adjustable parameters | -//+------------------------------------------------------------------+ -bool CExpertBase::ValidationSettings() - { -//--- rechecking parameters - if(m_init_phase==INIT_PHASE_VALIDATION) - return(true); -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_TUNING) - { - Print(__FUNCTION__+": not the right time to check parameters"); - return(false); - } -//--- initial check of parameters is successful, phase of tuning is over - m_init_phase=INIT_PHASE_VALIDATION; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Setting pointers of price timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::SetPriceSeries(CiOpen *open,CiHigh *high,CiLow *low,CiClose *close) - { -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_VALIDATION) - { - Print(__FUNCTION__+": changing of timeseries is forbidden"); - return(false); - } -//--- check pointers - if((IS_OPEN_SERIES_USAGE && open==NULL) || - (IS_HIGH_SERIES_USAGE && high==NULL) || - (IS_LOW_SERIES_USAGE && low==NULL) || - (IS_CLOSE_SERIES_USAGE && close==NULL)) - { - Print(__FUNCTION__+": NULL pointer"); - return(false); - } - m_open =open; - m_high =high; - m_low =low; - m_close=close; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Setting pointers of other timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::SetOtherSeries(CiSpread *spread,CiTime *time,CiTickVolume *tick_volume,CiRealVolume *real_volume) - { -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_VALIDATION) - { - Print(__FUNCTION__+": changing of timeseries is forbidden"); - return(false); - } -//--- check pointers - if((IS_SPREAD_SERIES_USAGE && spread==NULL) || - (IS_TIME_SERIES_USAGE && time==NULL) || - (IS_TICK_VOLUME_SERIES_USAGE && tick_volume==NULL) || - (IS_REAL_VOLUME_SERIES_USAGE && real_volume==NULL)) - { - Print(__FUNCTION__+": NULL pointer"); - return(false); - } - m_spread =spread; - m_time =time; - m_tick_volume=tick_volume; - m_real_volume=real_volume; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of indicators and timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitIndicators(CIndicators *indicators) - { -//--- this call is for compatibility with the previous version - if(!ValidationSettings()) - return(false); -//--- check the initialization phase - if(m_init_phase!=INIT_PHASE_VALIDATION) - { - Print(__FUNCTION__+": parameters of setting are not checked"); - return(false); - } - if(!m_other_symbol && !m_other_period) - return(true); -//--- check pointers - if(m_symbol==NULL) - return(false); - if(indicators==NULL) - return(false); -//--- initialization of required timeseries - if(IS_OPEN_SERIES_USAGE && !InitOpen(indicators)) - return(false); - if(IS_HIGH_SERIES_USAGE && !InitHigh(indicators)) - return(false); - if(IS_LOW_SERIES_USAGE && !InitLow(indicators)) - return(false); - if(IS_CLOSE_SERIES_USAGE && !InitClose(indicators)) - return(false); - if(IS_SPREAD_SERIES_USAGE && !InitSpread(indicators)) - return(false); - if(IS_TIME_SERIES_USAGE && !InitTime(indicators)) - return(false); - if(IS_TICK_VOLUME_SERIES_USAGE && !InitTickVolume(indicators)) - return(false); - if(IS_REAL_VOLUME_SERIES_USAGE && !InitRealVolume(indicators)) - return(false); -//--- initialization of object (from the point of view of the base class) has been performed successfully -//--- now it's impossible to change anything in the settings - m_init_phase=INIT_PHASE_COMPLETE; -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Access to data of the Open timeseries. | -//+------------------------------------------------------------------+ -double CExpertBase::Open(int ind) const - { -//--- check pointer - if(m_open==NULL) - return(EMPTY_VALUE); -//--- return the result - return(m_open.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the High timeseries. | -//+------------------------------------------------------------------+ -double CExpertBase::High(int ind) const - { -//--- check pointer - if(m_high==NULL) - return(EMPTY_VALUE); -//--- return the result - return(m_high.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the Low timeseries. | -//+------------------------------------------------------------------+ -double CExpertBase::Low(int ind) const - { -//--- check pointer - if(m_low==NULL) - return(EMPTY_VALUE); -//--- return the result - return(m_low.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the Close timeseries. | -//+------------------------------------------------------------------+ -double CExpertBase::Close(int ind) const - { -//--- check pointer - if(m_close==NULL) - return(EMPTY_VALUE); -//--- return the result - return(m_close.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the Spread timeseries. | -//+------------------------------------------------------------------+ -int CExpertBase::Spread(int ind) const - { -//--- check pointer - if(m_spread==NULL) - return(INT_MAX); -//--- return the result - return(m_spread.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the Time timeseries. | -//+------------------------------------------------------------------+ -datetime CExpertBase::Time(int ind) const - { -//--- check pointer - if(m_time==NULL) - return(0); -//--- return the result - return(m_time.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the TickVolume timeseries. | -//+------------------------------------------------------------------+ -long CExpertBase::TickVolume(int ind) const - { -//--- check pointer - if(m_tick_volume==NULL) - return(0); -//--- return the result - return(m_tick_volume.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Access to data of the RealVolume timeseries. | -//+------------------------------------------------------------------+ -long CExpertBase::RealVolume(int ind) const - { -//--- check pointer - if(m_real_volume==NULL) - return(0); -//--- return the result - return(m_real_volume.GetData(ind)); - } -//+------------------------------------------------------------------+ -//| Initialization of the Open timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitOpen(CIndicators *indicators) - { -//--- create object - if((m_open=new CiOpen)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_open)) - { - Print(__FUNCTION__+": error adding object"); - delete m_open; - return(false); - } -//--- initialize object - if(!m_open.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the High timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitHigh(CIndicators *indicators) - { -//--- create object - if((m_high=new CiHigh)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_high)) - { - Print(__FUNCTION__+": error adding object"); - delete m_high; - return(false); - } -//--- initialize object - if(!m_high.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the Low timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitLow(CIndicators *indicators) - { -//--- create object - if((m_low=new CiLow)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_low)) - { - Print(__FUNCTION__+": error adding object"); - delete m_low; - return(false); - } -//--- initialize object - if(!m_low.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the Close timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitClose(CIndicators *indicators) - { -//--- create object - if((m_close=new CiClose)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_close)) - { - Print(__FUNCTION__+": error adding object"); - delete m_close; - return(false); - } -//--- initialize object - if(!m_close.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the Spread timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitSpread(CIndicators *indicators) - { -//--- create object - if((m_spread=new CiSpread)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_spread)) - { - Print(__FUNCTION__+": error adding object"); - delete m_spread; - return(false); - } -//--- initialize object - if(!m_spread.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the Time timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitTime(CIndicators *indicators) - { -//--- create object - if((m_time=new CiTime)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_time)) - { - Print(__FUNCTION__+": error adding object"); - delete m_time; - return(false); - } -//--- initialize object - if(!m_time.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the TickVolume timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitTickVolume(CIndicators *indicators) - { -//--- create object - if((m_tick_volume=new CiTickVolume)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_tick_volume)) - { - Print(__FUNCTION__+": error adding object"); - delete m_tick_volume; - return(false); - } -//--- initialize object - if(!m_tick_volume.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialization of the RealVolume timeseries. | -//+------------------------------------------------------------------+ -bool CExpertBase::InitRealVolume(CIndicators *indicators) - { -//--- create object - if((m_real_volume=new CiRealVolume)==NULL) - { - Print(__FUNCTION__+": error creating object"); - return(false); - } -//--- add object to collection - if(!indicators.Add(m_real_volume)) - { - Print(__FUNCTION__+": error adding object"); - delete m_real_volume; - return(false); - } -//--- initialize object - if(!m_real_volume.Create(m_symbol.Name(),m_period)) - { - Print(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/ExpertMoney.mqh b/Include/Expert/ExpertMoney.mqh deleted file mode 100644 index 393f832..0000000 --- a/Include/Expert/ExpertMoney.mqh +++ /dev/null @@ -1,124 +0,0 @@ -//+------------------------------------------------------------------+ -//| ExpertMoney.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ExpertBase.mqh" -//+------------------------------------------------------------------+ -//| Class CExpertMoney. | -//| Purpose: Base class money managment. | -//| Derives from class CExpertBase. | -//+------------------------------------------------------------------+ -class CExpertMoney : public CExpertBase - { -protected: - //--- input parameters - double m_percent; - -public: - CExpertMoney(void); - ~CExpertMoney(void); - //--- methods of setting adjustable parameters - void Percent(double percent) { m_percent=percent; } - //--- method of verification of settings - virtual bool ValidationSettings(); - //--- - virtual double CheckOpenLong(double price,double sl); - virtual double CheckOpenShort(double price,double sl); - virtual double CheckReverse(CPositionInfo *position,double sl); - virtual double CheckClose(CPositionInfo *position); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CExpertMoney::CExpertMoney(void) : m_percent(10.0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CExpertMoney::~CExpertMoney(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CExpertMoney::ValidationSettings() - { - if(!CExpertBase::ValidationSettings()) - return(false); -//--- initial data checks - if(m_percent<0.0 || m_percent>100.0) - { - printf(__FUNCTION__+": percentage of risk should be in the range from 0 to 100 inclusive"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open long position. | -//+------------------------------------------------------------------+ -double CExpertMoney::CheckOpenLong(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- - double lot; - if(price==0.0) - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent); - else - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); - if(lotm_account.Balance()*m_percent/100.0) - return(position.Volume()); -//--- - return(0.0); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/ExpertSignal.mqh b/Include/Expert/ExpertSignal.mqh deleted file mode 100644 index 994cb79..0000000 --- a/Include/Expert/ExpertSignal.mqh +++ /dev/null @@ -1,464 +0,0 @@ -//+------------------------------------------------------------------+ -//| ExpertSignal.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ExpertBase.mqh" -//+------------------------------------------------------------------+ -//| Macro definitions. | -//+------------------------------------------------------------------+ -//--- check if a market model is used -#define IS_PATTERN_USAGE(p) ((m_patterns_usage&(((int)1)<=m_threshold_open) - { - //--- there's a signal - result=true; - //--- try to get the levels of opening - if(!OpenLongParams(price,sl,tp,expiration)) - result=false; - } -//--- zeroize the base price - m_base_price=0.0; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| Generating a sell signal | -//+------------------------------------------------------------------+ -bool CExpertSignal::CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration) - { - bool result =false; -//--- the "prohibition" signal - if(m_direction==EMPTY_VALUE) - return(false); -//--- check of exceeding the threshold value - if(-m_direction>=m_threshold_open) - { - //--- there's a signal - result=true; - //--- try to get the levels of opening - if(!OpenShortParams(price,sl,tp,expiration)) - result=false; - } -//--- zeroize the base price - m_base_price=0.0; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| Detecting the levels for buying | -//+------------------------------------------------------------------+ -bool CExpertSignal::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration) - { - CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL; -//--- - if(general==NULL) - { - //--- if a base price is not specified explicitly, take the current market price - double base_price=(m_base_price==0.0) ? m_symbol.Ask() : m_base_price; - price =m_symbol.NormalizePrice(base_price-m_price_level*PriceLevelUnit()); - sl =(m_stop_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price-m_stop_level*PriceLevelUnit()); - tp =(m_take_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price+m_take_level*PriceLevelUnit()); - expiration+=m_expiration*PeriodSeconds(m_period); - return(true); - } -//--- - return(general.OpenLongParams(price,sl,tp,expiration)); - } -//+------------------------------------------------------------------+ -//| Detecting the levels for selling | -//+------------------------------------------------------------------+ -bool CExpertSignal::OpenShortParams(double &price,double &sl,double &tp,datetime &expiration) - { - CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL; -//--- - if(general==NULL) - { - //--- if a base price is not specified explicitly, take the current market price - double base_price=(m_base_price==0.0) ? m_symbol.Bid() : m_base_price; - price =m_symbol.NormalizePrice(base_price+m_price_level*PriceLevelUnit()); - sl =(m_stop_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price+m_stop_level*PriceLevelUnit()); - tp =(m_take_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price-m_take_level*PriceLevelUnit()); - expiration+=m_expiration*PeriodSeconds(m_period); - return(true); - } -//--- - return(general.OpenShortParams(price,sl,tp,expiration)); - } -//+------------------------------------------------------------------+ -//| Generating a signal for closing of a long position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CheckCloseLong(double &price) - { - bool result =false; -//--- the "prohibition" signal - if(m_direction==EMPTY_VALUE) - return(false); -//--- check of exceeding the threshold value - if(-m_direction>=m_threshold_close) - { - //--- there's a signal - result=true; - //--- try to get the level of closing - if(!CloseLongParams(price)) - result=false; - } -//--- zeroize the base price - m_base_price=0.0; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| Generating a signal for closing a short position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CheckCloseShort(double &price) - { - bool result =false; -//--- the "prohibition" signal - if(m_direction==EMPTY_VALUE) - return(false); -//--- check of exceeding the threshold value - if(m_direction>=m_threshold_close) - { - //--- there's a signal - result=true; - //--- try to get the level of closing - if(!CloseShortParams(price)) - result=false; - } -//--- zeroize the base price - m_base_price=0.0; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| Detecting the levels for closing a long position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CloseLongParams(double &price) - { - CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL; -//--- - if(general==NULL) - { - //--- if a base price is not specified explicitly, take the current market price - price=(m_base_price==0.0) ? m_symbol.Bid() : m_base_price; - return(true); - } -//--- - return(general.CloseLongParams(price)); - } -//+------------------------------------------------------------------+ -//| Detecting the levels for closing a short position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CloseShortParams(double &price) - { - CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL; -//--- - if(general==NULL) - { - //--- if a base price is not specified explicitly, take the current market price - price=(m_base_price==0.0)?m_symbol.Ask():m_base_price; - return(true); - } -//--- ok - return(general.CloseShortParams(price)); - } -//+------------------------------------------------------------------+ -//| Generating a signal for reversing a long position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CheckReverseLong(double &price,double &sl,double &tp,datetime &expiration) - { - double c_price; -//--- check the signal of closing a long position - if(!CheckCloseLong(c_price)) - return(false); -//--- check the signal of opening a short position - if(!CheckOpenShort(price,sl,tp,expiration)) - return(false); -//--- difference between the close and open prices must not exceed two spreads - if(c_price!=price) - return(false); -//--- there's a signal - return(true); - } -//+------------------------------------------------------------------+ -//| Generating a signal for reversing a short position | -//+------------------------------------------------------------------+ -bool CExpertSignal::CheckReverseShort(double &price,double &sl,double &tp,datetime &expiration) - { - double c_price; -//--- check the signal of closing a short position - if(!CheckCloseShort(c_price)) - return(false); -//--- check the signal of opening a long position - if(!CheckOpenLong(price,sl,tp,expiration)) - return(false); -//--- difference between the close and open prices must not exceed two spreads - if(c_price!=price) - return(false); -//--- there's a signal - return(true); - } -//+------------------------------------------------------------------+ -//| Detecting the "weighted" direction | -//+------------------------------------------------------------------+ -double CExpertSignal::Direction(void) - { - long mask; - double direction; - double result=m_weight*(LongCondition()-ShortCondition()); - int number=(result==0.0)? 0 : 1; // number of "voted" -//--- - int total=m_filters.Total(); -//--- loop by filters - for(int i=0;i -#include -#include -#include -#include -//+------------------------------------------------------------------+ -//| Class CExpertTrade. | -//| Appointment: Class simple trade operations. | -//| Derives from class CTrade. | -//+------------------------------------------------------------------+ -class CExpertTrade : public CTrade - { -protected: - ENUM_ORDER_TYPE_TIME m_order_type_time; - datetime m_order_expiration; - CSymbolInfo *m_symbol; // symbol object - CAccountInfo m_account; // account object - -public: - CExpertTrade(void); - ~CExpertTrade(void); - //--- methods for easy trade - bool SetSymbol(CSymbolInfo *symbol); - bool SetOrderTypeTime(ENUM_ORDER_TYPE_TIME order_type_time); - bool SetOrderExpiration(datetime order_expiration); - bool Buy(double volume,double price,double sl,double tp,const string comment=""); - bool Sell(double volume,double price,double sl,double tp,const string comment=""); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CExpertTrade::CExpertTrade(void) : m_symbol(NULL), - m_order_type_time(ORDER_TIME_GTC), - m_order_expiration(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CExpertTrade::~CExpertTrade(void) - { - } -//+------------------------------------------------------------------+ -//| Setting working symbol for easy trade operations. | -//+------------------------------------------------------------------+ -bool CExpertTrade::SetSymbol(CSymbolInfo *symbol) - { - if(symbol!=NULL) - { - m_symbol=symbol; - return(true); - } -//--- - return(false); - } -//+------------------------------------------------------------------+ -//| Setting order expiration type for easy trade operations | -//+------------------------------------------------------------------+ -bool CExpertTrade::SetOrderTypeTime(ENUM_ORDER_TYPE_TIME order_type_time) - { - if(m_symbol==NULL) - return(false); -//--- - if(order_type_time==ORDER_TIME_SPECIFIED) - { - if((m_symbol.TradeTimeFlags()&SYMBOL_EXPIRATION_SPECIFIED)==0) - { - m_order_type_time =ORDER_TIME_GTC; - m_order_expiration=0; - return(false); - } - } -//--- - m_order_type_time=order_type_time; -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Setting order expiration time for easy trade operations | -//+------------------------------------------------------------------+ -bool CExpertTrade::SetOrderExpiration(datetime order_expiration) - { - if(m_symbol==NULL) - return(false); -//--- check expiration - if(order_expiration>=TimeCurrent()+60) - { - if(!SetOrderTypeTime(ORDER_TIME_SPECIFIED)) - return(false); - m_order_expiration=order_expiration; - } - else - { - m_order_type_time=ORDER_TIME_GTC; - m_order_expiration=0; - } -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Easy LONG trade operation | -//+------------------------------------------------------------------+ -bool CExpertTrade::Buy(double volume,double price,double sl,double tp,const string comment="") - { - double ask,stops_level; -//--- checking - if(m_symbol==NULL) - return(false); - string symbol=m_symbol.Name(); - if(symbol=="") - return(false); -//--- - ask=m_symbol.Ask(); - stops_level=m_symbol.StopsLevel()*m_symbol.Point(); - if(price!=0.0) - { - if(price>ask+stops_level) - { - //--- send "BUY_STOP" order - return(OrderOpen(symbol,ORDER_TYPE_BUY_STOP,volume,0.0,price,sl,tp, - m_order_type_time,m_order_expiration,comment)); - } - if(pricebid+stops_level) - { - //--- send "SELL_LIMIT" order - return(OrderOpen(symbol,ORDER_TYPE_SELL_LIMIT,volume,0.0,price,sl,tp, - m_order_type_time,m_order_expiration,comment)); - } - if(price -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trading with fixed trade volume | -//| Type=Money | -//| Name=FixLot | -//| Class=CMoneyFixedLot | -//| Page= | -//| Parameter=Percent,double,10.0,Percent | -//| Parameter=Lots,double,0.1,Fixed volume | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CMoneyFixedLot. | -//| Purpose: Class of money management with fixed lot. | -//| Derives from class CExpertMoney. | -//+------------------------------------------------------------------+ -class CMoneyFixedLot : public CExpertMoney - { -protected: - //--- input parameters - double m_lots; - -public: - CMoneyFixedLot(void); - ~CMoneyFixedLot(void); - //--- - void Lots(double lots) { m_lots=lots; } - virtual bool ValidationSettings(void); - //--- - virtual double CheckOpenLong(double price,double sl) { return(m_lots); } - virtual double CheckOpenShort(double price,double sl) { return(m_lots); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CMoneyFixedLot::CMoneyFixedLot(void) : m_lots(0.1) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CMoneyFixedLot::~CMoneyFixedLot(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CMoneyFixedLot::ValidationSettings(void) - { - if(!CExpertMoney::ValidationSettings()) - return(false); -//--- initial data checks - if(m_lotsm_symbol.LotsMax()) - { - printf(__FUNCTION__+": lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); - return(false); - } - if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10) - { - printf(__FUNCTION__+": lots amount is not corresponding with lot step %f",m_symbol.LotsStep()); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Money/MoneyFixedMargin.mqh b/Include/Expert/Money/MoneyFixedMargin.mqh deleted file mode 100644 index 18acb7e..0000000 --- a/Include/Expert/Money/MoneyFixedMargin.mqh +++ /dev/null @@ -1,76 +0,0 @@ -//+------------------------------------------------------------------+ -//| MoneyFixedMargin.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trading with fixed margin | -//| Type=Money | -//| Name=FixMargin | -//| Class=CMoneyFixedMargin | -//| Page= | -//| Parameter=Percent,double,10.0,Percentage of margin | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CMoneyFixedMargin. | -//| Purpose: Class of money management with fixed percent margin. | -//| Derives from class CExpertMoney. | -//+------------------------------------------------------------------+ -class CMoneyFixedMargin : public CExpertMoney - { -public: - CMoneyFixedMargin(void); - ~CMoneyFixedMargin(void); - //--- - virtual double CheckOpenLong(double price,double sl); - virtual double CheckOpenShort(double price,double sl); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CMoneyFixedMargin::CMoneyFixedMargin(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CMoneyFixedMargin::~CMoneyFixedMargin(void) - { - } -//+------------------------------------------------------------------+ -//| Getting lot size for open long position. | -//+------------------------------------------------------------------+ -double CMoneyFixedMargin::CheckOpenLong(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - if(price==0.0) - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent); - else - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); -//--- return trading volume - return(lot); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open short position. | -//+------------------------------------------------------------------+ -double CMoneyFixedMargin::CheckOpenShort(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - if(price==0.0) - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent); - else - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); -//--- return trading volume - return(lot); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Money/MoneyFixedRisk.mqh b/Include/Expert/Money/MoneyFixedRisk.mqh deleted file mode 100644 index e022be0..0000000 --- a/Include/Expert/Money/MoneyFixedRisk.mqh +++ /dev/null @@ -1,109 +0,0 @@ -//+------------------------------------------------------------------+ -//| MoneyFixedRisk.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trading with fixed risk | -//| Type=Money | -//| Name=FixRisk | -//| Class=CMoneyFixedRisk | -//| Page= | -//| Parameter=Percent,double,10.0,Risk percentage | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CMoneyFixedRisk. | -//| Purpose: Class of money management with fixed percent risk. | -//| Derives from class CExpertMoney. | -//+------------------------------------------------------------------+ -class CMoneyFixedRisk : public CExpertMoney - { -public: - CMoneyFixedRisk(void); - ~CMoneyFixedRisk(void); - //--- - virtual double CheckOpenLong(double price,double sl); - virtual double CheckOpenShort(double price,double sl); - virtual double CheckClose(CPositionInfo *position) { return(0.0); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CMoneyFixedRisk::CMoneyFixedRisk(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CMoneyFixedRisk::~CMoneyFixedRisk(void) - { - } -//+------------------------------------------------------------------+ -//| Getting lot size for open long position. | -//+------------------------------------------------------------------+ -double CMoneyFixedRisk::CheckOpenLong(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - double minvol=m_symbol.LotsMin(); - if(sl==0.0) - lot=minvol; - else - { - double loss; - if(price==0.0) - loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_BUY,1.0,m_symbol.Ask(),sl); - else - loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_BUY,1.0,price,sl); - double stepvol=m_symbol.LotsStep(); - lot=MathFloor(m_account.Balance()*m_percent/loss/100.0/stepvol)*stepvol; - } -//--- - if(lotmaxvol) - lot=maxvol; -//--- return trading volume - return(lot); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open short position. | -//+------------------------------------------------------------------+ -double CMoneyFixedRisk::CheckOpenShort(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - double minvol=m_symbol.LotsMin(); - if(sl==0.0) - lot=minvol; - else - { - double loss; - if(price==0.0) - loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_SELL,1.0,m_symbol.Bid(),sl); - else - loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_SELL,1.0,price,sl); - double stepvol=m_symbol.LotsStep(); - lot=MathFloor(m_account.Balance()*m_percent/loss/100.0/stepvol)*stepvol; - } -//--- - if(lotmaxvol) - lot=maxvol; -//--- return trading volume - return(lot); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Money/MoneyNone.mqh b/Include/Expert/Money/MoneyNone.mqh deleted file mode 100644 index d389c6e..0000000 --- a/Include/Expert/Money/MoneyNone.mqh +++ /dev/null @@ -1,71 +0,0 @@ -//+------------------------------------------------------------------+ -//| MoneyNone.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trading with minimal allowed trade volume | -//| Type=Money | -//| Name=MinLot | -//| Class=CMoneyNone | -//| Page= | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CMoneyNone. | -//| Appointment: Class no money managment. | -//| Derives from class CExpertMoney. | -//+------------------------------------------------------------------+ -class CMoneyNone : public CExpertMoney - { -public: - CMoneyNone(void); - ~CMoneyNone(void); - //--- - virtual bool ValidationSettings(void); - //--- - virtual double CheckOpenLong(double price,double sl); - virtual double CheckOpenShort(double price,double sl); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CMoneyNone::CMoneyNone(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CMoneyNone::~CMoneyNone(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CMoneyNone::ValidationSettings(void) - { - Percent(100.0); -//--- initial data checks - if(!CExpertMoney::ValidationSettings()) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open long position. | -//+------------------------------------------------------------------+ -double CMoneyNone::CheckOpenLong(double price,double sl) - { - return(m_symbol.LotsMin()); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open short position. | -//+------------------------------------------------------------------+ -double CMoneyNone::CheckOpenShort(double price,double sl) - { - return(m_symbol.LotsMin()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Money/MoneySizeOptimized.mqh b/Include/Expert/Money/MoneySizeOptimized.mqh deleted file mode 100644 index 71a2628..0000000 --- a/Include/Expert/Money/MoneySizeOptimized.mqh +++ /dev/null @@ -1,155 +0,0 @@ -//+------------------------------------------------------------------+ -//| MoneySizeOptimized.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trading with optimized trade volume | -//| Type=Money | -//| Name=SizeOptimized | -//| Class=CMoneySizeOptimized | -//| Page= | -//| Parameter=DecreaseFactor,double,3.0,Decrease factor | -//| Parameter=Percent,double,10.0,Percent | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CMoneySizeOptimized. | -//| Purpose: Class of money management with size optimized. | -//| Derives from class CExpertMoney. | -//+------------------------------------------------------------------+ -class CMoneySizeOptimized : public CExpertMoney - { -protected: - double m_decrease_factor; - -public: - CMoneySizeOptimized(void); - ~CMoneySizeOptimized(void); - //--- - void DecreaseFactor(double decrease_factor) { m_decrease_factor=decrease_factor; } - virtual bool ValidationSettings(void); - //--- - virtual double CheckOpenLong(double price,double sl); - virtual double CheckOpenShort(double price,double sl); - -protected: - double Optimize(double lots); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CMoneySizeOptimized::CMoneySizeOptimized(void) : m_decrease_factor(3.0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CMoneySizeOptimized::~CMoneySizeOptimized(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CMoneySizeOptimized::ValidationSettings(void) - { - if(!CExpertMoney::ValidationSettings()) - return(false); -//--- initial data checks - if(m_decrease_factor<=0.0) - { - printf(__FUNCTION__+": decrease factor must be greater then 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open long position. | -//+------------------------------------------------------------------+ -double CMoneySizeOptimized::CheckOpenLong(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - if(price==0.0) - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent); - else - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); -//--- return trading volume - return(Optimize(lot)); - } -//+------------------------------------------------------------------+ -//| Getting lot size for open short position. | -//+------------------------------------------------------------------+ -double CMoneySizeOptimized::CheckOpenShort(double price,double sl) - { - if(m_symbol==NULL) - return(0.0); -//--- select lot size - double lot; - if(price==0.0) - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent); - else - lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); -//--- return trading volume - return(Optimize(lot)); - } -//+------------------------------------------------------------------+ -//| Optimizing lot size for open. | -//+------------------------------------------------------------------+ -double CMoneySizeOptimized::Optimize(double lots) - { - double lot=lots; -//--- calculate number of losses orders without a break - if(m_decrease_factor>0) - { - //--- select history for access - HistorySelect(0,TimeCurrent()); - //--- - int orders=HistoryDealsTotal(); // total history deals - int losses=0; // number of consequent losing orders - CDealInfo deal; - //--- - for(int i=orders-1;i>=0;i--) - { - deal.Ticket(HistoryDealGetTicket(i)); - if(deal.Ticket()==0) - { - Print("CMoneySizeOptimized::Optimize: HistoryDealGetTicket failed, no trade history"); - break; - } - //--- check symbol - if(deal.Symbol()!=m_symbol.Name()) - continue; - //--- check profit - double profit=deal.Profit(); - if(profit>0.0) - break; - if(profit<0.0) - losses++; - } - //--- - if(losses>1) - lot=NormalizeDouble(lot-lot*losses/m_decrease_factor,2); - } -//--- normalize and check limits - double stepvol=m_symbol.LotsStep(); - lot=stepvol*NormalizeDouble(lot/stepvol,0); -//--- - double minvol=m_symbol.LotsMin(); - if(lotmaxvol) - lot=maxvol; -//--- - return(lot); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalAC.mqh b/Include/Expert/Signal/SignalAC.mqh deleted file mode 100644 index 9565897..0000000 --- a/Include/Expert/Signal/SignalAC.mqh +++ /dev/null @@ -1,173 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalAC.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Accelerator Oscillator' | -//| Type=SignalAdvanced | -//| Name=Accelerator Oscillator | -//| ShortName=AC | -//| Class=CSignalAC | -//| Page=signal_ac | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalAC. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Accelerator Oscillator' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalAC : public CExpertSignal - { -protected: - CiAC m_ac; // object-indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "first analyzed bar has required color" - int m_pattern_1; // model 1 "there is a condition for entering the market" - int m_pattern_2; // model 2 "condition for entering the market has just appeared" - -public: - CSignalAC(void); - ~CSignalAC(void); - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitAC(CIndicators *indicators); - //--- methods of getting data - double AC(int ind) { return(m_ac.Main(ind)); } - double DiffAC(int ind) { return(AC(ind)-AC(ind+1)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalAC::CSignalAC(void) : m_pattern_0(90), - m_pattern_1(50), - m_pattern_2(30) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalAC::~CSignalAC(void) - { - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalAC::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize AC indicator - if(!InitAC(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize AC indicators. | -//+------------------------------------------------------------------+ -bool CSignalAC::InitAC(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_ac))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_ac.Create(m_symbol.Name(),m_period)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalAC::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the first analyzed bar is "red", don't "vote" for buying - if(DiffAC(idx++)<0.0) - return(result); -//--- first analyzed bar is "green" (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; -//--- if the second analyzed bar is "red", there is no condition for buying - if(DiffAC(idx)<0.0) - return(result); -//--- second analyzed bar is "green" (the condition for buying may be fulfilled) -//--- if the second analyzed bar is less than zero, we need to analyzed the third bar - if(AC(idx++)<0.0) - { - //--- if the third analyzed bar is "red", there is no condition for buying - if(DiffAC(idx++)<0.0) - return(result); - } -//--- there is a condition for buying - if(IS_PATTERN_USAGE(1)) - result=m_pattern_1; -//--- if the previously analyzed bar is "red", the condition for buying has just been fulfilled - if(IS_PATTERN_USAGE(2) && DiffAC(idx)<0.0) - result=m_pattern_2; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalAC::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the first analyzed bar is "green", don't "vote" for selling - if(DiffAC(idx++)>0.0) - return(result); -//--- first analyzed bar is "red" (the indicator has no objections to selling) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; -//--- if the second analyzed bar is "green", there is no condition for selling - if(DiffAC(idx)>0.0) - return(result); -//--- second analyzed bar is "red" (the condition for selling may be fulfilled) -//--- if the second analyzed bar is greater than zero, we need to analyze the third bar - if(AC(idx++)>0.0) - { - //--- if the third analyzed bar is "green", there is no condition for selling - if(DiffAC(idx++)>0.0) - return(result); - } -//--- there us a condition for selling - if(IS_PATTERN_USAGE(1)) - result=m_pattern_1; -//--- if the previously analyzed bar is "green", the condition for selling has just been fulfilled - if(IS_PATTERN_USAGE(2) && DiffAC(idx)>0.0) - result=m_pattern_2; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalAMA.mqh b/Include/Expert/Signal/SignalAMA.mqh deleted file mode 100644 index 3d968e3..0000000 --- a/Include/Expert/Signal/SignalAMA.mqh +++ /dev/null @@ -1,265 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalAMA.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Adaptive Moving Average' | -//| Type=SignalAdvanced | -//| Name=Adaptive Moving Average | -//| ShortName=AMA | -//| Class=CSignalAMA | -//| Page=signal_ama | -//| Parameter=PeriodMA,int,10,Period of averaging | -//| Parameter=PeriodFast,int,2,Period of fast EMA | -//| Parameter=PeriodSlow,int,30,Period of slow EMA | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalAMA. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Adaptive Moving Average' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalAMA : public CExpertSignal - { -protected: - CiAMA m_ma; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_period_fast; // the "period of fast EMA" parameter of the indicator - int m_period_slow; // the "period of slow EMA" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is on the necessary side from the indicator" - int m_pattern_1; // model 1 "price crossed the indicator with opposite direction" - int m_pattern_2; // model 2 "price crossed the indicator with the same direction" - int m_pattern_3; // model 3 "piercing" - -public: - CSignalAMA(void); - ~CSignalAMA(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void PeriodFast(int value) { m_period_fast=value; } - void PeriodSlow(int value) { m_period_slow=value; } - void Shift(int value) { m_ma_shift=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double MA(int ind) { return(m_ma.Main(ind)); } - double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); } - double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); } - double DiffHighMA(int ind) { return(High(ind)-MA(ind)); } - double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); } - double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalAMA::CSignalAMA(void) : m_ma_period(10), - m_ma_shift(0), - m_period_fast(2), - m_period_slow(30), - m_ma_applied(PRICE_CLOSE), - m_pattern_0(10), - m_pattern_1(70), - m_pattern_2(100), - m_pattern_3(60) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalAMA::~CSignalAMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalAMA::ValidationSettings(void) - { -//--- call of the method of the parent class - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalAMA::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize AMA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalAMA::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_ma))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_period_fast,m_period_slow,m_ma_shift,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalAMA::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)<0.0) - { - //--- the close price is below the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0) - { - //--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is above the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the indicator is directed upwards - if(DiffMA(idx)>0.0) - { - if(DiffOpenMA(idx)<0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is below the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is above the indicator - if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0) - { - //--- the low price is below the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalAMA::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)>0.0) - { - //--- the close price is above the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0) - { - //--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is below the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- the indicator is directed downwards - if(DiffMA(idx)<0.0) - { - if(DiffOpenMA(idx)>0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is above the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is below the indicator - if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0) - { - //--- the high price is above the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalAO.mqh b/Include/Expert/Signal/SignalAO.mqh deleted file mode 100644 index bfe0535..0000000 --- a/Include/Expert/Signal/SignalAO.mqh +++ /dev/null @@ -1,339 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalAO.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Awesome Oscillator' | -//| Type=SignalAdvanced | -//| Name=Awesome Oscillator | -//| ShortName=AO | -//| Class=CSignalAO | -//| Page=signal_ao | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalAO. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Awesome Oscillator' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalAO : public CExpertSignal - { -protected: - CiAO m_ao; // object-indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "first analyzed bar has required color" - int m_pattern_1; // model 1 "the 'saucer' signal" - int m_pattern_2; // model 2 "the 'crossing of the zero line' signal" - int m_pattern_3; // model 2 "the 'divergence' signal" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalAO(void); - ~CSignalAO(void); - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitAO(CIndicators *indicators); - //--- methods of getting data - double AO(int ind) { return(m_ao.Main(ind)); } - double DiffAO(int ind) { return(AO(ind)-AO(ind+1)); } - int StateAO(int ind); - bool ExtStateAO(int ind); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalAO::CSignalAO(void) : m_pattern_0(30), - m_pattern_1(20), - m_pattern_2(70), - m_pattern_3(90) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalAO::~CSignalAO(void) - { - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalAO::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize AO indicator - if(!InitAO(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize AO indicators. | -//+------------------------------------------------------------------+ -bool CSignalAO::InitAO(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_ao))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_ao.Create(m_symbol.Name(),m_period)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the indicator state. | -//+------------------------------------------------------------------+ -int CSignalAO::StateAO(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(AO(i+1)==EMPTY_VALUE) - break; - var=DiffAO(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalAO::ExtStateAO(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateAO(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=AO(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalAO::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the first analyzed bar is "red", don't "vote" for buying - if(DiffAO(idx)<0.0) - return(result); -//--- first analyzed bar is "green" (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - if(AO(idx++)>0.0) - { - //--- first analyzed bar is greater than zero, search for the "saucer" and "crosing of the zero line" signals - if(IS_PATTERN_USAGE(1) && DiffAO(idx)<0.0) - { - //--- the "saucer" signal - //--- there is a condition for buying - return(m_pattern_1); - } - if(IS_PATTERN_USAGE(2) && AO(idx)<0.0) - { - //--- the "crossing of the zero line" signal - //--- there is a condition for buying - return(m_pattern_2); - } - } - else - { - //--- first analyzed bar is less than zero, search for the "divergence" signal - //--- if the second analyzed bar is "red", the condition for buying may be fulfilled - if(IS_PATTERN_USAGE(3) && DiffAO(idx)<0.0) - { - idx=StartIndex(); - //--- search for the "divergence" signal - ExtStateAO(idx); - if((m_extr_map&0xF)==1) - { - if(m_extr_osc[0]<0.0 && m_extr_osc[1]<0.0 && m_extr_osc[2]<0.0) - { - //--- both valleys are below zero, the peak is between them and it hasn't raised above zero - //--- we suppose that this is "divergence" - return(m_pattern_3); - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalAO::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the first analyzed bar is "green", don't "vote" for selling - if(DiffAO(idx)>0.0) - return(result); -//--- first analyzed bar is "red" (the indicator has no objections to selling) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - if(AO(idx++)<0.0) - { - //--- first analyzed bar is below zero, search for the "saucer" and "crossing of the zero line" signals - if(IS_PATTERN_USAGE(1) && DiffAO(idx)>0.0) - { - //--- the "saucer" signal - //--- there is a condition for buying - return(m_pattern_1); - } - if(IS_PATTERN_USAGE(2) && AO(idx)>0.0) - { - //--- the "crossing of the zero line" signal - //--- there is a condition for buying - return(m_pattern_2); - } - } - else - { - //--- first analyzed bar is above zero, search for the "divergence" signal - //--- if the second analyzed bar is "green", the condition for buying may be fulfilled - if(IS_PATTERN_USAGE(3) && DiffAO(idx)>0.0) - { - idx=StartIndex(); - //--- search for the "divergence" signal - ExtStateAO(idx); - if((m_extr_map&0xF)==1) - { - if(m_extr_osc[0]>0.0 && m_extr_osc[1]>0.0 && m_extr_osc[2]>0.0) - { - //--- both peaks are above zero and the valley between them hasn't fallen below zero - //--- we suppose that this is "divergence" - return(m_pattern_3); - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalBearsPower.mqh b/Include/Expert/Signal/SignalBearsPower.mqh deleted file mode 100644 index df1b25d..0000000 --- a/Include/Expert/Signal/SignalBearsPower.mqh +++ /dev/null @@ -1,289 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalBearsPower.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Bears Power' | -//| Type=SignalAdvanced | -//| Name=Bears Power | -//| ShortName=BearsPower | -//| Class=CSignalBearsPower | -//| Page=signal_bears | -//| Parameter=PeriodBears,int,13,Period of calculation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalBearsPower. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Bears Power' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalBearsPower : public CExpertSignal - { -protected: - CiBearsPower m_bears; // object-oscillator - //--- adjusted parameters - int m_period_bears; // the "period of calculation" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "reverse of the oscillator to required direction" - int m_pattern_1; // model 1 "divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalBearsPower(void); - ~CSignalBearsPower(void); - //--- methods of setting adjustable parameters - void PeriodBears(int value) { m_period_bears=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - //--- the oscillator doesn't identify conditions for selling - -protected: - //--- method of initialization of the oscillator - bool InitBears(CIndicators *indicators); - //--- methods of getting data - double Bears(int ind) { return(m_bears.Main(ind)); } - double DiffBears(int ind) { return(Bears(ind)-Bears(ind+1)); } - int StateBears(int ind); - bool ExtStateBears(int ind); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalBearsPower::CSignalBearsPower(void) : m_period_bears(13), - m_pattern_0(20), - m_pattern_1(80) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalBearsPower::~CSignalBearsPower(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalBearsPower::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_period_bears<=0) - { - printf(__FUNCTION__+": period Bears must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalBearsPower::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize BearsPower oscillator - if(!InitBears(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize BearsPower oscillators. | -//+------------------------------------------------------------------+ -bool CSignalBearsPower::InitBears(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_bears))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_bears.Create(m_symbol.Name(),m_period,m_period_bears)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalBearsPower::StateBears(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(Bears(i+1)==EMPTY_VALUE) - break; - var=DiffBears(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- return the result - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalBearsPower::ExtStateBears(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateBears(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=Bears(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalBearsPower::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the oscillator is above zero, don't "vote" for buying - if(Bears(idx)>0.0) - return(result); -//--- the oscillator is below zero - if(StateBears(idx)>0) - { - //--- the oscillator has turned upwards at a previous bar - //--- there is a condition for buying - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the model 1 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(1)) - { - ExtStateBears(idx); - if((m_extr_map&0xF)==1) - { - if(m_extr_osc[0]<0.0 && m_extr_osc[2]<0.0) - { - //--- both valleys are below zero - //--- we suppose that this is "divergence" - result=m_pattern_1; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalBullsPower.mqh b/Include/Expert/Signal/SignalBullsPower.mqh deleted file mode 100644 index 10c8ef7..0000000 --- a/Include/Expert/Signal/SignalBullsPower.mqh +++ /dev/null @@ -1,289 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalBullsPower.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Bulls Power' | -//| Type=SignalAdvanced | -//| Name=Bulls Power | -//| ShortName=BullsPower | -//| Class=CSignalBullsPower | -//| Page=signal_bulls | -//| Parameter=PeriodBulls,int,13,Period of calculation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalBullsPower. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Bulls Power' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalBullsPower : public CExpertSignal - { -protected: - CiBullsPower m_bulls; // object-oscillator - //--- adjusted parameters - int m_period_bulls; // the "period of calculation" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "reverse of the oscillator to required direction" - int m_pattern_1; // model 1 "divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalBullsPower(void); - ~CSignalBullsPower(void); - //--- methods of setting adjustable parameters - void PeriodBulls(int value) { m_period_bulls=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int ShortCondition(void); - //--- the oscillator doesn't identify conditions for buying - -protected: - //--- method of initialization of the oscillator - bool InitBears(CIndicators *indicators); - //--- methods of getting data - double Bulls(int ind) { return(m_bulls.Main(ind)); } - double DiffBulls(int ind) { return(Bulls(ind)-Bulls(ind+1)); } - int StateBulls(int ind); - bool ExtStateBulls(int ind); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalBullsPower::CSignalBullsPower(void) : m_period_bulls(13), - m_pattern_0(20), - m_pattern_1(80) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalBullsPower::~CSignalBullsPower(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalBullsPower::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_period_bulls<=0) - { - printf(__FUNCTION__+": period Bulls must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalBullsPower::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize BullsPower oscillator - if(!InitBears(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize BearsPower oscillators. | -//+------------------------------------------------------------------+ -bool CSignalBullsPower::InitBears(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_bulls))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_bulls.Create(m_symbol.Name(),m_period,m_period_bulls)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalBullsPower::StateBulls(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(Bulls(i+1)==EMPTY_VALUE) - break; - var=DiffBulls(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- return the result - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalBullsPower::ExtStateBulls(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateBulls(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=Bulls(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalBullsPower::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the oscillator is below zero, don't "vote" for selling - if(Bulls(idx)<0.0) - return(result); -//--- the oscillator is above zero - if(StateBulls(idx)<0) - { - //--- the oscillator has turned downwards at a previous bar - //--- there us a condition for selling - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the model 1 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(1)) - { - ExtStateBulls(idx); - if((m_extr_map&0xF)==1) - { - if(m_extr_osc[0]>0.0 && m_extr_osc[2]>0.0) - { - //--- both peaks are above zero - //--- we suppose that this is "divergence" - result=m_pattern_1; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalCCI.mqh b/Include/Expert/Signal/SignalCCI.mqh deleted file mode 100644 index ed2caee..0000000 --- a/Include/Expert/Signal/SignalCCI.mqh +++ /dev/null @@ -1,382 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalCCI.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscilator 'Commodity Channel Index' | -//| Type=SignalAdvanced | -//| Name=Commodity Channel Index | -//| ShortName=CCI | -//| Class=CSignalCCI | -//| Page=signal_cci | -//| Parameter=PeriodCCI,int,8,Period of calculation | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalCCI. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Commodity Channel Index' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalCCI : public CExpertSignal - { -protected: - CiCCI m_cci; // object-oscillator - //--- adjusted parameters - int m_periodCCI; // the "period of calculation" parameter of the oscillator - ENUM_APPLIED_PRICE m_applied; // the "prices series" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling" - int m_pattern_2; // model 2 "divergence of the oscillator and price" - int m_pattern_3; // model 3 "double divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalCCI(void); - ~CSignalCCI(void); - //--- methods of setting adjustable parameters - void PeriodCCI(int value) { m_periodCCI=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitStoch(CIndicators *indicators); - //--- methods of getting data - double CCI(int ind) { return(m_cci.Main(ind)); } - double Diff(int ind) { return(CCI(ind)-CCI(ind+1)); } - int State(int ind); - bool ExtState(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalCCI::CSignalCCI(void) : m_periodCCI(14), - m_applied(PRICE_CLOSE), - m_pattern_0(90), - m_pattern_1(60), - m_pattern_2(100), - m_pattern_3(50) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalCCI::~CSignalCCI(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalCCI::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_periodCCI<=0) - { - printf(__FUNCTION__+": period of the CCI oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalCCI::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize CCI oscillator - if(!InitStoch(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize CCI oscillators. | -//+------------------------------------------------------------------+ -bool CSignalCCI::InitStoch(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_cci))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_cci.Create(m_symbol.Name(),m_period,m_periodCCI,m_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalCCI::State(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(CCI(i+1)==EMPTY_VALUE) - break; - var=Diff(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- return the result - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalCCI::ExtState(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=State(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=CCI(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,3,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalCCI::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalCCI::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(Diff(idx)>0.0) - { - //--- the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling - if(IS_PATTERN_USAGE(1) && Diff(idx+1)<0.0 && CCI(idx+1)<-100.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3)) - { - ExtState(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, search for the "double divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b - return(m_pattern_3); // signal number 3 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalCCI::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(Diff(idx)<0.0) - { - //--- the oscillator is directed downwards confirming the possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying - if(IS_PATTERN_USAGE(1) && Diff(idx+1)>0.0 && CCI(idx+1)>100.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3)) - { - ExtState(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, search for the "double divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b - return(m_pattern_3); // signal number 3 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalDEMA.mqh b/Include/Expert/Signal/SignalDEMA.mqh deleted file mode 100644 index 8cb1191..0000000 --- a/Include/Expert/Signal/SignalDEMA.mqh +++ /dev/null @@ -1,257 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalDEMA.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Double Exponential Moving Average' | -//| Type=SignalAdvanced | -//| Name=Double Exponential Moving Average | -//| ShortName=DEMA | -//| Class=CSignalDEMA | -//| Page=signal_dema | -//| Parameter=PeriodMA,int,12,Period of averaging | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalDEMA. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Double Exponential Moving Average' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalDEMA : public CExpertSignal - { -protected: - CiDEMA m_ma; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is on the necessary side from the indicator" - int m_pattern_1; // model 1 "price crossed the indicator with opposite direction" - int m_pattern_2; // model 2 "price crossed the indicator with the same direction" - int m_pattern_3; // model 3 "piercing" - -public: - CSignalDEMA(void); - ~CSignalDEMA(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void Shift(int value) { m_ma_shift=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double MA(int ind) { return(m_ma.Main(ind)); } - double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); } - double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); } - double DiffHighMA(int ind) { return(High(ind)-MA(ind)); } - double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); } - double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalDEMA::CSignalDEMA(void) : m_ma_period(12), - m_ma_shift(0), - m_ma_applied(PRICE_CLOSE), - m_pattern_0(20), - m_pattern_1(60), - m_pattern_2(80), - m_pattern_3(60) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalDEMA::~CSignalDEMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalDEMA::ValidationSettings(void) - { -//--- call of the method of the parent class - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalDEMA::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize DEMA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalDEMA::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add indicator to collection - if(!indicators.Add(GetPointer(m_ma))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize indicator - if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalDEMA::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)<0.0) - { - //--- the close price is below the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0) - { - //--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is above the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the indicator is directed upwards - if(DiffMA(idx)>0.0) - { - if(DiffOpenMA(idx)<0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is below the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is above the indicator - if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0) - { - //--- the low price is below the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalDEMA::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)>0.0) - { - //--- the close price is above the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0) - { - //--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is below the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- the indicator is directed downwards - if(DiffMA(idx)<0.0) - { - if(DiffOpenMA(idx)>0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is above the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is below the indicator - if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0) - { - //--- the high price is above the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalDeMarker.mqh b/Include/Expert/Signal/SignalDeMarker.mqh deleted file mode 100644 index 23af291..0000000 --- a/Include/Expert/Signal/SignalDeMarker.mqh +++ /dev/null @@ -1,378 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalDeMarker.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'DeMarker' | -//| Type=SignalAdvanced | -//| Name=DeMarker | -//| ShortName=DeM | -//| Class=CSignalDeM | -//| Page=signal_demarker | -//| Parameter=PeriodDeM,int,8,Period of calculation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalDeM. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Commodity Channel Index' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalDeM : public CExpertSignal - { -protected: - CiDeMarker m_dem; // object-oscillator - //--- adjusted parameters - int m_periodDeM; // the "period of calculation" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling" - int m_pattern_2; // model 2 "divergence of the oscillator and price" - int m_pattern_3; // model 3 "double divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalDeM(void); - ~CSignalDeM(void); - //--- methods of setting adjustable parameters - void PeriodDeM(int value) { m_periodDeM=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitStoch(CIndicators *indicators); - //--- methods of getting data - double DeM(int ind) { return(m_dem.Main(ind)); } - double DiffDeM(int ind) { return(DeM(ind)-DeM(ind+1)); } - int StateDeM(int ind); - bool ExtStateDeM(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalDeM::CSignalDeM(void) : m_periodDeM(14), - m_pattern_0(90), - m_pattern_1(60), - m_pattern_2(100), - m_pattern_3(80) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalDeM::~CSignalDeM(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalDeM::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_periodDeM<=0) - { - printf(__FUNCTION__+": period of the DeMarker oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalDeM::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize DeMarker oscillator - if(!InitStoch(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize DeMarker oscillators. | -//+------------------------------------------------------------------+ -bool CSignalDeM::InitStoch(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_dem))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_dem.Create(m_symbol.Name(),m_period,m_periodDeM)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalDeM::StateDeM(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(DeM(i+1)==EMPTY_VALUE) - break; - var=DiffDeM(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalDeM::ExtStateDeM(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateDeM(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=DeM(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalDeM::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalDeM::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffDeM(idx)>0.0) - { - //--- the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling - if(IS_PATTERN_USAGE(1) && DiffDeM(idx+1)<0.0 && DeM(idx+1)<0.3) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3)) - { - ExtStateDeM(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, search for the "double divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b - return(m_pattern_3); // signal number 3 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalDeM::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffDeM(idx)<0.0) - { - //--- the oscillator is directed downwards confirming the possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying - if(IS_PATTERN_USAGE(1) && DiffDeM(idx+1)>0.0 && DeM(idx+1)>0.7) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3)) - { - ExtStateDeM(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, search for the "double divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b - return(m_pattern_3); // signal number 3 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalEnvelopes.mqh b/Include/Expert/Signal/SignalEnvelopes.mqh deleted file mode 100644 index e1f56e3..0000000 --- a/Include/Expert/Signal/SignalEnvelopes.mqh +++ /dev/null @@ -1,193 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalEnvelopes.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Envelopes' | -//| Type=SignalAdvanced | -//| Name=Envelopes | -//| ShortName=Envelopes | -//| Class=CSignalEnvelopes | -//| Page=signal_envelopes | -//| Parameter=PeriodMA,int,45,Period of averaging | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//| Parameter=Deviation,double,0.15,Deviation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalEnvelopes. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Envelopes' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalEnvelopes : public CExpertSignal - { -protected: - CiEnvelopes m_env; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator - double m_deviation; // the "deviation" parameter of the indicator - double m_limit_in; // threshold sensitivity of the 'rollback zone' - double m_limit_out; // threshold sensitivity of the 'break through zone' - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is near the necessary border of the envelope" - int m_pattern_1; // model 1 "price crossed a border of the envelope" - -public: - CSignalEnvelopes(void); - ~CSignalEnvelopes(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void Shift(int value) { m_ma_shift=value; } - void Method(ENUM_MA_METHOD value) { m_ma_method=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - void Deviation(double value) { m_deviation=value; } - void LimitIn(double value) { m_limit_in=value; } - void LimitOut(double value) { m_limit_out=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double Upper(int ind) { return(m_env.Upper(ind)); } - double Lower(int ind) { return(m_env.Lower(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45), - m_ma_shift(0), - m_ma_method(MODE_SMA), - m_ma_applied(PRICE_CLOSE), - m_deviation(0.15), - m_limit_in(0.2), - m_limit_out(0.2), - m_pattern_0(90), - m_pattern_1(70) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalEnvelopes::~CSignalEnvelopes(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalEnvelopes::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalEnvelopes::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize MA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalEnvelopes::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_env))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalEnvelopes::LongCondition(void) - { - int result=0; - int idx =StartIndex(); - double close=Close(idx); - double upper=Upper(idx); - double lower=Lower(idx); - double width=upper-lower; -//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying - if(IS_PATTERN_USAGE(0) && closelower-m_limit_out*width) - result=m_pattern_0; -//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying - if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) - result=m_pattern_1; -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalEnvelopes::ShortCondition(void) - { - int result =0; - int idx =StartIndex(); - double close=Close(idx); - double upper=Upper(idx); - double lower=Lower(idx); - double width=upper-lower; -//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling - if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Fractal Adaptive Moving Average' | -//| Type=SignalAdvanced | -//| Name=Fractal Adaptive Moving Average | -//| ShortName=FraMA | -//| Class=CSignalFrAMA | -//| Page=signal_frama | -//| Parameter=PeriodMA,int,12,Period of averaging | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalFrAMA. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Fractal Adaptive Moving Average' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalFrAMA : public CExpertSignal - { -protected: - CiFrAMA m_ma; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is on the necessary side from the indicator" - int m_pattern_1; // model 1 "price crossed the indicator with opposite direction" - int m_pattern_2; // model 2 "price crossed the indicator with the same direction" - int m_pattern_3; // model 3 "piercing" - -public: - CSignalFrAMA(void); - ~CSignalFrAMA(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void Shift(int value) { m_ma_shift=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double MA(int ind) { return(m_ma.Main(ind)); } - double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); } - double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); } - double DiffHighMA(int ind) { return(High(ind)-MA(ind)); } - double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); } - double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalFrAMA::CSignalFrAMA(void) : m_ma_period(12), - m_ma_shift(0), - m_ma_applied(PRICE_CLOSE), - m_pattern_0(90), - m_pattern_1(100), - m_pattern_2(80), - m_pattern_3(60) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalFrAMA::~CSignalFrAMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalFrAMA::ValidationSettings(void) - { -//--- call of the method of the parent class - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalFrAMA::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize FrAMA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalFrAMA::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add indicator to collection - if(!indicators.Add(GetPointer(m_ma))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize indicator - if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalFrAMA::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)<0.0) - { - //--- the close price is below the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0) - { - //--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is above the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the indicator is directed upwards - if(DiffMA(idx)>0.0) - { - if(DiffOpenMA(idx)<0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is below the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is above the indicator - if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0) - { - //--- the low price is below the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalFrAMA::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)>0.0) - { - //--- the close price is above the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0) - { - //--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is below the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- the indicator is directed downwards - if(DiffMA(idx)<0.0) - { - if(DiffOpenMA(idx)>0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is above the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is below the indicator - if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0) - { - //--- the high price is above the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalITF.mqh b/Include/Expert/Signal/SignalITF.mqh deleted file mode 100644 index b10c760..0000000 --- a/Include/Expert/Signal/SignalITF.mqh +++ /dev/null @@ -1,91 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalITF.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of intraday time filter | -//| Type=SignalAdvanced | -//| Name=IntradayTimeFilter | -//| ShortName=ITF | -//| Class=CSignalITF | -//| Page=signal_time_filter | -//| Parameter=GoodHourOfDay,int,-1,Good hour | -//| Parameter=BadHoursOfDay,int,0,Bad hours (bit-map) | -//| Parameter=GoodDayOfWeek,int,-1,Good day of week | -//| Parameter=BadDaysOfWeek,int,0,Bad days of week (bit-map) | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalITF. | -//| Appointment: Class trading signals time filter. | -//| Derives from class CExpertSignal. | -//+------------------------------------------------------------------+ -class CSignalITF : public CExpertSignal - { -protected: - //--- input parameters - int m_good_minute_of_hour; - long m_bad_minutes_of_hour; - int m_good_hour_of_day; - int m_bad_hours_of_day; - int m_good_day_of_week; - int m_bad_days_of_week; - -public: - CSignalITF(void); - ~CSignalITF(void); - //--- methods initialize protected data - void GoodMinuteOfHour(int value) { m_good_minute_of_hour=value; } - void BadMinutesOfHour(long value) { m_bad_minutes_of_hour=value; } - void GoodHourOfDay(int value) { m_good_hour_of_day=value; } - void BadHoursOfDay(int value) { m_bad_hours_of_day=value; } - void GoodDayOfWeek(int value) { m_good_day_of_week=value; } - void BadDaysOfWeek(int value) { m_bad_days_of_week=value; } - //--- methods of checking conditions of entering the market - virtual double Direction(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalITF::CSignalITF(void) : m_good_minute_of_hour(-1), - m_bad_minutes_of_hour(0), - m_good_hour_of_day(-1), - m_bad_hours_of_day(0), - m_good_day_of_week(-1), - m_bad_days_of_week(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalITF::~CSignalITF(void) - { - } -//+------------------------------------------------------------------+ -//| Check conditions for time filter. | -//+------------------------------------------------------------------+ -double CSignalITF::Direction(void) - { - MqlDateTime s_time; -//--- - TimeCurrent(s_time); -//--- check days conditions - if(!((m_good_day_of_week==-1 || m_good_day_of_week==s_time.day_of_week) && - !(m_bad_days_of_week&(1< -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Moving Average' | -//| Type=SignalAdvanced | -//| Name=Moving Average | -//| ShortName=MA | -//| Class=CSignalMA | -//| Page=signal_ma | -//| Parameter=PeriodMA,int,12,Period of averaging | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalMA. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Moving Average' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalMA : public CExpertSignal - { -protected: - CiMA m_ma; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is on the necessary side from the indicator" - int m_pattern_1; // model 1 "price crossed the indicator with opposite direction" - int m_pattern_2; // model 2 "price crossed the indicator with the same direction" - int m_pattern_3; // model 3 "piercing" - -public: - CSignalMA(void); - ~CSignalMA(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void Shift(int value) { m_ma_shift=value; } - void Method(ENUM_MA_METHOD value) { m_ma_method=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double MA(int ind) { return(m_ma.Main(ind)); } - double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); } - double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); } - double DiffHighMA(int ind) { return(High(ind)-MA(ind)); } - double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); } - double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalMA::CSignalMA(void) : m_ma_period(12), - m_ma_shift(0), - m_ma_method(MODE_SMA), - m_ma_applied(PRICE_CLOSE), - m_pattern_0(80), - m_pattern_1(10), - m_pattern_2(60), - m_pattern_3(60) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalMA::~CSignalMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalMA::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalMA::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize MA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalMA::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_ma))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalMA::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)<0.0) - { - //--- the close price is below the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0) - { - //--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is above the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the indicator is directed upwards - if(DiffMA(idx)>0.0) - { - if(DiffOpenMA(idx)<0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is below the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is above the indicator - if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0) - { - //--- the low price is below the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalMA::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)>0.0) - { - //--- the close price is above the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0) - { - //--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is below the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- the indicator is directed downwards - if(DiffMA(idx)<0.0) - { - if(DiffOpenMA(idx)>0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is above the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is below the indicator - if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0) - { - //--- the high price is above the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalMACD.mqh b/Include/Expert/Signal/SignalMACD.mqh deleted file mode 100644 index 01ee550..0000000 --- a/Include/Expert/Signal/SignalMACD.mqh +++ /dev/null @@ -1,408 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalMACD.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'MACD' | -//| Type=SignalAdvanced | -//| Name=MACD | -//| ShortName=MACD | -//| Class=CSignalMACD | -//| Page=signal_macd | -//| Parameter=PeriodFast,int,12,Period of fast EMA | -//| Parameter=PeriodSlow,int,24,Period of slow EMA | -//| Parameter=PeriodSignal,int,9,Period of averaging of difference | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalMACD. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Moving Average Convergence/Divergence' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalMACD : public CExpertSignal - { -protected: - CiMACD m_MACD; // object-oscillator - //--- adjusted parameters - int m_period_fast; // the "period of fast EMA" parameter of the oscillator - int m_period_slow; // the "period of slow EMA" parameter of the oscillator - int m_period_signal; // the "period of averaging of difference" parameter of the oscillator - ENUM_APPLIED_PRICE m_applied; // the "price series" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse of the oscillator to required direction" - int m_pattern_2; // model 2 "crossing of main and signal line" - int m_pattern_3; // model 3 "crossing of main line an the zero level" - int m_pattern_4; // model 4 "divergence of the oscillator and price" - int m_pattern_5; // model 5 "double divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalMACD(void); - ~CSignalMACD(void); - //--- methods of setting adjustable parameters - void PeriodFast(int value) { m_period_fast=value; } - void PeriodSlow(int value) { m_period_slow=value; } - void PeriodSignal(int value) { m_period_signal=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - void Pattern_4(int value) { m_pattern_4=value; } - void Pattern_5(int value) { m_pattern_5=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitMACD(CIndicators *indicators); - //--- methods of getting data - double Main(int ind) { return(m_MACD.Main(ind)); } - double Signal(int ind) { return(m_MACD.Signal(ind)); } - double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); } - int StateMain(int ind); - double State(int ind) { return(Main(ind)-Signal(ind)); } - bool ExtState(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalMACD::CSignalMACD(void) : m_period_fast(12), - m_period_slow(24), - m_period_signal(9), - m_applied(PRICE_CLOSE), - m_pattern_0(10), - m_pattern_1(30), - m_pattern_2(80), - m_pattern_3(50), - m_pattern_4(60), - m_pattern_5(100) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalMACD::~CSignalMACD(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalMACD::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_period_fast>=m_period_slow) - { - printf(__FUNCTION__+": slow period must be greater than fast period"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalMACD::InitIndicators(CIndicators *indicators) - { -//--- check of pointer is performed in the method of the parent class -//--- -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize MACD oscilator - if(!InitMACD(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize MACD oscillators. | -//+------------------------------------------------------------------+ -bool CSignalMACD::InitMACD(CIndicators *indicators) - { -//--- add object to collection - if(!indicators.Add(GetPointer(m_MACD))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_MACD.Create(m_symbol.Name(),m_period,m_period_fast,m_period_slow,m_period_signal,m_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalMACD::StateMain(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(Main(i+1)==EMPTY_VALUE) - break; - var=DiffMain(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalMACD::ExtState(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateMain(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=Main(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalMACD::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalMACD::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffMain(idx)>0.0) - { - //--- the main line is directed upwards, and it confirms the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, look for a reverse of the main line - if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, look for an intersection of the main and signal line - if(IS_PATTERN_USAGE(2) && State(idx)>0.0 && State(idx+1)<0.0) - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, look for an intersection of the main line and the zero level - if(IS_PATTERN_USAGE(3) && Main(idx)>0.0 && Main(idx+1)<0.0) - result=m_pattern_3; // signal number 3 - //--- if the models 4 or 5 are used and the main line turned upwards below the zero level, look for divergences - if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)<0.0) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- if the model 4 is used, look for the "divergence" signal - if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b - result=m_pattern_4; // signal number 4 - //--- if the model 5 is used, look for the "double divergence" signal - if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b - return(m_pattern_5); // signal number 5 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalMACD::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffMain(idx)<0.0) - { - //--- main line is directed downwards, confirming a possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, look for a reverse of the main line - if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, look for an intersection of the main and signal line - if(IS_PATTERN_USAGE(2) && State(idx)<0.0 && State(idx+1)>0.0) - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, look for an intersection of the main line and the zero level - if(IS_PATTERN_USAGE(3) && Main(idx)<0.0 && Main(idx+1)>0.0) - result=m_pattern_3; // signal number 3 - //--- if the models 4 or 5 are used and the main line turned downwards above the zero level, look for divergences - if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)>0.0) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- if the model 4 is used, look for the "divergence" signal - if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b - result=m_pattern_4; // signal number 4 - //--- if the model 5 is used, look for the "double divergence" signal - if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b - return(m_pattern_5); // signal number 5 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalRSI.mqh b/Include/Expert/Signal/SignalRSI.mqh deleted file mode 100644 index 2506abf..0000000 --- a/Include/Expert/Signal/SignalRSI.mqh +++ /dev/null @@ -1,400 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalRSI.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Relative Strength Index' | -//| Type=SignalAdvanced | -//| Name=Relative Strength Index | -//| ShortName=RSI | -//| Class=CSignalRSI | -//| Page=signal_rsi | -//| Parameter=PeriodRSI,int,8,Period of calculation | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalRSI. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Relative Strength Index' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalRSI : public CExpertSignal - { -protected: - CiRSI m_rsi; // object-oscillator - //--- adjusted parameters - int m_periodRSI; // the "period of calculation" parameter of the oscillator - ENUM_APPLIED_PRICE m_applied; // the "prices series" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling" - int m_pattern_2; // model 2 "failed swing" - int m_pattern_3; // model 3 "divergence of the oscillator and price" - int m_pattern_4; // model 4 "double divergence of the oscillator and price" - int m_pattern_5; // model 5 "head/shoulders" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalRSI(void); - ~CSignalRSI(void); - //--- methods of setting adjustable parameters - void PeriodRSI(int value) { m_periodRSI=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - void Pattern_4(int value) { m_pattern_4=value; } - void Pattern_5(int value) { m_pattern_5=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitRSI(CIndicators *indicators); - //--- methods of getting data - double RSI(int ind) { return(m_rsi.Main(ind)); } - double DiffRSI(int ind) { return(RSI(ind)-RSI(ind+1)); } - int StateRSI(int ind); - bool ExtStateRSI(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalRSI::CSignalRSI(void) : m_periodRSI(14), - m_applied(PRICE_CLOSE), - m_pattern_0(70), - m_pattern_1(100), - m_pattern_2(90), - m_pattern_3(80), - m_pattern_4(100), - m_pattern_5(20) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalRSI::~CSignalRSI(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalRSI::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_periodRSI<=0) - { - printf(__FUNCTION__+": period of the RSI oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalRSI::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize RSI oscillator - if(!InitRSI(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize RSI oscillators. | -//+------------------------------------------------------------------+ -bool CSignalRSI::InitRSI(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_rsi))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_rsi.Create(m_symbol.Name(),m_period,m_periodRSI,m_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalRSI::StateRSI(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(RSI(i+1)==EMPTY_VALUE) - break; - var=DiffRSI(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalRSI::ExtStateRSI(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateRSI(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=RSI(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalRSI::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalRSI::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(DiffRSI(idx)>0.0) - { - //--- the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling - if(IS_PATTERN_USAGE(1) && DiffRSI(idx+1)<0.0 && RSI(idx+1)<30.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2, 3, 4 or 5 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) - { - ExtStateRSI(idx); - //--- search for the "failed swing" signal - if(IS_PATTERN_USAGE(2) && RSI(idx)>m_extr_osc[1]) - result=m_pattern_2; // signal number 2 - //--- search for the "divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b - result=m_pattern_3; // signal number 3 - //--- search for the "double divergence" signal - if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b - return(m_pattern_4); // signal number 4 - //--- search for the "head/shoulders" signal - if(IS_PATTERN_USAGE(5) && CompareMaps(0x62662,5,true) && RSI(idx)>m_extr_osc[1]) // 01100010011001100010b - result=m_pattern_5; // signal number 5 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalRSI::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(DiffRSI(idx)<0.0) - { - //--- the oscillator is directed downwards confirming the possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying - if(IS_PATTERN_USAGE(1) && DiffRSI(idx+1)>0.0 && RSI(idx+1)>70.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2, 3, 4 or 5 is used, perform the extended analysis of the oscillator state - if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) - { - ExtStateRSI(idx); - //--- search for the "failed swing" signal - if(IS_PATTERN_USAGE(2) && RSI(idx) -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Relative Vigor Index' | -//| Type=SignalAdvanced | -//| Name=Relative Vigor Index | -//| ShortName=RVI | -//| Class=CSignalRVI | -//| Page=signal_rvi | -//| Parameter=PeriodRVI,int,10,Period of calculation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalRVI. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Relative Vigor Index' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalRVI : public CExpertSignal - { -protected: - CiRVI m_rvi; // object-oscillator - //--- adjusted parameters - int m_periodRVI; // the "period of calculation" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "crossing of main and signal line" - -public: - CSignalRVI(void); - ~CSignalRVI(void); - //--- methods of setting adjustable parameters - void PeriodRVI(int value) { m_periodRVI=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitRVI(CIndicators *indicators); - //--- methods of getting data - double Main(int ind) { return(m_rvi.Main(ind)); } - double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); } - double Signal(int ind) { return(m_rvi.Signal(ind)); } - double DiffSignal(int ind) { return(Signal(ind)-Signal(ind+1)); } - double DiffMainSignal(int ind) { return(Main(ind)-Signal(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalRVI::CSignalRVI(void) : m_periodRVI(10), - m_pattern_0(60), - m_pattern_1(100) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalRVI::~CSignalRVI(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalRVI::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_periodRVI<=0) - { - printf(__FUNCTION__+": the period of calculation of the RVI oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalRVI::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize RVI oscillator - if(!InitRVI(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize RVI oscillators. | -//+------------------------------------------------------------------+ -bool CSignalRVI::InitRVI(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_rvi))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_rvi.Create(m_symbol.Name(),m_period,m_periodRVI)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalRVI::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(DiffMain(idx)>0.0) - { - //--- the main line of the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal - //--- if the main line crosses the signal line upwards, this is a signal for buying - if(DiffMainSignal(idx)>0 && DiffMainSignal(idx+1)<0) - { - //--- the main line of the oscillator has crossed the signal line upwards (signal for buying) - if(IS_PATTERN_USAGE(1)) - result=m_pattern_1; // signal number 1 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalRVI::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(DiffMain(idx)<0.0) - { - //--- the main line of the oscillator is directed downwards confirming the possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal - //--- if the main line crosses the signal line from top downwards, this is a signal for selling - if(DiffMainSignal(idx)<0 && DiffMainSignal(idx+1)>0) - { - //--- the main line of the oscillator has crossed the signal line from top downwards (signal for selling) - if(IS_PATTERN_USAGE(1)) - result=m_pattern_1; // signal number 1 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalSAR.mqh b/Include/Expert/Signal/SignalSAR.mqh deleted file mode 100644 index b0cbda9..0000000 --- a/Include/Expert/Signal/SignalSAR.mqh +++ /dev/null @@ -1,168 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalSAR.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Parabolic SAR' | -//| Type=SignalAdvanced | -//| Name=Parabolic SAR | -//| ShortName=SAR | -//| Class=CSignalSAR | -//| Page=signal_sar | -//| Parameter=Step,double,0.02,Speed increment | -//| Parameter=Maximum,double,0.2,Maximum rate | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalSAR. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Parabolic SAR' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalSAR : public CExpertSignal - { -protected: - CiSAR m_sar; // object-indicator - //--- adjusted parameters - double m_step; // the "speed increment" parameter of the indicator - double m_maximum; // the "maximum rate" parameter of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the parabolic is on the necessary side from the price" - int m_pattern_1; // model 1 "the parabolic has 'switched'" - -public: - CSignalSAR(void); - ~CSignalSAR(void); - //--- methods of setting adjustable parameters - void Step(double value) { m_step=value; } - void Maximum(double value) { m_maximum=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitSAR(CIndicators *indicators); - //--- methods of getting data - double SAR(int ind) { return(m_sar.Main(ind)); } - double Close(int ind) { return(m_close.GetData(ind)); } - double DiffClose(int ind) { return(Close(ind)-SAR(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalSAR::CSignalSAR(void) : m_step(0.02), - m_maximum(0.2), - m_pattern_0(40), - m_pattern_1(90) - { -//--- initialization of protected data - m_used_series=USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalSAR::~CSignalSAR(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalSAR::ValidationSettings(void) - { -//--- call of the method of the parent class - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalSAR::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize SAR indicator - if(!InitSAR(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create SAR indicators. | -//+------------------------------------------------------------------+ -bool CSignalSAR::InitSAR(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_sar))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_sar.Create(m_symbol.Name(),m_period,m_step,m_maximum)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalSAR::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the indicator is above the price at the first analyzed bar, don't 'vote' buying - if(DiffClose(idx++)<0.0) - return(result); -//--- the indicator is below the price at the first analyzed bar (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; -//--- if the indicator is above the price at the second analyzed bar, then there is a condition for buying - if(IS_PATTERN_USAGE(1) && DiffClose(idx)<0.0) - return(m_pattern_1); -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalSAR::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- if the indicator is below the price at the first analyzed bar, don't "vote" for selling - if(DiffClose(idx++)>0.0) - return(result); -//--- the indicator is above the price at the first analyzed bar (the indicator has no objections to selling) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; -//--- if the indicator is below the price at the second analyzed bar, then there is a condition for selling - if(IS_PATTERN_USAGE(1) && DiffClose(idx)>0.0) - return(m_pattern_1); -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalStoch.mqh b/Include/Expert/Signal/SignalStoch.mqh deleted file mode 100644 index 51c1e1a..0000000 --- a/Include/Expert/Signal/SignalStoch.mqh +++ /dev/null @@ -1,426 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalStoch.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Stochastic' | -//| Type=SignalAdvanced | -//| Name=Stochastic | -//| ShortName=Stoch | -//| Class=CSignalStoch | -//| Page=signal_stochastic | -//| Parameter=PeriodK,int,8,K-period | -//| Parameter=PeriodD,int,3,D-period | -//| Parameter=PeriodSlow,int,3,Period of slowing | -//| Parameter=Applied,ENUM_STO_PRICE,STO_LOWHIGH,Prices to apply to | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalStoch. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Stochastic' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalStoch : public CExpertSignal - { -protected: - CiStochastic m_stoch; // object-oscillator - CPriceSeries *m_app_price_high; // pointer to the object-timeseries for determining divergences directed downwards - CPriceSeries *m_app_price_low; // pointer to the object-timeseries for determining divergences directed upwards - //--- adjusted parameters - int m_periodK; // the "period %K" parameter of the oscillator - int m_periodD; // the "period %D" parameter of the oscillator - int m_period_slow; // the "period of slowing" parameter of the oscillator - ENUM_STO_PRICE m_applied; // the "apply to" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse of the oscillator to required direction" - int m_pattern_2; // model 2 "crossing of main and signal line" - int m_pattern_3; // model 3 "divergence of the oscillator and price" - int m_pattern_4; // model 4 "double divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalStoch(void); - ~CSignalStoch(void); - //--- methods of setting adjustable parameters - void PeriodK(int value) { m_periodK=value; } - void PeriodD(int value) { m_periodD=value; } - void PeriodSlow(int value) { m_period_slow=value; } - void Applied(ENUM_STO_PRICE value) { m_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - void Pattern_4(int value) { m_pattern_4=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitStoch(CIndicators *indicators); - //--- methods of getting data - double Main(int ind) { return(m_stoch.Main(ind)); } - double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); } - double Signal(int ind) { return(m_stoch.Signal(ind)); } - double DiffSignal(int ind) { return(Signal(ind)-Signal(ind+1)); } - double DiffMainSignal(int ind) { return(Main(ind)-Signal(ind)); } - int StateStoch(int ind); - bool ExtStateStoch(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - void DiverDebugPrint(); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalStoch::CSignalStoch(void) : m_periodK(8), - m_periodD(3), - m_period_slow(3), - m_applied(STO_LOWHIGH), - m_pattern_0(30), - m_pattern_1(60), - m_pattern_2(50), - m_pattern_3(100), - m_pattern_4(90) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalStoch::~CSignalStoch(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalStoch::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_periodK<=0) - { - printf(__FUNCTION__+": the period %K of the Stochastic oscillator must be greater than 0"); - return(false); - } - if(m_periodD<=0) - { - printf(__FUNCTION__+": the period %D of the Stochastic oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalStoch::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize Stochastic oscillator - if(!InitStoch(indicators)) - return(false); - if(m_applied==STO_CLOSECLOSE) - { - //--- copying the Close timeseries - m_app_price_high=GetPointer(m_close); - //--- copying the Close timeseries - m_app_price_low=GetPointer(m_close); - } - else - { - //--- copying the High timeseries - m_app_price_high=GetPointer(m_high); - //--- copying the Low timeseries - m_app_price_low=GetPointer(m_low); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize Stochastic oscillators. | -//+------------------------------------------------------------------+ -bool CSignalStoch::InitStoch(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_stoch))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_stoch.Create(m_symbol.Name(),m_period,m_periodK,m_periodD,m_period_slow,MODE_SMA,m_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalStoch::StateStoch(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(Main(i+1)==EMPTY_VALUE) - break; - var=DiffMain(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalStoch::ExtStateStoch(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=StateStoch(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=Main(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalStoch::CompareMaps(int map,int count,bool minimax=false,int start=0) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalStoch::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffMain(idx)>0.0) - { - //--- the main line is directed upwards, and it confirms the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, look for a reverse of the main line - if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, look for an intersection of the main and signal line - if(IS_PATTERN_USAGE(2) && DiffMainSignal(idx)>0.0 && DiffMainSignal(idx+1)<0.0) - result=m_pattern_2; // signal number 2 - //--- if the models 3 or 4 are used, look for divergences - if((IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4))) - { - //--- perform the extended analysis of the oscillator state - ExtStateStoch(idx); - //--- if the model 3 is used, look for the "divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b - result=m_pattern_3; // signal number 3 - //--- if the model 4 is used, look for the "double divergence" signal - if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b - return(m_pattern_4); // signal number 4 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalStoch::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffMain(idx)<0.0) - { - //--- main line is directed downwards, confirming a possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, look for a reverse of the main line - if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, look for an intersection of the main and signal line - if(IS_PATTERN_USAGE(2) && DiffMainSignal(idx)<0.0 && DiffMainSignal(idx+1)>0.0) - result=m_pattern_2; // signal number 2 - //--- if the models 3 or 4 are used, look for divergences - if((IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4))) - { - //--- perform the extended analysis of the oscillator state - ExtStateStoch(idx); - //--- if the model 3 is used, look for the "divergence" signal - if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b - result=m_pattern_3; // signal number 3 - //--- if the model 4 is used, look for the "double divergence" signal - if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b - return(m_pattern_4); // signal number 4 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalTEMA.mqh b/Include/Expert/Signal/SignalTEMA.mqh deleted file mode 100644 index 0c47d3b..0000000 --- a/Include/Expert/Signal/SignalTEMA.mqh +++ /dev/null @@ -1,257 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalTEMA.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of indicator 'Triple Exponential Moving Average' | -//| Type=SignalAdvanced | -//| Name=Triple Exponential Moving Average | -//| ShortName=TEMA | -//| Class=CSignalTEMA | -//| Page=signal_tema | -//| Parameter=PeriodMA,int,12,Period of averaging | -//| Parameter=Shift,int,0,Time shift | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalTEMA. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Triple Exponential Moving Average' indicator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalTEMA : public CExpertSignal - { -protected: - CiTEMA m_ma; // object-indicator - //--- adjusted parameters - int m_ma_period; // the "period of averaging" parameter of the indicator - int m_ma_shift; // the "time shift" parameter of the indicator - ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "price is on the necessary side from the indicator" - int m_pattern_1; // model 1 "price crossed the indicator with opposite direction" - int m_pattern_2; // model 2 "price crossed the indicator with the same direction" - int m_pattern_3; // model 3 "piercing" - -public: - CSignalTEMA(void); - ~CSignalTEMA(void); - //--- methods of setting adjustable parameters - void PeriodMA(int value) { m_ma_period=value; } - void Shift(int value) { m_ma_shift=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the indicator - bool InitMA(CIndicators *indicators); - //--- methods of getting data - double MA(int ind) { return(m_ma.Main(ind)); } - double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); } - double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); } - double DiffHighMA(int ind) { return(High(ind)-MA(ind)); } - double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); } - double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalTEMA::CSignalTEMA(void) : m_ma_period(12), - m_ma_shift(0), - m_ma_applied(PRICE_CLOSE), - m_pattern_0(50), - m_pattern_1(10), - m_pattern_2(60), - m_pattern_3(60) - { -//--- initialization of protected data - m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalTEMA::~CSignalTEMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalTEMA::ValidationSettings(void) - { -//--- call of the method of the parent class - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalTEMA::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize TEMA indicator - if(!InitMA(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create MA indicators. | -//+------------------------------------------------------------------+ -bool CSignalTEMA::InitMA(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_ma))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalTEMA::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)<0.0) - { - //--- the close price is below the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0) - { - //--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is above the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- if the indicator is directed upwards - if(DiffMA(idx)>0.0) - { - if(DiffOpenMA(idx)<0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is below the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is above the indicator - if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0) - { - //--- the low price is below the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalTEMA::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- analyze positional relationship of the close price and the indicator at the first analyzed bar - if(DiffCloseMA(idx)>0.0) - { - //--- the close price is above the indicator - if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0) - { - //--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards - result=m_pattern_1; - //--- consider that this is an unformed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - else - { - //--- the close price is below the indicator (the indicator has no objections to buying) - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; - //--- the indicator is directed downwards - if(DiffMA(idx)<0.0) - { - if(DiffOpenMA(idx)>0.0) - { - //--- if the model 2 is used - if(IS_PATTERN_USAGE(2)) - { - //--- the open price is above the indicator (i.e. there was an intersection) - result=m_pattern_2; - //--- suggest to enter the market at the "roll back" - m_base_price=m_symbol.NormalizePrice(MA(idx)); - } - } - else - { - //--- if the model 3 is used and the open price is below the indicator - if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0) - { - //--- the high price is above the indicator - result=m_pattern_3; - //--- consider that this is a formed "piercing" and suggest to enter the market at the current price - m_base_price=0.0; - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalTRIX.mqh b/Include/Expert/Signal/SignalTRIX.mqh deleted file mode 100644 index 4a5391b..0000000 --- a/Include/Expert/Signal/SignalTRIX.mqh +++ /dev/null @@ -1,395 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalTRIX.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Triple Exponential Average' | -//| Type=SignalAdvanced | -//| Name=Triple Exponential Average | -//| ShortName=TriX | -//| Class=CSignalTriX | -//| Page=signal_trix | -//| Parameter=PeriodTriX,int,14,Period of calculation | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalTriX. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Triple Exponential Average' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalTriX : public CExpertSignal - { -protected: - CiTriX m_trix; // object-oscillator - //--- adjusted parameters - int m_period_trix; // the "period of calculation" parameter of the oscillator - ENUM_APPLIED_PRICE m_applied; // the "price series" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse of the oscillator to required direction" - int m_pattern_2; // model 2 "crossing of main line an the zero level" - int m_pattern_3; // model 3 "divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalTriX(void); - ~CSignalTriX(void); - //--- methods of setting adjustable parameters - void PeriodTriX(int value) { m_period_trix=value; } - void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - void Pattern_3(int value) { m_pattern_3=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitTriX(CIndicators *indicators); - //--- methods of getting data - double TriX(int ind) { return(m_trix.Main(ind)); } - double DiffTriX(int ind) { return(TriX(ind)-TriX(ind+1)); } - int State(int ind); - bool ExtState(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalTriX::CSignalTriX(void) : m_period_trix(12), - m_applied(PRICE_CLOSE), - m_pattern_0(20), - m_pattern_1(80), - m_pattern_2(100), - m_pattern_3(70) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalTriX::~CSignalTriX(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalTriX::ValidationSettings(void) - { - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- - if(m_period_trix<=0) - { - printf(__FUNCTION__+": period must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalTriX::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize TriX oscilator - if(!InitTriX(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize TriX oscillators. | -//+------------------------------------------------------------------+ -bool CSignalTriX::InitTriX(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_trix))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_trix.Create(m_symbol.Name(),m_period,m_period_trix,m_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalTriX::State(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(TriX(i+1)==EMPTY_VALUE) - break; - var=DiffTriX(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalTriX::ExtState(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=State(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=TriX(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalTriX::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>j)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) - check_map=(m_extr_map>>i)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding oscillator extremum - inp_map=(map>>(j+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(i+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalTriX::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the oscillator - if(DiffTriX(idx)>0.0) - { - //--- the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator - if(IS_PATTERN_USAGE(1) && DiffTriX(idx)>0.0 && DiffTriX(idx+1)<0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, search for an intersection of the oscillator line and the zero level - if(IS_PATTERN_USAGE(2) && TriX(idx)>0.0 && TriX(idx+1)<0.0) - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used, and the oscillator turned up below the zero level, search for the divergence - if(IS_PATTERN_USAGE(3) && TriX(idx)<0.0) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- search for the "divergence" signal - if(CompareMaps(1,1)) // 0000 0001b - { - if(m_extr_osc[0]<0.0 && m_extr_osc[1]<0.0 && m_extr_osc[2]<0.0) - { - //--- both valleys of the oscillator are below zero and the peak between them hasn't raised above zero - result=m_pattern_3; // signal number 3 - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalTriX::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- check direction of the main line - if(DiffTriX(idx)<0.0) - { - //--- main line is directed downwards, confirming a possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the main line - if(IS_PATTERN_USAGE(1) && DiffTriX(idx)<0.0 && DiffTriX(idx+1)>0.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 is used, search for an intersection of the main line and the zero level - if(IS_PATTERN_USAGE(2) && TriX(idx)<0.0 && TriX(idx+1)>0.0) - result=m_pattern_2; // signal number 2 - //--- if the model 3 is used and the main line turned down above the zero level, search for the divergence - if(IS_PATTERN_USAGE(3) && TriX(idx)>0.0) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- search for the "divergence" signal - if(CompareMaps(1,1)) // 0000 0001b - { - if(m_extr_osc[0]>0.0 && m_extr_osc[1]>0.0 && m_extr_osc[2]>0.0) - { - //--- both peaks of the oscillator are above zero and the valley between them hasn't fallen below zero - result=m_pattern_3; // signal number 3 - } - } - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Signal/SignalWPR.mqh b/Include/Expert/Signal/SignalWPR.mqh deleted file mode 100644 index 170aca9..0000000 --- a/Include/Expert/Signal/SignalWPR.mqh +++ /dev/null @@ -1,371 +0,0 @@ -//+------------------------------------------------------------------+ -//| SignalWPR.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Signals of oscillator 'Williams Percent Range' | -//| Type=SignalAdvanced | -//| Name=Williams Percent Range | -//| ShortName=WPR | -//| Class=CSignalWPR | -//| Page=signal_wpr | -//| Parameter=PeriodWPR,int,8,Period of calculation | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CSignalWPR. | -//| Purpose: Class of generator of trade signals based on | -//| the 'Williams Percent Range' oscillator. | -//| Is derived from the CExpertSignal class. | -//+------------------------------------------------------------------+ -class CSignalWPR : public CExpertSignal - { -protected: - CiWPR m_wpr; // object-oscillator - //--- adjusted parameters - int m_period_wpr; // the "period of calculation" parameter of the oscillator - //--- "weights" of market models (0-100) - int m_pattern_0; // model 0 "the oscillator has required direction" - int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling" - int m_pattern_2; // model 2 "divergence of the oscillator and price" - //--- variables - double m_extr_osc[10]; // array of values of extremums of the oscillator - double m_extr_pr[10]; // array of values of the corresponding extremums of price - int m_extr_pos[10]; // array of shifts of extremums (in bars) - uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price - -public: - CSignalWPR(void); - ~CSignalWPR(void); - //--- methods of setting adjustable parameters - void PeriodWPR(int value) { m_period_wpr=value; } - //--- methods of adjusting "weights" of market models - void Pattern_0(int value) { m_pattern_0=value; } - void Pattern_1(int value) { m_pattern_1=value; } - void Pattern_2(int value) { m_pattern_2=value; } - //--- method of verification of settings - virtual bool ValidationSettings(void); - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- methods of checking if the market models are formed - virtual int LongCondition(void); - virtual int ShortCondition(void); - -protected: - //--- method of initialization of the oscillator - bool InitWPR(CIndicators *indicators); - //--- methods of getting data - // double WPR(int ind); - double WPR(int ind) { return(m_wpr.Main(ind)); } - double Diff(int ind) { return(WPR(ind)-WPR(ind+1)); } - int State(int ind); - bool ExtState(int ind); - bool CompareMaps(int map,int count,bool minimax=false,int start=0); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSignalWPR::CSignalWPR(void) : m_period_wpr(14), - m_pattern_0(80), - m_pattern_1(70), - m_pattern_2(90) - { -//--- initialization of protected data - m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignalWPR::~CSignalWPR(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CSignalWPR::ValidationSettings(void) - { -//--- validation settings of additional filters - if(!CExpertSignal::ValidationSettings()) - return(false); -//--- initial data checks - if(m_period_wpr<=0) - { - printf(__FUNCTION__+": period of the WPR oscillator must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CSignalWPR::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- initialization of indicators and timeseries of additional filters - if(!CExpertSignal::InitIndicators(indicators)) - return(false); -//--- create and initialize WPR oscillator - if(!InitWPR(indicators)) - return(false); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize WPR oscillators. | -//+------------------------------------------------------------------+ -bool CSignalWPR::InitWPR(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_wpr))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_wpr.Create(m_symbol.Name(),m_period,m_period_wpr)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Check of the oscillator state. | -//+------------------------------------------------------------------+ -int CSignalWPR::State(int ind) - { - int res=0; - double var; -//--- - for(int i=ind;;i++) - { - if(WPR(i+1)==EMPTY_VALUE) - break; - var=Diff(i); - if(res>0) - { - if(var<0) - break; - res++; - continue; - } - if(res<0) - { - if(var>0) - break; - res--; - continue; - } - if(var>0) - res++; - if(var<0) - res--; - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Extended check of the oscillator state consists | -//| in forming a bit-map according to certain rules, | -//| which shows ratios of extremums of the oscillator and price. | -//+------------------------------------------------------------------+ -bool CSignalWPR::ExtState(int ind) - { -//--- operation of this method results in a bit-map of extremums -//--- practically, the bit-map of extremums is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an element of the analyzed bit-map -//--- bit 3 - not used (always 0) -//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- bit 1 - not used (always 0) -//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one -//--- (a higher peak or a deeper valley), otherwise - 0 -//--- in addition to them, the following is formed: -//--- array of values of extremums of the oscillator, -//--- array of values of price extremums and -//--- array of "distances" between extremums of the oscillator (in bars) -//--- it should be noted that when using the results of the extended check of state, -//--- you should consider, which extremum of the oscillator (peak or valley) -//--- is the "reference point" (i.e. was detected first during the analysis) -//--- if a peak is detected first then even elements of all arrays -//--- will contain information about peaks, and odd elements will contain information about valleys -//--- if a valley is detected first, then respectively in reverse - int pos=ind,off,index; - uint map; // intermediate bit-map for one extremum -//--- - m_extr_map=0; - for(int i=0;i<10;i++) - { - off=State(pos); - if(off>0) - { - //--- minimum of the oscillator is detected - pos+=off; - m_extr_pos[i]=pos; - m_extr_osc[i]=WPR(pos); - if(i>1) - { - m_extr_pr[i]=m_low.MinValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]1) - { - m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); - //--- form the intermediate bit-map - map=0; - if(m_extr_pr[i-2]>m_extr_pr[i]) - map+=1; // set bit 0 - if(m_extr_osc[i-2]>m_extr_osc[i]) - map+=4; // set bit 2 - //--- add the result - m_extr_map+=map<<(4*(i-2)); - } - else - m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); - } - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Comparing the bit-map of extremums with pattern. | -//+------------------------------------------------------------------+ -bool CSignalWPR::CompareMaps(int map,int count,bool minimax,int start) - { - int step =(minimax)?4:8; - int total=step*(start+count); -//--- check input parameters for a possible going out of range of the bit-map - if(total>32) - return(false); -//--- bit-map of the patter is an "array" of 4-bit fields -//--- each "element of the array" definitely describes the desired ratio -//--- of current extremums of the oscillator and the price with previous ones -//--- purpose of bits of an elements of the pattern of the bit-map pattern -//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us -//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 -//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) -//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us -//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 -//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one -//--- (current peak is higher or current valley is deeper) -//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one -//--- (current peak is lower or current valley is less deep) - uint inp_map,check_map; - int i,j; -//--- loop by extremums (4 minimums and 4 maximums) -//--- price and the oscillator are checked separately (thus, there are 16 checks) - for(i=step*start,j=0;i>i)&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map<2) - { - //--- "take" two bits of the corresponding extremum of the oscillator (higher-order bit is always 0) - check_map=(m_extr_map>>j)&3; - if(inp_map!=check_map) - return(false); - } - //--- "take" two bits - pattern of the corresponding price extremum - inp_map=(map>>(i+2))&3; - //--- if the higher-order bit=1, then any ratio is suitable for us - if(inp_map>=2) - continue; - //--- "take" two bits of the corresponding price extremum (higher-order bit is always 0) - check_map=(m_extr_map>>(j+2))&3; - if(inp_map!=check_map) - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will grow. | -//+------------------------------------------------------------------+ -int CSignalWPR::LongCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(Diff(idx)>0.0) - { - //--- the oscillator is directed upwards confirming the possibility of price growth - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling - if(IS_PATTERN_USAGE(1) && Diff(idx+1)<0.0 && WPR(idx+1)>-80.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, search for the divergences - if(IS_PATTERN_USAGE(2)) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ -//| "Voting" that price will fall. | -//+------------------------------------------------------------------+ -int CSignalWPR::ShortCondition(void) - { - int result=0; - int idx =StartIndex(); -//--- - if(Diff(idx)<0.0) - { - //--- the oscillator is directed downwards confirming the possibility of falling of price - if(IS_PATTERN_USAGE(0)) - result=m_pattern_0; // "confirming" signal number 0 - //--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying - if(IS_PATTERN_USAGE(1) && Diff(idx+1)>0.0 && WPR(idx+1)<-20.0) - result=m_pattern_1; // signal number 1 - //--- if the model 2 or 3 is used, search for the divergences - if(IS_PATTERN_USAGE(2)) - { - //--- perform the extended analysis of the oscillator state - ExtState(idx); - //--- if the model 2 is used, search for the "divergence" signal - if(CompareMaps(1,1)) // 00000001b - result=m_pattern_2; // signal number 2 - } - } -//--- return the result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Trailing/TrailingFixedPips.mqh b/Include/Expert/Trailing/TrailingFixedPips.mqh deleted file mode 100644 index a854312..0000000 --- a/Include/Expert/Trailing/TrailingFixedPips.mqh +++ /dev/null @@ -1,132 +0,0 @@ -//+------------------------------------------------------------------+ -//| TrailingFixedPips.mqh | -//| Copyright 2009-2016, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+----------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trailing Stop based on fixed Stop Level | -//| Type=Trailing | -//| Name=FixedPips | -//| Class=CTrailingFixedPips | -//| Page= | -//| Parameter=StopLevel,int,30,Stop Loss trailing level (in points) | -//| Parameter=ProfitLevel,int,50,Take Profit trailing level (in points) | -//+----------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CTrailingFixedPips. | -//| Purpose: Class of trailing stops with fixed stop level in pips. | -//| Derives from class CExpertTrailing. | -//+------------------------------------------------------------------+ -class CTrailingFixedPips : public CExpertTrailing - { -protected: - //--- input parameters - int m_stop_level; - int m_profit_level; - -public: - CTrailingFixedPips(void); - ~CTrailingFixedPips(void); - //--- methods of initialization of protected data - void StopLevel(int stop_level) { m_stop_level=stop_level; } - void ProfitLevel(int profit_level) { m_profit_level=profit_level; } - virtual bool ValidationSettings(void); - //--- - virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); - virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CTrailingFixedPips::CTrailingFixedPips(void) : m_stop_level(30), - m_profit_level(50) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTrailingFixedPips::~CTrailingFixedPips(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CTrailingFixedPips::ValidationSettings(void) - { - if(!CExpertTrailing::ValidationSettings()) - return(false); -//--- initial data checks - if(m_profit_level!=0 && m_profit_level*(m_adjusted_point/m_symbol.Point())delta) - { - sl=price-delta; - if(m_profit_level!=0) - tp=price+m_profit_level*m_adjusted_point; - } -//--- - return(sl!=EMPTY_VALUE); - } -//+------------------------------------------------------------------+ -//| Checking trailing stop and/or profit for short position. | -//+------------------------------------------------------------------+ -bool CTrailingFixedPips::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp) - { -//--- check - if(position==NULL) - return(false); - if(m_stop_level==0) - return(false); -//--- - double delta; - double pos_sl=position.StopLoss(); - double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; - double price =m_symbol.Ask(); -//--- - sl=EMPTY_VALUE; - tp=EMPTY_VALUE; - delta=m_stop_level*m_adjusted_point; - if(base-price>delta) - { - sl=price+delta; - if(m_profit_level!=0) - tp=price-m_profit_level*m_adjusted_point; - } -//--- - return(sl!=EMPTY_VALUE); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Trailing/TrailingMA.mqh b/Include/Expert/Trailing/TrailingMA.mqh deleted file mode 100644 index 34e97de..0000000 --- a/Include/Expert/Trailing/TrailingMA.mqh +++ /dev/null @@ -1,157 +0,0 @@ -//+------------------------------------------------------------------+ -//| TrailingMA.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trailing Stop based on MA | -//| Type=Trailing | -//| Name=MA | -//| Class=CTrailingMA | -//| Page= | -//| Parameter=Period,int,12,Period of MA | -//| Parameter=Shift,int,0,Shift of MA | -//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | -//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CTrailingMA. | -//| Purpose: Class of trailing stops based on MA. | -//| Derives from class CExpertTrailing. | -//+------------------------------------------------------------------+ -class CTrailingMA : public CExpertTrailing - { -protected: - CiMA *m_MA; - //--- input parameters - int m_ma_period; - int m_ma_shift; - ENUM_MA_METHOD m_ma_method; - ENUM_APPLIED_PRICE m_ma_applied; - -public: - CTrailingMA(void); - ~CTrailingMA(void); - //--- methods of initialization of protected data - void Period(int period) { m_ma_period=period; } - void Shift(int shift) { m_ma_shift=shift; } - - void Method(ENUM_MA_METHOD method) { m_ma_method=method; } - void Applied(ENUM_APPLIED_PRICE applied) { m_ma_applied=applied; } - virtual bool InitIndicators(CIndicators *indicators); - virtual bool ValidationSettings(void); - //--- - virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); - virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CTrailingMA::CTrailingMA(void) : m_MA(NULL), - m_ma_period(12), - m_ma_shift(0), - m_ma_method(MODE_SMA), - m_ma_applied(PRICE_CLOSE) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CTrailingMA::~CTrailingMA(void) - { - } -//+------------------------------------------------------------------+ -//| Validation settings protected data. | -//+------------------------------------------------------------------+ -bool CTrailingMA::ValidationSettings(void) - { - if(!CExpertTrailing::ValidationSettings()) - return(false); -//--- initial data checks - if(m_ma_period<=0) - { - printf(__FUNCTION__+": period MA must be greater than 0"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Checking for input parameters and setting protected data. | -//+------------------------------------------------------------------+ -bool CTrailingMA::InitIndicators(CIndicators *indicators) - { -//--- check - if(indicators==NULL) - return(false); -//--- create MA indicator - if(m_MA==NULL) - if((m_MA=new CiMA)==NULL) - { - printf(__FUNCTION__+": error creating object"); - return(false); - } -//--- add MA indicator to collection - if(!indicators.Add(m_MA)) - { - printf(__FUNCTION__+": error adding object"); - delete m_MA; - return(false); - } -//--- initialize MA indicator - if(!m_MA.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } - m_MA.BufferResize(3+m_ma_shift); -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Checking trailing stop and/or profit for long position. | -//+------------------------------------------------------------------+ -bool CTrailingMA::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp) - { -//--- check - if(position==NULL) - return(false); -//--- - double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); - double new_sl=NormalizeDouble(m_MA.Main(1),m_symbol.Digits()); - double pos_sl=position.StopLoss(); - double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; -//--- - sl=EMPTY_VALUE; - tp=EMPTY_VALUE; - if(new_sl>base && new_sllevel) - sl=new_sl; -//--- - return(sl!=EMPTY_VALUE); - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Trailing/TrailingNone.mqh b/Include/Expert/Trailing/TrailingNone.mqh deleted file mode 100644 index 53b626a..0000000 --- a/Include/Expert/Trailing/TrailingNone.mqh +++ /dev/null @@ -1,40 +0,0 @@ -//+------------------------------------------------------------------+ -//| TrailingNone.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trailing Stop not used | -//| Type=Trailing | -//| Name=None | -//| Class=CTrailingNone | -//| Page= | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CTrailingNone. | -//| Appointment: Class no traling stops. | -//| Derives from class CExpertTrailing. | -//+------------------------------------------------------------------+ -class CTrailingNone : public CExpertTrailing - { -public: - CTrailingNone(void); - ~CTrailingNone(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CTrailingNone::CTrailingNone(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTrailingNone::~CTrailingNone(void) - { - } -//+------------------------------------------------------------------+ diff --git a/Include/Expert/Trailing/TrailingParabolicSAR.mqh b/Include/Expert/Trailing/TrailingParabolicSAR.mqh deleted file mode 100644 index 588f02c..0000000 --- a/Include/Expert/Trailing/TrailingParabolicSAR.mqh +++ /dev/null @@ -1,123 +0,0 @@ -//+------------------------------------------------------------------+ -//| TrailingParabolicSAR.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -// wizard description start -//+------------------------------------------------------------------+ -//| Description of the class | -//| Title=Trailing Stop based on Parabolic SAR | -//| Type=Trailing | -//| Name=ParabolicSAR | -//| Class=CTrailingPSAR | -//| Page= | -//| Parameter=Step,double,0.02,Speed increment | -//| Parameter=Maximum,double,0.2,Maximum rate | -//+------------------------------------------------------------------+ -// wizard description end -//+------------------------------------------------------------------+ -//| Class CTrailingPSAR. | -//| Appointment: Class traling stops with Parabolic SAR. | -//| Derives from class CExpertTrailing. | -//+------------------------------------------------------------------+ -class CTrailingPSAR : public CExpertTrailing - { -protected: - CiSAR m_sar; // object-indicator - //--- adjusted parameters - double m_step; // the "speed increment" parameter of the indicator - double m_maximum; // the "maximum rate" parameter of the indicator - -public: - CTrailingPSAR(void); - ~CTrailingPSAR(void); - //--- methods of setting adjustable parameters - void Step(double step) { m_step=step; } - void Maximum(double maximum) { m_maximum=maximum; } - //--- method of creating the indicator and timeseries - virtual bool InitIndicators(CIndicators *indicators); - //--- - virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); - virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CTrailingPSAR::CTrailingPSAR(void) : m_step(0.02), - m_maximum(0.2) - - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CTrailingPSAR::~CTrailingPSAR(void) - { - } -//+------------------------------------------------------------------+ -//| Create indicators. | -//+------------------------------------------------------------------+ -bool CTrailingPSAR::InitIndicators(CIndicators *indicators) - { -//--- check pointer - if(indicators==NULL) - return(false); -//--- add object to collection - if(!indicators.Add(GetPointer(m_sar))) - { - printf(__FUNCTION__+": error adding object"); - return(false); - } -//--- initialize object - if(!m_sar.Create(m_symbol.Name(),m_period,m_step,m_maximum)) - { - printf(__FUNCTION__+": error initializing object"); - return(false); - } -//--- ok - return(true); - } -//+------------------------------------------------------------------+ -//| Checking trailing stop and/or profit for long position. | -//+------------------------------------------------------------------+ -bool CTrailingPSAR::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp) - { -//--- check - if(position==NULL) - return(false); -//--- - double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); - double new_sl=NormalizeDouble(m_sar.Main(1),m_symbol.Digits()); - double pos_sl=position.StopLoss(); - double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; -//--- - sl=EMPTY_VALUE; - tp=EMPTY_VALUE; - if(new_sl>base && new_sllevel) - sl=new_sl; -//--- - return(sl!=EMPTY_VALUE); - } -//+------------------------------------------------------------------+ diff --git a/Include/ExpertBase.mqh b/Include/ExpertBase.mqh deleted file mode 100644 index e5afc1d..0000000 --- a/Include/ExpertBase.mqh +++ /dev/null @@ -1,380 +0,0 @@ -/* - ExpertBase.mqh - - Copyright 2013-2020, Orchard Forex - https://www.orchardforex.com - -*/ - - -#include "CommonBase.mqh" -#include "SignalBase.mqh" -#include "TPSLBase.mqh" -#include "Trade/Trade.mqh" - -class CExpertBase : public CCommonBase { - -protected: - - int mMagicNumber; - string mTradeComment; - - double mVolume; - - datetime mLastBarTime; - datetime mBarTime; - - ////Changed - // Arrays to hold the signal objects - CSignalBase *mEntrySignals[]; - CSignalBase *mExitSignals[]; - ////CSignalBase *mEntrySignal; - ////CSignalBase *mExitSignal; - - double mTakeProfitValue; - double mStopLossValue; - CTPSLBase *mTakeProfitObj; - CTPSLBase *mStopLossObj; - - CTradeCustom Trade; - -private: - -protected: - - virtual bool LoopMain(bool newBar, bool firstTime); - -protected: - - int Init(int magicNumber, string tradeComment); - -public: - - // - // Constructors - // - CExpertBase() : CCommonBase() - { Init(0, ""); } - CExpertBase(string symbol, int timeframe, int magicNumber, string tradeComment) - : CCommonBase(symbol, timeframe) - { Init(magicNumber, tradeComment); } - CExpertBase(string symbol, ENUM_TIMEFRAMES timeframe, int magicNumber, string tradeComment) - : CCommonBase(symbol, timeframe) - { Init(magicNumber, tradeComment); } - CExpertBase(int magicNumber, string tradeComment) - : CCommonBase() - { Init(magicNumber, tradeComment); } - - // - // Destructors - // - ~CExpertBase(); - -public: // Default properties - - // - // Assign the default values to the expert - // - virtual void SetVolume(double volume) { mVolume = volume; } - - virtual void SetTakeProfitValue(int takeProfitPoints) - { mTakeProfitValue = PointsToDouble(takeProfitPoints); } - virtual void SetTakeProfitObj(CTPSLBase *takeProfitObj) - { mTakeProfitObj = takeProfitObj; } - - virtual void SetStopLossValue(int stopLossPoints) - { mStopLossValue = PointsToDouble(stopLossPoints); } - virtual void SetStopLossObj(CTPSLBase *stopLossObj) - { mStopLossObj = stopLossObj; } - - virtual void SetTradeComment(string comment) { mTradeComment = comment; } - virtual void SetMagic(int magicNumber) { mMagicNumber = magicNumber; - Trade.SetExpertMagicNumber(magicNumber); } - -public: // Setup - - ////Changed - virtual void AddEntrySignal(CSignalBase *signal) { AddSignal(signal, mEntrySignals); } - virtual void AddExitSignal(CSignalBase *signal) { AddSignal(signal, mExitSignals); } - virtual void AddSignal(CSignalBase *signal, CSignalBase* &signals[]); - ////virtual void AddEntrySignal(CSignalBase *signal) { mEntrySignal=signal; } - ////virtual void AddExitSignal(CSignalBase *signal) { mExitSignal=signal; } - -public: // Event handlers - - virtual int OnInit(); - virtual void OnTick(); - virtual void OnTimer() { return; } - virtual double OnTester() { return(0.0); } - virtual void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {}; - -#ifdef __MQL5__ - virtual void OnTrade() { return; } - virtual void OnTradeTransaction(const MqlTradeTransaction& trans, - const MqlTradeRequest& request, - const MqlTradeResult& result) - { return; } - virtual int OnTesterInit() { return(INIT_SUCCEEDED); } - virtual void OnTesterPass() { return; } - virtual void OnTesterDeinit() { return; } - virtual void OnBookEvent() { return; } -#endif - -public: // Functions - - virtual void GetMarketPrices(ENUM_ORDER_TYPE orderType, MqlTradeRequest &request); - ////New - virtual ENUM_OFX_SIGNAL_DIRECTION GetCurrentSignal(CSignalBase* &signals[], - ENUM_OFX_SIGNAL_TYPE signalType); - -}; - -CExpertBase::~CExpertBase() { - -} - -int CExpertBase::OnInit() { - - int i = 0; - for (i=ArraySize(mEntrySignals)-1; i>=0; i--) { - if (mEntrySignals[i].InitResult()!=INIT_SUCCEEDED) return(mEntrySignals[i].InitResult()); - } - for (i=ArraySize(mExitSignals)-1; i>=0; i--) { - if (mExitSignals[i].InitResult()!=INIT_SUCCEEDED) return(mExitSignals[i].InitResult()); - } - if (mTakeProfitObj!=NULL) { - if (mTakeProfitObj.InitResult()!=INIT_SUCCEEDED) return(mTakeProfitObj.InitResult()); - } - if (mStopLossObj!=NULL) { - if (mStopLossObj.InitResult()!=INIT_SUCCEEDED) return(mStopLossObj.InitResult()); - } - - return(INIT_SUCCEEDED); - -} - -int CExpertBase::Init(int magicNumber, string tradeComment) { - - if (mInitResult!=INIT_SUCCEEDED) return(mInitResult); - - mTradeComment = tradeComment; - SetMagic(magicNumber); - - mTakeProfitValue = 0.0; - mStopLossValue = 0.0; - - mLastBarTime = 0; - - ////New - ArrayResize(mEntrySignals, 0); // Just make sure these are initialised - ArrayResize(mExitSignals, 0); - - return(INIT_SUCCEEDED); - -} - -void CExpertBase::OnTick(void) { - - if (!TradeAllowed()) return; - - mBarTime = iTime(mSymbol, mTimeframe, 0); - - bool firstTime = (mLastBarTime==0); - bool newBar = (mBarTime!=mLastBarTime); - - if (LoopMain(newBar, firstTime)) { - mLastBarTime = mBarTime; - } - - return; - -} - -bool CExpertBase::LoopMain(bool newBar,bool firstTime) { - - // - // To start I will only trade on a new bar - // and not on the first bar after start - // - if (!newBar) return(true); - if (firstTime) return(true); - - // - // Update the signals - // - ////Changed - ENUM_OFX_SIGNAL_DIRECTION entrySignal = GetCurrentSignal(mEntrySignals, OFX_ENTRY_SIGNAL); - ENUM_OFX_SIGNAL_DIRECTION exitSignal = GetCurrentSignal(mExitSignals, OFX_EXIT_SIGNAL); - ////if (mEntrySignal!=NULL) mEntrySignal.UpdateSignal(); - ////if (mEntrySignal!=mExitSignal) { - //// if (mExitSignal!=NULL) mExitSignal.UpdateSignal(); - ////} - - // - // Should any trades be closed - // - ////Changed - if (exitSignal==OFX_SIGNAL_BOTH) { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - } else - if (exitSignal==OFX_SIGNAL_BUY) { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - } else - if (exitSignal==OFX_SIGNAL_SELL) { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - } - ////if (mExitSignal!=NULL) { - //// if (mExitSignal.ExitSignal()==OFX_SIGNAL_BOTH) { - //// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - //// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - //// } else - //// if (mExitSignal.ExitSignal()==OFX_SIGNAL_BUY) { - //// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - //// } else - //// if (mExitSignal.ExitSignal()==OFX_SIGNAL_SELL) { - //// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - //// } - ////} - - // - // Should a trade be opened - // - MqlTradeRequest request = {}; // Just initialising - ////Changed - if (entrySignal==OFX_SIGNAL_BOTH) { - - GetMarketPrices(ORDER_TYPE_BUY, request); - Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); - - GetMarketPrices(ORDER_TYPE_SELL, request); - Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); - - } else - if (entrySignal==OFX_SIGNAL_BUY) { - - GetMarketPrices(ORDER_TYPE_BUY, request); - Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); - - } else - if (entrySignal==OFX_SIGNAL_SELL) { - - GetMarketPrices(ORDER_TYPE_SELL, request); - Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); - - } -//// if (mEntrySignal!=NULL) { -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BOTH) { -//// -//// GetMarketPrices(ORDER_TYPE_BUY, request); -//// Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// GetMarketPrices(ORDER_TYPE_SELL, request); -//// Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } else -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BUY) { -//// -//// GetMarketPrices(ORDER_TYPE_BUY, request); -//// Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } else -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_SELL) { -//// -//// GetMarketPrices(ORDER_TYPE_SELL, request); -//// Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } -//// } - - return(true); - -} - -void CExpertBase::GetMarketPrices(ENUM_ORDER_TYPE orderType, MqlTradeRequest &request) { - - double sl = (mStopLossObj==NULL) ? mStopLossValue : mStopLossObj.GetStopLoss(); - double tp = (mTakeProfitObj==NULL) ? mTakeProfitValue : mTakeProfitObj.GetTakeProfit(); - - if (orderType==ORDER_TYPE_BUY) { - if (request.price==0.0) request.price = SymbolInfoDouble(mSymbol, SYMBOL_ASK); - request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price+tp, mDigits); - request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price-sl, mDigits); - } - - if (orderType==ORDER_TYPE_SELL) { - if (request.price==0.0) request.price = SymbolInfoDouble(mSymbol, SYMBOL_BID); - request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price-tp, mDigits); - request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price+sl, mDigits); - } - - return; - -} - -////New -void CExpertBase::AddSignal(CSignalBase *signal, CSignalBase* &signals[]) { - - int index = ArraySize(signals); - ArrayResize(signals, index+1); - signals[index] = signal; - -} - -////New -ENUM_OFX_SIGNAL_DIRECTION CExpertBase::GetCurrentSignal(CSignalBase* &signals[], - ENUM_OFX_SIGNAL_TYPE signalType) { - - ENUM_OFX_SIGNAL_DIRECTION result = OFX_SIGNAL_NONE; - ENUM_OFX_SIGNAL_DIRECTION r2 = OFX_SIGNAL_NONE; // Just working value - int index = ArraySize(signals); - - if (index<=0) { - - return(result); - - } else { - - signals[0].UpdateSignal(); - result = signals[0].GetSignal(signalType); - - // I have chosen to update all signals in case there is some - // behavour that needs it. The penalty is some performance - // If performance is an issue just add an exit inside the loop - // as the commented line - for (int i = 1; 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 aHfulnnsTyicU2=%ThW&MOyqLbCjJkBz}V;j diff --git a/Include/Generic/HashMap.mqh b/Include/Generic/HashMap.mqh deleted file mode 100644 index 5ae3f60..0000000 --- a/Include/Generic/HashMap.mqh +++ /dev/null @@ -1,617 +0,0 @@ -//+------------------------------------------------------------------+ -//| HashMap.mqh | -//| Copyright 2016-2021, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include -#include -#include -#include "HashSet.mqh" -//+------------------------------------------------------------------+ -//| Struct Entry. | -//| Usage: Internal structure for organization CHashMap. | -//+------------------------------------------------------------------+ -template -struct Entry: public Slot - { -public: - TKey key; - Entry(void): key((TKey)NULL) {} - }; -//+------------------------------------------------------------------+ -//| Class CKeyValuePair. | -//| Usage: Defines a key/value pair that can be set or retrieved. | -//+------------------------------------------------------------------+ -template -class CKeyValuePair: public IComparable*> - { -protected: - TKey m_key; - TValue m_value; - -public: - CKeyValuePair(void) { } - CKeyValuePair(TKey key,TValue value): m_key(key), m_value(value) { } - ~CKeyValuePair(void) { } - //--- methods to access protected data - TKey Key(void) { return(m_key); } - void Key(TKey key) { m_key=key; } - TValue Value(void) { return(m_value); } - void Value(TValue value) { m_value=value; } - //--- method to create clone of current instance - CKeyValuePair*Clone(void) { return new CKeyValuePair(m_key,m_value); } - //--- method to compare keys - int Compare(CKeyValuePair*pair) { return ::Compare(m_key,pair.m_key); } - //--- method for determining equality - bool Equals(CKeyValuePair*pair) { return ::Equals(m_key,pair.m_key); } - //--- method to calculate hash code - int HashCode(void) { return ::GetHashCode(m_key); } - }; -//+------------------------------------------------------------------+ -//| Class CKeyValuePairComparer. | -//| Usage: Provides a comparer class for convertation IComparer| -//| to the IComparer*> interface. | -//+------------------------------------------------------------------+ -template -class CKeyValuePairComparer: public IComparer*> - { -private: - IComparer*m_comparer; - -public: - CKeyValuePairComparer(IComparer*comaprer) { m_comparer=comaprer; } - int Compare(CKeyValuePair* x,CKeyValuePair* y) { return(m_comparer.Compare(x.Key(), y.Key())); } - }; -//+------------------------------------------------------------------+ -//| Class CHashMap. | -//| Usage: Represents a collection of keys and values. | -//+------------------------------------------------------------------+ -template -class CHashMap: public IMap - { -protected: - int m_buckets[]; - Entrym_entries[]; - int m_count; - int m_capacity; - int m_free_list; - int m_free_count; - IEqualityComparer*m_comparer; - bool m_delete_comparer; - -public: - CHashMap(void); - CHashMap(const int capacity); - CHashMap(IEqualityComparer*comparer); - CHashMap(const int capacity,IEqualityComparer*comparer); - CHashMap(IMap*map); - CHashMap(IMap*map,IEqualityComparer*comparer); - ~CHashMap(void); - //--- methods of filling data - bool Add(CKeyValuePair*pair); - bool Add(TKey key,TValue value); - //--- methods of access to protected data - int Count(void) { return(m_count-m_free_count); } - IEqualityComparer*Comparer(void) const { return(m_comparer); } - bool Contains(CKeyValuePair*item); - bool Contains(TKey key,TValue value); - bool ContainsKey(TKey key); - bool ContainsValue(TValue value); - //--- methods of copy data from collection - int CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0); - int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0); - //--- methods of cleaning and deleting - void Clear(void); - bool Remove(CKeyValuePair*item); - bool Remove(TKey key); - //--- method of access to the data - bool TryGetValue(TKey key,TValue &value); - bool TrySetValue(TKey key,TValue value); - -private: - void Initialize(const int capacity); - void Resize(int new_size); - int FindEntry(TKey key); - bool Insert(TKey key,TValue value,const bool add); - static int m_collision_threshold; - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashMap class | -//| that is empty, has the default initial capacity, and uses the | -//| default equality comparer for the key type. | -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(void): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashMap class | -//| that is empty, has the specified initial capacity, and uses the | -//| default equality comparer for the key type. | -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(const int capacity): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { -//--- set capacity - if(capacity>0) - Initialize(capacity); -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashMap class | -//| that is empty, has the default initial capacity, and uses the | -//| specified IEqualityComparer. | -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(IEqualityComparer*comparer): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified equality comaprer - m_comparer=comparer; - m_delete_comparer=false; - } - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashMap class | -//| that is empty, has the specified initial capacity, and uses the | -//| specified IEqualityComparer. | -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(const int capacity,IEqualityComparer*comparer): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { - if(capacity>0) - Initialize(capacity); -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified equality comaprer - m_comparer=comparer; - m_delete_comparer=false; - } - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashMap class | -//| that contains elements copied from the specified | -//| IMap and uses the default equality comparer for the | -//| key type. | -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(IMap*map): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; -//--- check map - if(CheckPointer(map)!=POINTER_INVALID && map.Count()>0) - { - //--- set capacity - Initialize(map.Count()); - TKey keys[]; - TValue values[]; - map.CopyTo(keys,values); - //--- copy all keys and values from specified map to current map - for(int i=0; i class | -//| that contains elements copied from the specified | -//| IMap and uses the specified IEqualityComparer.| -//+------------------------------------------------------------------+ -template -CHashMap::CHashMap(IMap*map,IEqualityComparer*comparer): m_count(0), - m_free_list(0), - m_free_count(0), - m_capacity(0) - { -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified equality comaprer - m_comparer=comparer; - m_delete_comparer=false; - } -//--- check map - if(CheckPointer(map)!=POINTER_INVALID && map.Count()>0) - { - //--- set capacity - Initialize(map.Count()); - TKey keys[]; - TValue values[]; - map.CopyTo(keys,values); - //--- copy all keys and values from specified map to current map - for(int i=0; i -CHashMap::~CHashMap(void) - { - if(m_delete_comparer) - delete m_comparer; - } -//+------------------------------------------------------------------+ -//| Adds the specified key-value pair to the map. | -//+------------------------------------------------------------------+ -template -bool CHashMap::Add(CKeyValuePair*pair) - { -//--- check pair - if(CheckPointer(pair)==POINTER_INVALID) - return(false); - return Add(pair.Key(),pair.Value()); - } -//+------------------------------------------------------------------+ -//| Adds the specified key and value to the map. | -//+------------------------------------------------------------------+ -template -bool CHashMap::Add(TKey key,TValue value) - { - return Insert(key,value,true); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified key-value pair.| -//+------------------------------------------------------------------+ -template -bool CHashMap::Contains(CKeyValuePair*item) - { -//--- check pair - if(CheckPointer(item)==POINTER_INVALID) - return(false); -//--- find pair with specified key - int i=FindEntry(item.Key()); -//--- create default equality value comparer - CDefaultEqualityComparercomparer; -//--- check value is equal value from the found pair - if(i>=0 && comparer.Equals(m_entries[i].value,item.Value())) - return(true); - else - return(false); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified key with value.| -//+------------------------------------------------------------------+ -template -bool CHashMap::Contains(TKey key,TValue value) - { -//--- find pair with specified key - int i=FindEntry(key); -//--- create default equality value comparer - CDefaultEqualityComparercomparer; -//--- check value is equal value from the found pair - if(i>=0 && comparer.Equals(m_entries[i].value,value)) - return(true); - else - return(false); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified key. | -//+------------------------------------------------------------------+ -template -bool CHashMap::ContainsKey(TKey key) - { - return(FindEntry(key)>=0); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified value. | -//+------------------------------------------------------------------+ -template -bool CHashMap::ContainsValue(TValue value) - { -//--- create default equality value comparer - CDefaultEqualityComparercomparer_value(); -//--- try to find pair contains specified value - for(int i=0; i=0 && comparer_value.Equals(m_entries[i].value,value)) - return(true); - return(false); - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the map to a compatible | -//| one-dimensional array. | -//+------------------------------------------------------------------+ -template -int CHashMap::CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0) - { -//--- resize array - if(dst_start+m_count>ArraySize(dst_array)) - ArrayResize(dst_array,dst_start+m_count); -//--- start copy - int index=0; - for(int i=0; i=0) - { - //--- check indexes - if(dst_start+index>=ArraySize(dst_array) || index>=m_count) - return(index); - dst_array[dst_start+index++]=new CKeyValuePair(m_entries[i].key,m_entries[i].value); - } - return(index); - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the map to a compatible | -//| one-dimensionals keys and values arrays. | -//+------------------------------------------------------------------+ -template -int CHashMap::CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0) - { - int count=m_count-m_free_count; -//--- resize keys array - if(dst_start+count>ArraySize(dst_keys)) - ArrayResize(dst_keys,dst_start+count); -//--- resize values array - if(dst_start+count>ArraySize(dst_values)) - ArrayResize(dst_values,MathMin(ArraySize(dst_keys),dst_start+count)); -//--- start copy - int index=0; - for(int i=0; i=0) - { - //--- check indexes - if(dst_start+index>=ArraySize(dst_keys) || dst_start+index>=ArraySize(dst_values) || index>=count) - return(index); - dst_keys[dst_start+index]=m_entries[i].key; - dst_values[dst_start+index]=m_entries[i].value; - index++; - } - return(index); - } -//+------------------------------------------------------------------+ -//| Removes all keys and values from the map. | -//+------------------------------------------------------------------+ -template -void CHashMap::Clear(void) - { -//--- check count - if(m_count>0) - { - ArrayFill(m_buckets,0,m_capacity,-1); - ArrayFree(m_entries); - m_count=0; - m_free_list=-1; - m_free_count=0; - } - } -//+------------------------------------------------------------------+ -//| Removes the specified key-value pair from map. | -//+------------------------------------------------------------------+ -template -bool CHashMap::Remove(CKeyValuePair*item) - { -//--- check pair - if(CheckPointer(item)==POINTER_INVALID) - return(false); -//--- find pair with specified key - int i=FindEntry(item.Key()); -//--- create default equality value comparer - CDefaultEqualityComparercomparer_value(); -//--- remove pair - if(i>=0 && comparer_value.Equals(m_entries[i].value,item.Value())) - return Remove(item.Key()); - return(false); - } -//+------------------------------------------------------------------+ -//| Removes the value with the specified key from the map. | -//+------------------------------------------------------------------+ -template -bool CHashMap::Remove(TKey key) - { - if(m_capacity!=0) - { - int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF; - int bucket=hash_code%m_capacity; - int last=-1; - //--- search pair with specified key - for(int i=m_buckets[bucket]; i>=0; last=i,i=m_entries[i].next) - { - if(m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key)) - { - if(last<0) - m_buckets[bucket]=m_entries[i].next; - else - m_entries[last].next=m_entries[i].next; - //--- remove pair - m_entries[i].hash_code=-1; - m_entries[i].next=m_free_list; - m_entries[i].key=(TKey)NULL; - m_entries[i].value=(TValue)NULL; - //--- incremet free count - m_free_list=i; - m_free_count++; - return(true); - } - } - } - return(false); - } -//+------------------------------------------------------------------+ -//| Gets the value associated with the specified key. | -//+------------------------------------------------------------------+ -template -bool CHashMap::TryGetValue(TKey key,TValue &value) - { -//--- find pair with specified key - int i=FindEntry(key); -//--- check index - if(i>=0) - { - //--- get value - value=m_entries[i].value; - return(true); - } - return(false); - } -//+------------------------------------------------------------------+ -//| Sets the value associated with the specified key. | -//+------------------------------------------------------------------+ -template -bool CHashMap::TrySetValue(TKey key,TValue value) - { - return Insert(key, value, false); - } -//+------------------------------------------------------------------+ -//| Initialize map with specified capacity. | -//+------------------------------------------------------------------+ -template -void CHashMap::Initialize(const int capacity) - { - m_capacity=CPrimeGenerator::GetPrime(capacity); - ArrayResize(m_buckets,m_capacity); - ArrayFill(m_buckets,0,m_capacity,-1); - ArrayResize(m_entries,m_capacity); - m_free_list=-1; - } -//+------------------------------------------------------------------+ -//| Resize map. | -//+------------------------------------------------------------------+ -template -void CHashMap::Resize(const int new_size) - { -//--- resize buckets - ArrayResize(m_buckets,new_size); - ArrayFill(m_buckets,0,new_size,-1); -//--- resize entries - ArrayResize(m_entries,new_size); -//--- restore buckets - for(int i=0; i=0) - { - int bucket=m_entries[i].hash_code%new_size; - m_entries[i].next = m_buckets[bucket]; - m_buckets[bucket] = i; - } -//--- restore capacity - m_capacity=new_size; - } -//+------------------------------------------------------------------+ -//| Find index of entry with specified key. | -//+------------------------------------------------------------------+ -template -int CHashMap::FindEntry(TKey key) - { - if(m_capacity!=NULL) - { - //--- get hash code from key - int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF; - //--- search pair with specified key - for(int i=m_buckets[hash_code%m_capacity]; i>=0; i=m_entries[i].next) - if(m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key)) - return(i); - } - return(-1); - } -//+------------------------------------------------------------------+ -//| Insert the value with the specified key from the map. | -//+------------------------------------------------------------------+ -template -bool CHashMap::Insert(TKey key,TValue value,const bool add) - { - if(m_capacity==0) - Initialize(0); -//--- get hash code from key - int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF; - int target_bucket=hash_code%m_capacity; -//--- collisions count in one bucket with different hashes - int collision_count=0; -//--- search pair with specified key - for(int i=m_buckets[target_bucket]; i>=0; i=m_entries[i].next) - { - //--- hash compare - if(m_entries[i].hash_code!=hash_code) - { - collision_count++; - continue; - } - //--- value compare - if(m_comparer.Equals(m_entries[i].key,key)) - { - //--- adding duplicate - if(add) - return(false); - m_entries[i].value=value; - return(true); - } - } -//--- check collision - if(collision_count>=m_collision_threshold) - { - int new_size=CPrimeGenerator::ExpandPrime(m_count); - Resize(new_size); - target_bucket=hash_code%new_size; - } -//--- calculate index - int index; - if(m_free_count>0) - { - index=m_free_list; - m_free_list=m_entries[index].next; - m_free_count--; - } - else - { - if(m_count==ArraySize(m_entries)) - { - int new_size=CPrimeGenerator::ExpandPrime(m_count); - Resize(new_size); - target_bucket=hash_code%new_size; - } - index=m_count; - m_count++; - } -//--- set pair - m_entries[index].hash_code=hash_code; - m_entries[index].next=m_buckets[target_bucket]; - m_entries[index].key=key; - m_entries[index].value=value; - m_buckets[target_bucket]=index; - return(true); - } -template -static int CHashMap::m_collision_threshold=8; -//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/Include/Generic/HashSet.mqh b/Include/Generic/HashSet.mqh deleted file mode 100644 index fbb2141..0000000 --- a/Include/Generic/HashSet.mqh +++ /dev/null @@ -1,972 +0,0 @@ -//+------------------------------------------------------------------+ -//| HashSet.mqh | -//| Copyright 2016-2021, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include -#include -//+------------------------------------------------------------------+ -//| Struct Slot. | -//| Usage: Internal structure for organization CHashSet. | -//+------------------------------------------------------------------+ -template -struct Slot - { -public: - int hash_code; - T value; - int next; - Slot(void): hash_code(0),value((T)NULL),next(0) {} - }; -//+------------------------------------------------------------------+ -//| Class CHashSet. | -//| Usage: Represents a set of unique values. | -//+------------------------------------------------------------------+ -template -class CHashSet: public ISet - { -protected: - int m_buckets[]; - Slot m_slots[]; - int m_count; - int m_last_index; - int m_free_list; - IEqualityComparer*m_comparer; - bool m_delete_comparer; - -public: - CHashSet(void); - CHashSet(IEqualityComparer*comparer); - CHashSet(ICollection*collection); - CHashSet(ICollection*collection,IEqualityComparer*comparer); - CHashSet(T &array[]); - CHashSet(T &array[],IEqualityComparer*comparer); - ~CHashSet(void); - //--- methods of filling data - bool Add(T value); - //--- methods of access to protected data - int Count(void) { return(m_count); } - IEqualityComparer* Comparer(void) const { return(m_comparer); } - bool Contains(T item); - void TrimExcess(void); - //--- methods of copy data from collection - int CopyTo(T &ds_array[],const int dst_start=0); - //--- methods of cleaning and deleting - void Clear(void); - bool Remove(T item); - //--- methods of changing sets - void ExceptWith(ICollection*collection); - void ExceptWith(T &array[]); - void IntersectWith(ICollection*collection); - void IntersectWith(T &array[]); - void SymmetricExceptWith(ICollection*collection); - void SymmetricExceptWith(T &array[]); - void UnionWith(ICollection*collection); - void UnionWith(T &array[]); - //--- methods for determining the relationship between sets - bool IsProperSubsetOf(ICollection*collection); - bool IsProperSubsetOf(T &array[]); - bool IsProperSupersetOf(ICollection*collection); - bool IsProperSupersetOf(T &array[]); - bool IsSubsetOf(ICollection*collection); - bool IsSubsetOf(T &array[]); - bool IsSupersetOf(ICollection*collection); - bool IsSupersetOf(T &array[]); - bool Overlaps(ICollection*collection); - bool Overlaps(T &array[]); - bool SetEquals(ICollection*collection); - bool SetEquals(T &array[]); - -private: - void SetCapacity(const int new_size,bool new_hash_codes); - bool AddIfNotPresent(T value); - void Initialize(const int capacity); - void InternalSymmetricExceptWith(CHashSet*set); - bool InternalIsSubsetOf(CHashSet*set); - bool InternalIsSupersetOf(CHashSet*set); - bool InternalIsProperSubsetOf(CHashSet*set); - bool InternalIsProperSupersetOf(CHashSet*set); - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that is empty| -//| and uses the default equality comparer for the set type. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(void): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that is empty| -//| and uses the specified equality comparer for the set type. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(IEqualityComparer*comparer): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified equality comaprer - m_comparer=comparer; - m_delete_comparer=false; - } - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that uses the| -//| default equality comparer for the set type, contains elements | -//| copied from the specified collection, and has sufficient capacity| -//| to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(ICollection*collection): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- set capacity for elements of the collection - int count=collection.Count(); - Initialize(count); -//--- add element from collection to the set - this.UnionWith(collection); - if((m_count==0 && ArraySize(m_slots)>3) || - (m_count>0 && ArraySize(m_slots)/m_count>3)) - TrimExcess(); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that uses the| -//| specified equality comparer for the set type, contains elements | -//| copied from the specified collection, and has sufficient capacity| -//| to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(ICollection*collection,IEqualityComparer*comparer): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified comaprer - m_comparer=comparer; - m_delete_comparer=false; - } -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- set capacity for elements of the collection - int count=collection.Count(); - Initialize(count); -//--- add element from collection to the set - this.UnionWith(collection); - if((m_count==0 && ArraySize(m_slots)>3) || - (m_count>0 && ArraySize(m_slots)/m_count>3)) - TrimExcess(); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that uses the| -//| default equality comparer for the set type, contains elements | -//| copied from the specified array, and has sufficient capacity to | -//| accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(T &array[]): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; -//--- set capacity for elements of the array - int count=ArraySize(array); - Initialize(count); -//--- add element from array to the set - this.UnionWith(array); - if((m_count==0 && ArraySize(m_slots)>3) || - (m_count>0 && ArraySize(m_slots)/m_count>3)) - TrimExcess(); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CHashSet class that uses the| -//| specified equality comparer for the set type, contains elements | -//| copied from the specified array, and has sufficient capacity to | -//| accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CHashSet::CHashSet(T &array[],IEqualityComparer*comparer): m_count(0), - m_last_index(0), - m_free_list(-1) - { -//--- check equality comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default equality comaprer - m_comparer=new CDefaultEqualityComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified comaprer - m_comparer=comparer; - m_delete_comparer=false; - } -//--- set capacity for elements of the array - int count=ArraySize(array); - Initialize(count); -//--- add element from array to the set - this.UnionWith(array); - if((m_count==0 && ArraySize(m_slots)>3) || - (m_count>0 && ArraySize(m_slots)/m_count>3)) - TrimExcess(); - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -template CHashSet::~CHashSet(void) - { - if(m_delete_comparer) - delete m_comparer; - } -//+------------------------------------------------------------------+ -//| Adds the specified element to a set. | -//+------------------------------------------------------------------+ -template -bool CHashSet::Add(T value) - { - return AddIfNotPresent(value); - } -//+------------------------------------------------------------------+ -//| Determines whether a set contains the specified element. | -//+------------------------------------------------------------------+ -template -bool CHashSet::Contains(T item) - { -//--- check buckets - if(ArraySize(m_buckets)!=0) - { - //--- get hash code for item - int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF; - //--- search item in the slots - for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next) - if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item)) - return(true); - } - return(false); - } -//+------------------------------------------------------------------+ -//| Sets the capacity of a set to the actual number of elements it | -//| contains, rounded up to a nearby, implementation-specific value. | -//+------------------------------------------------------------------+ -template -void CHashSet::TrimExcess(void) - { - if(m_count==0) - { - ArrayFree(m_buckets); - ArrayFree(m_slots); - } - else - { - //--- calculate min prime size for current count - int new_size=CPrimeGenerator::GetPrime(m_count); - //--- resize buckets and slots - ArrayResize(m_slots,new_size); - ArrayResize(m_buckets,new_size); - //--- restore buckets and slots - int new_index=0; - for(int i=0; i=0) - { - m_slots[new_index]=m_slots[i]; - //--- rehash - int bucket=m_slots[new_index].hash_code%new_size; - m_slots[new_index].next=m_buckets[bucket]-1; - m_buckets[bucket]=new_index+1; - //--- increment index - new_index++; - } - } - m_last_index=new_index; - m_free_list=-1; - } - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the set to a compatible | -//| one-dimensional array. | -//+------------------------------------------------------------------+ -template -int CHashSet::CopyTo(T &dst_array[],const int dst_start) - { -//--- resize array - if(dst_start+m_count>ArraySize(dst_array)) - ArrayResize(dst_array,dst_start+m_count); -//--- start copy - int index=0; - for(int i=0; i=0) - { - if(dst_start+index>=ArraySize(dst_array) || index>=m_count) - return(index); - dst_array[dst_start+index++]=m_slots[i].value; - } - return(index); - } -//+------------------------------------------------------------------+ -//| Removes all elements from a set. | -//+------------------------------------------------------------------+ -template -void CHashSet::Clear(void) - { - if(m_last_index>0) - { - ArrayFree(m_slots); - ArrayFree(m_buckets); - m_last_index=0; - m_count=0; - m_free_list=-1; - } - } -//+------------------------------------------------------------------+ -//| Removes the specified element from a set. | -//+------------------------------------------------------------------+ -template -bool CHashSet::Remove(T item) - { - if(ArraySize(m_buckets)!=0) - { - //--- get hash code for item - int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF; - int bucket=hash_code%ArraySize(m_buckets); - int last=-1; - //--- search item - for(int i=m_buckets[bucket]-1; i>=0; last=i,i=m_slots[i].next) - { - if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item)) - { - if(last<0) - m_buckets[bucket]=m_slots[i].next+1; - else - m_slots[last].next=m_slots[i].next; - //--- remove item - m_slots[i].hash_code=-1; - m_slots[i].value=(T)NULL; - m_slots[i].next =m_free_list; - //--- decrement count - m_count--; - if(m_count==0) - { - m_last_index= 0; - m_free_list = -1; - } - else - { - m_free_list=i; - } - return(true); - } - } - } - return(false); - } -//+------------------------------------------------------------------+ -//| Removes all elements in the specified collection from the current| -//| set. | -//+------------------------------------------------------------------+ -template -void CHashSet::ExceptWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- this is already the enpty set - if(m_count==0) - return; -//--- special case if collecion is this -//--- a set minus itself is the empty set - if(collection==GetPointer(this)) - { - Clear(); - return; - } -//--- copy collection to array - T array[]; - collection.CopyTo(array,0); -//--- remove every element in collection from this - for(int i=0; i -void CHashSet::ExceptWith(T &array[]) - { -//--- this is already the enpty set - if(m_count==0) - return; -//--- remove every element in collection from this - for(int i=0; i -void CHashSet::IntersectWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- intersection of anything with empty set is empty set, so return if count is 0 - if(m_count==0) - return; -//--- if collection is empty, intersection is empty set - if(collection.Count()==0) - { - Clear(); - return; - } -//--- intersect - for(int i=0; i=0) - { - T item=m_slots[i].value; - if(!collection.Contains(item)) - Remove(item); - } - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present in that object and in the specified array. | -//+------------------------------------------------------------------+ -template -void CHashSet::IntersectWith(T &array[]) - { -//--- intersection of anything with empty set is empty set, so return if count is 0 - if(m_count==0) - return; -//--- if collection is empty, intersection is empty set - if(ArraySize(array)==0) - { - Clear(); - return; - } -//--- intersect - CHashSetset(array); - for(int i=0; i=0) - { - T item=m_slots[i].value; - if(!set.Contains(item)) - Remove(item); - } - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present either in that set or in the specified collection, but | -//| not both. | -//+------------------------------------------------------------------+ -template -void CHashSet::SymmetricExceptWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- if set is empty, then symmetric difference is other - if(m_count==0) - { - UnionWith(collection); - return; - } -//--- special case this; the symmetric difference of a set with itself is the empty set - if(collection==GetPointer(this)) - { - Clear(); - return; - } -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - InternalSymmetricExceptWith(ptr_set); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - InternalSymmetricExceptWith(GetPointer(set)); - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present either in that set or in the specified array, but not | -//| both. | -//+------------------------------------------------------------------+ -template -void CHashSet::SymmetricExceptWith(T &array[]) - { -//--- if set is empty, then symmetric difference is other - if(m_count==0) - { - UnionWith(array); - return; - } -//--- symmetric except - CHashSetset(array); - InternalSymmetricExceptWith(GetPointer(set)); - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain all elements that are present| -//| in itself, the specified collection, or both. | -//+------------------------------------------------------------------+ -template -void CHashSet::UnionWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- get array from collection - T array[]; - collection.CopyTo(array); -//--- union array with the current set - UnionWith(array); - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain all elements that are present| -//| in itself, the specified array, or both. | -//+------------------------------------------------------------------+ -template -void CHashSet::UnionWith(T &array[]) - { - for(int i=0; i -bool CHashSet::IsProperSubsetOf(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- the empty set is a proper subset of anything but the empty set - if(m_count==0) - return(collection.Count()>0); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return InternalIsProperSubsetOf(ptr_set); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return InternalIsProperSubsetOf(GetPointer(set)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper subset of the specified | -//| array. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsProperSubsetOf(T &array[]) - { -//--- the empty set is a proper subset of anything but the empty set - if(m_count==0) - return(ArraySize(array)>0); -//--- create a set based on a specified array - CHashSetset(array); - return InternalIsProperSubsetOf(GetPointer(set)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper superset of the specified | -//| collection. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsProperSupersetOf(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(m_count>0); -//--- the empty set is a proper subset of anything but the empty set - if(m_count==0) - return(false); -//--- if other is the empty set then this is a superset - if(collection.Count()==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return InternalIsProperSupersetOf(ptr_set); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return InternalIsProperSupersetOf(GetPointer(set)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper superset of the specified | -//| array. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsProperSupersetOf(T &array[]) - { -//--- the empty set is a proper subset of anything but the empty set - if(m_count==0) - return(false); -//--- if other is the empty set then this is a superset - if(ArraySize(array)==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - return InternalIsProperSupersetOf(GetPointer(set)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a subset of the specified collection.| -//+------------------------------------------------------------------+ -template -bool CHashSet::IsSubsetOf(ICollection*collection) - { - if(CheckPointer(collection)==POINTER_INVALID) - return(m_count==0); -//--- The empty set is a subset of any set - if(m_count==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return InternalIsSubsetOf(ptr_set); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return InternalIsSubsetOf(GetPointer(set)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a subset of the specified array. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsSubsetOf(T &array[]) - { -//--- The empty set is a subset of any set - if(m_count==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - return InternalIsSubsetOf(GetPointer(set)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a superset of the specified | -//| collection. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsSupersetOf(ICollection*collection) - { - if(CheckPointer(collection)==POINTER_INVALID) - return(m_count>=0); -//--- if other is the empty set then this is a superset - if(collection.Count()==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return InternalIsSupersetOf(ptr_set); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return InternalIsSupersetOf(GetPointer(set)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a superset of the specified array. | -//+------------------------------------------------------------------+ -template -bool CHashSet::IsSupersetOf(T &array[]) - { -//--- if other is the empty set then this is a superset - if(ArraySize(array)==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - return InternalIsSupersetOf(GetPointer(set)); - } -//+------------------------------------------------------------------+ -//| Determines whether the current set and a specified collection | -//| share common elements. | -//+------------------------------------------------------------------+ -template -bool CHashSet::Overlaps(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- check current count - if(m_count==0) - return(false); -//--- get array from collection - T array[]; - collection.CopyTo(array); -//--- check overlaps between current set and array - return Overlaps(array); - } -//+------------------------------------------------------------------+ -//| Determines whether the current set and a specified array share | -//| common elements. | -//+------------------------------------------------------------------+ -template -bool CHashSet::Overlaps(T &array[]) - { -//--- check current count - if(m_count==0) - return(false); -//--- try to find any elements from specified array in current set - for(int i=0; i -bool CHashSet::SetEquals(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- check current set is equal specified collection - if(collection==GetPointer(this)) - return(true); -//--- get array from collection - T array[]; - collection.CopyTo(array); -//--- check current set is equal specified array - return SetEquals(array); - } -//+------------------------------------------------------------------+ -//| Determines whether a set and the specified array contain the same| -//| elements. | -//+------------------------------------------------------------------+ -template -bool CHashSet::SetEquals(T &array[]) - { -//--- check size - if(ArraySize(array)!=m_count) - return(false); -//--- check current set is equal specified array - for(int i=0; i -void CHashSet::SetCapacity(const int new_size,bool new_hash_codes) - { -//--- resize slots - ArrayResize(m_slots,new_size); -//--- restore slots - if(new_hash_codes) - for(int i=0; i -bool CHashSet::AddIfNotPresent(T value) - { -//--- set minimum capacity - if(ArraySize(m_buckets)==0) - Initialize(0); -//--- get hash code and bucket for value - int hash_code=m_comparer.HashCode(value)&0x7FFFFFFF; - int bucket=hash_code%ArraySize(m_buckets); -//--- check value already in the set - for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next) - if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,value)) - return(false); -//--- calculate index for value - int index=0; - if(m_free_list>=0) - { - index=m_free_list; - m_free_list=m_slots[index].next; - } - else - { - if(m_last_index==ArraySize(m_slots)) - { - int new_size=CPrimeGenerator::ExpandPrime(m_count); - SetCapacity(new_size,false); - bucket=hash_code%ArraySize(m_buckets); - } - index=m_last_index; - m_last_index++; - } -//--- set value - m_slots[index].hash_code=hash_code; - m_slots[index].value=value; - m_slots[index].next=m_buckets[bucket]-1; - m_buckets[bucket]=index+1; -//--- increase count - m_count++; - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize set with specified capacity. | -//+------------------------------------------------------------------+ -template -void CHashSet::Initialize(const int capacity) - { - int size=CPrimeGenerator::GetPrime(capacity); - ArrayResize(m_buckets,size); - ArrayResize(m_slots,size); - ZeroMemory(m_buckets); - ZeroMemory(m_slots); - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present either in that set or in the specified set, but not both.| -//+------------------------------------------------------------------+ -template -void CHashSet::InternalSymmetricExceptWith(CHashSet*set) - { - for(int i=0; i -bool CHashSet::InternalIsSubsetOf(CHashSet*set) - { -//--- if this has more elements then it can't be a subset - if(m_count>set.m_count) - return(false); -//--- try to find any elements from current set in specified set - for(int i=0; i -bool CHashSet::InternalIsSupersetOf(CHashSet*set) - { -//--- if this has less elements then it can't be a superset - if(set.m_count>m_count) - return(false); -//--- try to find any elements from specified set in current set - for(int i=0; i -bool CHashSet::InternalIsProperSubsetOf(CHashSet*set) - { -//--- if this has more or equal elements then it can't be a proper subset - if(m_count>=set.m_count) - return(false); -//--- try to find any elements from current set in specified set - for(int i=0; i -bool CHashSet::InternalIsProperSupersetOf(CHashSet*set) - { -//--- if this has less or equal elements then it can't be a proper superset - if(m_count<=set.m_count) - return(false); -//--- try to find any elements from specified set in current set - for(int i=0; i. | -//| Usage: Defines methods to manipulate generic collections. | -//+------------------------------------------------------------------+ -template -interface ICollection - { -//--- methods of filling data - bool Add(T value); -//--- methods of access to protected data - int Count(void); - bool Contains(T item); -//--- methods of copy data from collection - int CopyTo(T &dst_array[],const int dst_start=0); -//--- methods of cleaning and removing - void Clear(void); - bool Remove(T item); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IComparable.mqh b/Include/Generic/Interfaces/IComparable.mqh deleted file mode 100644 index 45fb320..0000000 --- a/Include/Generic/Interfaces/IComparable.mqh +++ /dev/null @@ -1,19 +0,0 @@ -//+------------------------------------------------------------------+ -//| IComparable.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "IEqualityComparable.mqh" -//+------------------------------------------------------------------+ -//| Interface IComparable. | -//| Usage: Defines a generalized comparison method to create a | -//| type-specific comparison method for ordering or sorting | -//| instances. | -//+------------------------------------------------------------------+ -template -interface IComparable: public IEqualityComparable - { -//--- method for determining compare - int Compare(T value); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IComparer.mqh b/Include/Generic/Interfaces/IComparer.mqh deleted file mode 100644 index 47862dd..0000000 --- a/Include/Generic/Interfaces/IComparer.mqh +++ /dev/null @@ -1,17 +0,0 @@ -//+------------------------------------------------------------------+ -//| IComparer.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Interface IComparer. | -//| Usage: Defines a method that a type implements to compare two | -//| values. | -//+------------------------------------------------------------------+ -template -interface IComparer - { -//--- compares two values and returns a value indicating whether one is less than, equal to, or greater than the other - int Compare(T x,T y); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IEqualityComparable.mqh b/Include/Generic/Interfaces/IEqualityComparable.mqh deleted file mode 100644 index 5a09bde..0000000 --- a/Include/Generic/Interfaces/IEqualityComparable.mqh +++ /dev/null @@ -1,19 +0,0 @@ -//+------------------------------------------------------------------+ -//| IEqualityComparable.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Interface IEqualityComparable. | -//| Usage: Defines a generalized method to create a type-specific | -//| method for determining equality of instances. | -//+------------------------------------------------------------------+ -template -interface IEqualityComparable - { -//--- method for determining equality - bool Equals(T value); -//--- method to calculate hash code - int HashCode(void); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IEqualityComparer.mqh b/Include/Generic/Interfaces/IEqualityComparer.mqh deleted file mode 100644 index 8fbe395..0000000 --- a/Include/Generic/Interfaces/IEqualityComparer.mqh +++ /dev/null @@ -1,19 +0,0 @@ -//+------------------------------------------------------------------+ -//| IEqualityComparer.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Interface IEqualityComparer. | -//| Usage: Defines methods to support the comparison of values for | -//| equality. | -//+------------------------------------------------------------------+ -template -interface IEqualityComparer - { -//--- determines whether the specified values are equal - bool Equals(T x,T y); -//--- returns a hash code for the specified object - int HashCode(T value); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IList.mqh b/Include/Generic/Interfaces/IList.mqh deleted file mode 100644 index 1384a4c..0000000 --- a/Include/Generic/Interfaces/IList.mqh +++ /dev/null @@ -1,26 +0,0 @@ -//+------------------------------------------------------------------+ -//| IList.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ICollection.mqh" -//+------------------------------------------------------------------+ -//| Interface IList. | -//| Usage: Represents a collection of objects that can be | -//| individually accessed by index. | -//+------------------------------------------------------------------+ -template -interface IList: public ICollection - { -//--- method of access to the data - bool TryGetValue(const int index,T &value); - bool TrySetValue(const int index,T value); -//--- methods of filling the array - bool Insert(const int index,T item); -//--- methods for searching index - int IndexOf(T item); - int LastIndexOf(T item); -//--- methods of cleaning and deleting - bool RemoveAt(const int index); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/IMap.mqh b/Include/Generic/Interfaces/IMap.mqh deleted file mode 100644 index a328492..0000000 --- a/Include/Generic/Interfaces/IMap.mqh +++ /dev/null @@ -1,27 +0,0 @@ -//+------------------------------------------------------------------+ -//| IMap.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ICollection.mqh" -template -class CKeyValuePair; -//+------------------------------------------------------------------+ -//| Interface IMap. | -//| Usage: Represents a generic collection of key/value pairs. | -//+------------------------------------------------------------------+ -template -interface IMap: public ICollection*> - { -//--- methods of filling data - bool Add(TKey key,TValue value); -//--- methods of access to protected data - bool Contains(TKey key,TValue value); - bool Remove(TKey key); -//--- method of access to the data - bool TryGetValue(TKey key,TValue &value); - bool TrySetValue(TKey key,TValue value); -//--- methods of copy data from collection - int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Interfaces/ISet.mqh b/Include/Generic/Interfaces/ISet.mqh deleted file mode 100644 index 29a3839..0000000 --- a/Include/Generic/Interfaces/ISet.mqh +++ /dev/null @@ -1,37 +0,0 @@ -//+------------------------------------------------------------------+ -//| ISet.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ICollection.mqh" -//+------------------------------------------------------------------+ -//| Interface ISet. | -//| Usage: Provides the base interface for the abstraction of sets. | -//+------------------------------------------------------------------+ -template -interface ISet: public ICollection - { -//--- methods of changing sets - void ExceptWith(ICollection*collection); - void ExceptWith(T &array[]); - void IntersectWith(ICollection*collection); - void IntersectWith(T &array[]); - void SymmetricExceptWith(ICollection*collection); - void SymmetricExceptWith(T &array[]); - void UnionWith(ICollection*collection); - void UnionWith(T &array[]); -//--- methods for determining the relationship between sets - bool IsProperSubsetOf(ICollection*collection); - bool IsProperSubsetOf(T &array[]); - bool IsProperSupersetOf(ICollection*collection); - bool IsProperSupersetOf(T &array[]); - bool IsSubsetOf(ICollection*collection); - bool IsSubsetOf(T &array[]); - bool IsSupersetOf(ICollection*collection); - bool IsSupersetOf(T &array[]); - bool Overlaps(ICollection*collection); - bool Overlaps(T &array[]); - bool SetEquals(ICollection*collection); - bool SetEquals(T &array[]); - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/ArrayFunction.mqh b/Include/Generic/Internal/ArrayFunction.mqh deleted file mode 100644 index 1204bc7..0000000 --- a/Include/Generic/Internal/ArrayFunction.mqh +++ /dev/null @@ -1,135 +0,0 @@ -//+------------------------------------------------------------------+ -//| ArrayFunction.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "CompareFunction.mqh" -#include -//+------------------------------------------------------------------+ -//| Searches an entire one-dimensional sorted array for a specific | -//| element, using the IComparable generic interface implemented | -//| by each element of the array and by the specified object. | -//+------------------------------------------------------------------+ -template -int ArrayBinarySearch(T &array[],const int start_index,const int count, T value,IComparer*comparer) - { - int lo=start_index; - int hi=start_index+count-1; - int size=ArraySize(array); -//--- check array size - if(size==0) - return(-1); -//--- check comaparer - if(CheckPointer(comparer)==POINTER_INVALID) - return(-1); -//--- check index - if(start_index<0 || count<0 || size-start_index>1); - int order=comparer.Compare(array[i],value); - if(order==0) - { - return(i); - } - if(order<0) - { - lo=i+1; - } - else - { - hi=i-1; - } - } -//--- returns the index of an element nearest in value - if(lo>0) - return(lo-1); - return(lo); - } -//+------------------------------------------------------------------+ -//| Searches for the specified object and returns the index of its | -//| first occurrence in a one-dimensional array. | -//+------------------------------------------------------------------+ -template -int ArrayIndexOf(T &array[],T value,const int start_index,const int count) - { - int size=ArraySize(array); -//--- check array size - if(size==0) - return(-1); -//--- check start index and count - if(start_index<0 || start_index>size || - count<0 || count>size-start_index) - return(-1); -//--- search value - int end_index=start_index+count; - for(int i=start_index; i -int ArrayLastIndexOf(T &array[],T value,const int start_index,const int count) - { - int size=ArraySize(array); -//--- check array size - if(size==0) - return(-1); -//--- check start index and count - if(start_index<0 || start_index>=size || - count<0 || count>start_index+1) - return(-1); -//--- search value - int end_index=start_index-count+1; - for(int i=start_index; i>=end_index; i--) - { - //--- check the value in array is eqaul to specified value - if(::Equals(array[i],value)) - { - //--- return fist index from the end - return (i); - } - } -//--- return -1 if value not in array - return(-1); - } -//+------------------------------------------------------------------+ -//| Reverses the elements in a range of this array. Following a call | -//| to this method, an element in the range given by index and count | -//| which was previously located at index i will now be located at | -//| index index + (index + count - i - 1). | -//+------------------------------------------------------------------+ -template -bool ArrayReverse(T &array[],const int start_index,const int count) - { - int size=ArraySize(array); -//--- check start index and count - if(count<0 || size-start_index -//+------------------------------------------------------------------+ -//| Compares two objects and returns a value indicating whether one | -//| is less than, equal to, or greater than the other. | -//+------------------------------------------------------------------+ -int Compare(const bool x,const bool y) - { - if(x>y) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(xy) - return(1); - else if(x -int Compare(T x,T y) - { -//--- try to convert to comparable object - IComparable*comparable=dynamic_cast*>(x); - if(comparable) - { - //--- use specied compare method - return comparable.Compare(y); - } - else - { - //--- unknown compare function - return(0); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/DefaultComparer.mqh b/Include/Generic/Internal/DefaultComparer.mqh deleted file mode 100644 index cd4e7fa..0000000 --- a/Include/Generic/Internal/DefaultComparer.mqh +++ /dev/null @@ -1,22 +0,0 @@ -//+------------------------------------------------------------------+ -//| DefaultComparer.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include "CompareFunction.mqh" -//+------------------------------------------------------------------+ -//| Class CDefaultComparer. | -//| Usage: Provides a default class for implementations of the | -//| IComparer generic interface. | -//+------------------------------------------------------------------+ -template -class CDefaultComparer: public IComparer - { -public: - CDefaultComparer(void) { } - ~CDefaultComparer(void) { } - //--- compares two values and returns a value describing relationship between them - int Compare(T x,T y) { return ::Compare(x,y); } - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/DefaultEqualityComparer.mqh b/Include/Generic/Internal/DefaultEqualityComparer.mqh deleted file mode 100644 index 278f71a..0000000 --- a/Include/Generic/Internal/DefaultEqualityComparer.mqh +++ /dev/null @@ -1,25 +0,0 @@ -//+------------------------------------------------------------------+ -//| DefaultEqualityComparer.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include "EqualFunction.mqh" -#include "HashFunction.mqh" -//+------------------------------------------------------------------+ -//| Class CDefaultEqualityComparer. | -//| Usage: Provides a default class for implementations of the | -//| IEqualityComparer generic interface. | -//+------------------------------------------------------------------+ -template -class CDefaultEqualityComparer: public IEqualityComparer - { -public: - CDefaultEqualityComparer(void) { } - ~CDefaultEqualityComparer(void) { } - //--- determines whether the specified values are equal - bool Equals(T x,T y) { return ::Equals(x,y); } - //--- returns a hash code for the specified object - int HashCode(T value) { return ::GetHashCode(value); } - }; -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/EqualFunction.mqh b/Include/Generic/Internal/EqualFunction.mqh deleted file mode 100644 index 1eb92a6..0000000 --- a/Include/Generic/Internal/EqualFunction.mqh +++ /dev/null @@ -1,26 +0,0 @@ -//+------------------------------------------------------------------+ -//| EqualFunction.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Indicates whether x object is equal y object of the same type. | -//+------------------------------------------------------------------+ -template -bool Equals(T x,T y) - { -//--- try to convert to equality comparable object - IEqualityComparable*equtable=dynamic_cast*>(x); - if(equtable) - { - //--- use specied equality compare method - return equtable.Equals(y); - } - else - { - //--- use default equality comparer operator - return(x==y); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/HashFunction.mqh b/Include/Generic/Internal/HashFunction.mqh deleted file mode 100644 index 209f6c4..0000000 --- a/Include/Generic/Internal/HashFunction.mqh +++ /dev/null @@ -1,176 +0,0 @@ -//+------------------------------------------------------------------+ -//| HashFunction.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Unioun BitInterpreter. | -//| Usage: Provides the ability to interpret the same bit sequence in| -//| different types. | -//+------------------------------------------------------------------+ -union BitInterpreter - { - bool bool_value; - char char_value; - uchar uchar_value; - short short_value; - ushort ushort_value; - color color_value; - int int_value; - uint uint_value; - datetime datetime_value; - long long_value; - ulong ulong_value; - float float_value; - double double_value; - }; -//+------------------------------------------------------------------+ -//| Returns a hashcode for boolean. | -//+------------------------------------------------------------------+ -int GetHashCode(const bool value) - { - return((value)?true:false); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for character. | -//+------------------------------------------------------------------+ -int GetHashCode(const char value) - { - return((int)value | ((int)value << 16)); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for unsigned character. | -//+------------------------------------------------------------------+ -int GetHashCode(const uchar value) - { - return((int)value | ((int)value << 16)); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for short. | -//+------------------------------------------------------------------+ -int GetHashCode(const short value) - { - return(((int)((ushort)value) | (((int)value) << 16))); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for unsigned short. | -//+------------------------------------------------------------------+ -int GetHashCode(const ushort value) - { - return((int)value); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for color. | -//+------------------------------------------------------------------+ -int GetHashCode(const color value) - { - return((int)value); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for integer. | -//+------------------------------------------------------------------+ -int GetHashCode(const int value) - { - return(value); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for unsigned integer. | -//+------------------------------------------------------------------+ -int GetHashCode(const uint value) - { - return((int)value); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for datetime. | -//+------------------------------------------------------------------+ -int GetHashCode(const datetime value) - { - long ticks=(long)value; - return(((int)ticks) ^ (int)(ticks >> 32)); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for long. | -//+------------------------------------------------------------------+ -int GetHashCode(const long value) - { - return(((int)((long)value)) ^ (int)(value >> 32)); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for unsigned long. | -//+------------------------------------------------------------------+ -int GetHashCode(const ulong value) - { - return(((int)value) ^ (int)(value >> 32)); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for float. | -//+------------------------------------------------------------------+ -int GetHashCode(const float value) - { - if(value==0) - { - //--- ensure that 0 and -0 have the same hash code - return(0); - } - BitInterpreter convert; - convert.float_value=value; - return(convert.int_value); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for string. | -//+------------------------------------------------------------------+ -int GetHashCode(const double value) - { - if(value==0) - { - //--- ensure that 0 and -0 have the same hash code - return(0); - } - BitInterpreter convert; - convert.double_value=value; - long lvalue=convert.long_value; - return(((int)lvalue) ^ ((int)(lvalue >> 32))); - } -//+------------------------------------------------------------------+ -//| Returns a hashcode for string. | -//| The hashcode for a string is computed as: | -//| | -//| s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] | -//| | -//| using int arithmetic, where s[i] is the ith character of the | -//| string, n is the length of the string, and ^ indicates | -//| exponentiation. (The hash value of the empty string is zero.) | -//+------------------------------------------------------------------+ -int GetHashCode(const string value) - { - int len=StringLen(value); - int hash=0; -//--- check length of string - if(len>0) - { - //--- calculate a hash as a fucntion of each char - for(int i=0; i -int GetHashCode(T value) - { -//--- try to convert to equality comparable object - IEqualityComparable*equtable=dynamic_cast*>(value); - if(equtable) - { - //--- calculate hash by specied method - return equtable.HashCode(); - } - else - { - //--- calculate hash from name of object - return GetHashCode(typename(value)); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Internal/Introsort.mqh b/Include/Generic/Internal/Introsort.mqh deleted file mode 100644 index 8ac3ad6..0000000 --- a/Include/Generic/Internal/Introsort.mqh +++ /dev/null @@ -1,251 +0,0 @@ -//+------------------------------------------------------------------+ -//| Introsort.mqh | -//| Copyright 2016, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Struct Introsort. | -//| Usage: Used by the sort methods for instances of array. | -//+------------------------------------------------------------------+ -template -struct Introsort - { -public: - IComparer*comparer; - TKey keys[]; - TItem items[]; - - Introsort(void) {} - ~Introsort(void) {} - //--- method for sort array - void Sort(const int index,const int length); -private: - //--- methods for introspective sorting - void IntroSort(const int lo,const int hi,int depthLimit); - int PickPivotAndPartition(const int lo,const int hi); - void InsertionSort(const int lo,const int hi); - //--- methods for heap sorting - void Heapsort(const int lo,const int hi); - void DownHeap(const int i,const int n,const int lo); - //--- swap methods - void SwapIfGreaterWithItems(const int a,const int b); - void Swap(const int i,const int j); - //--- service methods - int FloorLog2(int n) const; - }; -//+------------------------------------------------------------------+ -//| IntrospectiveSort is a hybrid sorting algorithm that provides | -//| both fast average performance and (asymptotically) optimal | -//| worst-case performance. It begins with quicksort and switches to | -//| heapsort when the recursion depth exceeds a level based on the | -//| number of elements being sorted. | -//+------------------------------------------------------------------+ -template -void Introsort::Sort(const int index,const int length) - { - if(length<2) - return; - IntroSort(index,length+index-1,2*FloorLog2(ArraySize(keys))); - } -//+------------------------------------------------------------------+ -//| Exchanges the values of a and b, if a greater b. | -//+------------------------------------------------------------------+ -template -void Introsort::SwapIfGreaterWithItems(const int a,const int b) - { - if(a!=b) - { - if(comparer.Compare(keys[a],keys[b])>0) - { - TKey key=keys[a]; - keys[a]=keys[b]; - keys[b]=key; - if(ArraySize(items)!=NULL) - { - TItem item=items[a]; - items[a]=items[b]; - items[b]=item; - } - } - } - } -//+------------------------------------------------------------------+ -//| Exchanges the values of a and b. | -//+------------------------------------------------------------------+ -template -void Introsort::Swap(const int i,const int j) - { - TKey key=keys[i]; - keys[i]=keys[j]; - keys[j]=key; - if(ArraySize(items)!=NULL) - { - TItem item=items[i]; - items[i]=items[j]; - items[j]=item; - } - } -//+------------------------------------------------------------------+ -//| Returns the closest integer value less than or equal to the base | -//| 2 log of the input value. | -//+------------------------------------------------------------------+ -template -int Introsort::FloorLog2(int n) const - { - int result=0; - while(n>=1) - { - result++; - n=n/2; - } - return(result); - } -//+------------------------------------------------------------------+ -//| Introspective sort. | -//+------------------------------------------------------------------+ -template -void Introsort::IntroSort(const int lo,int hi,int depthLimit) - { - const int IntrosortSizeThreshold=16; - while(hi>lo) - { - int partitionSize = hi - lo + 1; - if(partitionSize <= IntrosortSizeThreshold) - { - if(partitionSize==1) - { - return; - } - if(partitionSize==2) - { - SwapIfGreaterWithItems(lo,hi); - return; - } - if(partitionSize==3) - { - SwapIfGreaterWithItems(lo,hi-1); - SwapIfGreaterWithItems(lo,hi); - SwapIfGreaterWithItems(hi-1,hi); - return; - } - InsertionSort(lo,hi); - return; - } - if(depthLimit==0) - { - Heapsort(lo,hi); - return; - } - depthLimit--; - int p=PickPivotAndPartition(lo,hi); - IntroSort(p+1,hi,depthLimit); - hi=p-1; - } - } -//+------------------------------------------------------------------+ -//| Insertion sort. | -//+------------------------------------------------------------------+ -template -void Introsort::InsertionSort(const int lo,const int hi) - { - int i,j; - TKey t; - TItem dt; - for(i=lo; i=lo && comparer.Compare(t,keys[j])<0) - { - keys[j+1]=keys[j]; - if(ArraySize(items)!=NULL) - { - items[j+1]=items[j]; - } - j--; - } - keys[j+1]=t; - if(ArraySize(items)!=NULL) - { - items[j+1]=dt; - } - } - } -//+------------------------------------------------------------------+ -//| Array partitioning by a quick sort algorithm. | -//+------------------------------------------------------------------+ -template -int Introsort::PickPivotAndPartition(const int lo,const int hi) - { -//--- Compute median-of-three. But also partition them, since we've done the comparison. - int mid=lo+(hi-lo)/2; - SwapIfGreaterWithItems(lo,mid); - SwapIfGreaterWithItems(lo,hi); - SwapIfGreaterWithItems(mid,hi); - TKey pivot=keys[mid]; - Swap(mid,hi-1); - int left=lo,right=hi-1; - while(left=right) - break; - Swap(left,right); - } -//--- Put pivot in the right location. - Swap(left,(hi-1)); - return (left); - } -//+------------------------------------------------------------------+ -//| Heap sorting algorithm. | -//+------------------------------------------------------------------+ -template -void Introsort::Heapsort(const int lo,const int hi) - { - int n=hi-lo+1; - for(int i=n/2; i>=1; i=i-1) - { - DownHeap(i,n,lo); - } - for(int i=n; i>1; i=i-1) - { - Swap(lo,lo+i-1); - DownHeap(1,i-1,lo); - } - } -//+------------------------------------------------------------------+ -//| Downheap function for heapsort. | -//+------------------------------------------------------------------+ -template -void Introsort::DownHeap(int i,const int n,const int lo) - { - TKey d=keys[lo+i-1]; - TItem dt=items[lo+i-1]; - int child; - while(i<=n/2) - { - child=2*i; - if(child=min) - return(prime); - } -//--- outside of our predefined table - for(int i=(min|1); i<=INT_MAX;i+=2) - { - if(IsPrime(i) && ((i-1)%s_hash_prime!=0)) - return(i); - } - return(min); - } -//+------------------------------------------------------------------+ -//| Generate a new prime value greater than old_size. | -//+------------------------------------------------------------------+ -int CPrimeGenerator::ExpandPrime(const int old_size) - { - int new_size=2*old_size; - if((uint)new_size>INT_MAX && INT_MAX>old_size) - return INT_MAX; - else - return GetPrime(new_size); - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/LinkedList.mqh b/Include/Generic/LinkedList.mqh deleted file mode 100644 index 5183648..0000000 --- a/Include/Generic/LinkedList.mqh +++ /dev/null @@ -1,563 +0,0 @@ -//+------------------------------------------------------------------+ -//| LinkedList.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -//+------------------------------------------------------------------+ -//| Class CLinkedListNode. | -//| Usage: Represents a node of linked list. | -//+------------------------------------------------------------------+ -template -class CLinkedListNode - { -protected: - CLinkedList*m_list; - CLinkedListNode*m_next; - CLinkedListNode*m_prev; - T m_item; - -public: - CLinkedListNode(T value): m_item(value) { } - CLinkedListNode(CLinkedList*list,T value): m_list(list),m_item(value) { } - ~CLinkedListNode(void) { } - //--- methods of access to protected data - CLinkedList* List(void) { return(m_list); } - void List(CLinkedList*value) { m_list=value; } - CLinkedListNode*Next(void) { return(m_next); } - void Next(CLinkedListNode*value) { m_next=value; } - CLinkedListNode*Previous(void) { return(m_prev); } - void Previous(CLinkedListNode*value) { m_prev=value; } - T Value(void) { return(m_item); } - void Value(T value) { m_item=value; } - }; -//+------------------------------------------------------------------+ -//| Class CLinkedList. | -//| Usage: Represents a doubly linked list. | -//+------------------------------------------------------------------+ -template -class CLinkedList: public ICollection - { -protected: - CLinkedListNode*m_head; - int m_count; - -public: - CLinkedList(void); - CLinkedList(ICollection*collection); - CLinkedList(T &array[]); - ~CLinkedList(void); - //--- methods of filling data - bool Add(T value); - CLinkedListNode*AddAfter(CLinkedListNode*node,T value); - bool AddAfter(CLinkedListNode*node,CLinkedListNode*new_node); - CLinkedListNode*AddBefore(CLinkedListNode*node,T value); - bool AddBefore(CLinkedListNode*node,CLinkedListNode*new_node); - CLinkedListNode*AddFirst(T value); - bool AddFirst(CLinkedListNode*node); - CLinkedListNode*AddLast(T value); - bool AddLast(CLinkedListNode*node); - //--- methods of access to protected data - int Count(void); - CLinkedListNode*Head(void) {return(m_head);} - CLinkedListNode*First(void); - CLinkedListNode*Last(void); - bool Contains(T item); - //--- methods of copy data from collection - int CopyTo(T &dst_array[],const int dst_start=0); - //--- methods of cleaning and deleting - void Clear(void); - bool Remove(T item); - bool Remove(CLinkedListNode*node); - bool RemoveFirst(void); - bool RemoveLast(void); - //--- method for searching - CLinkedListNode*Find(T value); - CLinkedListNode*FindLast(T value); - -private: - bool ValidateNode(CLinkedListNode*node); - bool ValidateNewNode(CLinkedListNode*node); - void InternalInsertNodeBefore(CLinkedListNode*node,CLinkedListNode*new_node); - void InternalInsertNodeToEmptyList(CLinkedListNode*new_node); - void InternalRemoveNode(CLinkedListNode*node); - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CLinkedList class that is | -//| empty. | -//+------------------------------------------------------------------+ -template -CLinkedList::CLinkedList(void): m_count(0) - { - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CLinkedList class that | -//| contains elements copied from the specified array and has | -//| sufficient capacity to accommodate the number of elements copied.| -//+------------------------------------------------------------------+ -template -CLinkedList::CLinkedList(T &array[]): m_count(0) - { - for(int i=0; i class that | -//| contains elements copied from the specified collection and has | -//| sufficient capacity to accommodate the number of elements copied.| -//+------------------------------------------------------------------+ -template -CLinkedList::CLinkedList(ICollection*collection): m_count(0) - { -//--- check collection - if(CheckPointer(collection)!=POINTER_INVALID) - { - T array[]; - int size=collection.CopyTo(array,0); - for(int i=0; i -CLinkedList::~CLinkedList(void) - { - Clear(); - } -//+------------------------------------------------------------------+ -//| Adds an value to the end of the list. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::Add(T value) - { - return(CheckPointer(AddLast(value))!=POINTER_INVALID); - } -//+------------------------------------------------------------------+ -//| Adds a new node containing the specified value after the | -//| specified existing node in the CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::AddAfter(CLinkedListNode*node,T value) - { -//--- check node - if(!ValidateNode(node)) - return(NULL); -//--- create new node - CLinkedListNode*result=new CLinkedListNode(node.List(),value); -//--- insert node to the list - InternalInsertNodeBefore(node.Next(),result); - return(result); - } -//+------------------------------------------------------------------+ -//| Adds the specified new node after the specified existing node in | -//| the LinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::AddAfter(CLinkedListNode*node,CLinkedListNode*new_node) - { -//--- check node - if(!ValidateNode(node)) - return(false); -//--- check new node - if(!ValidateNewNode(new_node)) - return(false); -//--- insert node to the list - InternalInsertNodeBefore(node.Next(),new_node); -//--- set the current list as list for new node - new_node.List(GetPointer(this)); - return(true); - } -//+------------------------------------------------------------------+ -//| Adds a new node containing the specified value before the | -//| specified existing node in the CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::AddBefore(CLinkedListNode*node,T value) - { -//--- check node - if(!ValidateNode(node)) - return(NULL); -//--- create new node - CLinkedListNode*result=new CLinkedListNode(node.List(),value); -//--- insert node to the list - InternalInsertNodeBefore(node,result); - if(node==m_head) - m_head=result; - return(result); - } -//+------------------------------------------------------------------+ -//| Adds the specified new node before the specified existing node in| -//| the LinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::AddBefore(CLinkedListNode*node,CLinkedListNode*new_node) - { -//--- check node - if(!ValidateNode(node)) - return(false); -//--- check new node - if(!ValidateNewNode(new_node)) - return(false); -//--- insert node to the list - InternalInsertNodeBefore(node,new_node); -//--- set the current list as list for new node - new_node.List(GetPointer(this)); - if(node==m_head) - m_head=new_node; - return(true); - } -//+------------------------------------------------------------------+ -//| Adds a new node containing the specified value at the start of | -//| the CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::AddFirst(T value) - { -//--- create new node - CLinkedListNode*node=new CLinkedListNode(GetPointer(this),value); -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - { - //--- insert node to the empty list - InternalInsertNodeToEmptyList(node); - } - else - { - //--- insert node to the list - InternalInsertNodeBefore(m_head,node); - m_head=node; - } - return(node); - } -//+------------------------------------------------------------------+ -//| Adds the specified new node at the start of the CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::AddFirst(CLinkedListNode*node) - { -//--- check node - if(!ValidateNewNode(node)) - return(false); -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - { - //--- insert node to the empty list - InternalInsertNodeToEmptyList(node); - } - else - { - //--- insert node to the list - InternalInsertNodeBefore(m_head,node); - m_head=node; - } -//--- set the current list as list for node - node.List(GetPointer(this)); - return(true); - } -//+------------------------------------------------------------------+ -//| Adds a new node containing the specified value at the end of the | -//| CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::AddLast(T value) - { -//--- create new node - CLinkedListNode*node=new CLinkedListNode(GetPointer(this),value); -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - { - //--- insert node to the empty list - InternalInsertNodeToEmptyList(node); - } - else - { - //--- insert node to the list - InternalInsertNodeBefore(m_head,node); - } - return(node); - } -//+------------------------------------------------------------------+ -//| Adds the specified new node at the end of the CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::AddLast(CLinkedListNode*node) - { -//--- check node - if(!ValidateNewNode(node)) - return(false); -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - { - //--- insert node to the empty list - InternalInsertNodeToEmptyList(node); - } - else - { - //--- insert node to the list - InternalInsertNodeBefore(m_head,node); - } -//--- set the current list as list for node - node.List(GetPointer(this)); - return(true); - } -//+------------------------------------------------------------------+ -//| Determines whether an element is in the linked list. | -//+------------------------------------------------------------------+ -template -int CLinkedList::Count(void) - { - return(m_count); - } -//+------------------------------------------------------------------+ -//| Gets the first node of the CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::First(void) - { - return(m_head); - } -//+------------------------------------------------------------------+ -//| Gets the last node of the CLinkedList. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::Last(void) - { - return(CheckPointer(m_head)!=POINTER_INVALID ? m_head.Previous() : NULL); - } -//+------------------------------------------------------------------+ -//| Determines whether a value is in the CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::Contains(T item) - { - return(CheckPointer(Find(item))!=POINTER_INVALID); - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the linkedlist to a compatible | -//| one-dimensional array. | -//+------------------------------------------------------------------+ -template -int CLinkedList::CopyTo(T &dst_array[],const int dst_start=0) - { -//--- resize array - if(dst_start+m_count>ArraySize(dst_array)) - ArrayResize(dst_array,dst_start+m_count); -//--- check start index - if(dst_start>ArraySize(dst_array)) - return(0); -//--- start copy - CLinkedListNode*node=m_head; - if(CheckPointer(node)!=POINTER_INVALID) - { - int dst_index=dst_start; - do - { - dst_array[dst_index++]=node.Value(); - node=node.Next(); - } - while(dst_index. | -//+------------------------------------------------------------------+ -template -void CLinkedList::Clear(void) - { -//--- check count - if(m_count>0) - { - //--- check head node - if(CheckPointer(m_head)!=POINTER_INVALID) - { - while(m_head.Next()!=m_head) - { - CLinkedListNode*node=m_head.Next(); - m_head.Next(node.Next()); - delete node; - } - delete m_head; - } - //--- reset count - m_count=0; - } - } -//+------------------------------------------------------------------+ -//| Removes the first occurrence of the specified value from the | -//| CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::Remove(T item) - { -//--- find node with specified value - CLinkedListNode*node=Find(item); - if(CheckPointer(node)!=POINTER_INVALID) - { - //--- remove node - InternalRemoveNode(node); - return(true); - } - return(false); - } -//+------------------------------------------------------------------+ -//| Removes the specified node from the LinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::Remove(CLinkedListNode*node) - { -//--- check node - if(ValidateNode(node)) - { - //--- remove node - InternalRemoveNode(node); - return(true); - } - return(false); - } -//+------------------------------------------------------------------+ -//| Removes the node at the start of the CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::RemoveFirst(void) - { -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - return(false); -//--- remove head node - InternalRemoveNode(m_head); - return(true); - } -//+------------------------------------------------------------------+ -//| Removes the node at the end of the CLinkedList. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::RemoveLast(void) - { -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - return(false); -//--- remove last node - InternalRemoveNode(m_head.Previous()); - return(true); - } -//+------------------------------------------------------------------+ -//| Finds the first node that contains the specified value. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::Find(T value) - { - CLinkedListNode*node=m_head; -//--- start search specified value in the list - if(CheckPointer(node)!=POINTER_INVALID) - { - do - { - //--- use default equals function - if(::Equals(node.Value(),value)) - return(node); - node=node.Next(); - } - while(node!=m_head); - } - return(NULL); - } -//+------------------------------------------------------------------+ -//| Finds the last node that contains the specified value. | -//+------------------------------------------------------------------+ -template -CLinkedListNode*CLinkedList::FindLast(T value) - { -//--- check head node - if(CheckPointer(m_head)==POINTER_INVALID) - return(NULL); -//--- get last node - CLinkedListNode *last = m_head.Previous(); - CLinkedListNode *node = last; -//--- start search from the end of the list - if(node!=NULL) - { - do - { - //--- use default equals function - if(::Equals(node.Value(),value)) - return(node); - node=node.Previous(); - } - while(node!=last); - } - return(NULL); - } -//+------------------------------------------------------------------+ -//| Validation of node on not null and belongs in the current list. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::ValidateNode(CLinkedListNode*node) - { - return(CheckPointer(node)!=POINTER_INVALID && node.List()==GetPointer(this)); - } -//+------------------------------------------------------------------+ -//| Validation of new node on not null. | -//+------------------------------------------------------------------+ -template -bool CLinkedList::ValidateNewNode(CLinkedListNode*node) - { - return(CheckPointer(node)!=POINTER_INVALID && node.List()==NULL); - } -//+------------------------------------------------------------------+ -//| Insert node before the specified node. | -//+------------------------------------------------------------------+ -template -void CLinkedList::InternalInsertNodeBefore(CLinkedListNode*node,CLinkedListNode*new_node) - { -//--- set node befor the specified node - new_node.Next(node); - new_node.Previous(node.Previous()); - node.Previous().Next(new_node); - node.Previous(new_node); -//--- increment count - m_count++; - } -//+------------------------------------------------------------------+ -//| Add first node to the list. | -//+------------------------------------------------------------------+ -template -void CLinkedList::InternalInsertNodeToEmptyList(CLinkedListNode*new_node) - { -//--- set node as head of the list - new_node.Next(new_node); - new_node.Previous(new_node); - m_head=new_node; -//--- increment count - m_count++; - } -//+------------------------------------------------------------------+ -//| Remove specified node from the list. | -//+------------------------------------------------------------------+ -template -void CLinkedList::InternalRemoveNode(CLinkedListNode*node) - { -//--- check node - if(node.Next()==node) - { - //--- resets the head of the list - m_head=NULL; - } - else - { - //--- detach node from the list - node.Next().Previous(node.Previous()); - node.Previous().Next(node.Next()); - if(m_head==node) - m_head=node.Next(); - } -//--- decrement count and delete node - m_count--; - delete node; - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Queue.mqh b/Include/Generic/Queue.mqh deleted file mode 100644 index 5b95f45388592cba66bf1d8c86a628bcdcd41399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23370 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 L!te(+Q=k4n#Pe)) diff --git a/Include/Generic/SortedMap.mqh b/Include/Generic/SortedMap.mqh deleted file mode 100644 index 170a530..0000000 --- a/Include/Generic/SortedMap.mqh +++ /dev/null @@ -1,341 +0,0 @@ -//+------------------------------------------------------------------+ -//| SortedMap.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include -#include -#include "HashMap.mqh" -#include "SortedSet.mqh" -//+------------------------------------------------------------------+ -//| Class CSortedMap. | -//| Usage: Represents a collection of key/value pairs that are sorted| -//| on the key. | -//+------------------------------------------------------------------+ -template -class CSortedMap: public IMap - { -protected: - CRedBlackTree*>*m_tree; - IComparer*m_comparer; - bool m_delete_comparer; - -public: - CSortedMap(void); - CSortedMap(IComparer*comparer); - CSortedMap(IMap*map); - CSortedMap(IMap*map,IComparer*comparer); - ~CSortedMap(void); - //--- methods of filling data - bool Add(CKeyValuePair*value) { return m_tree.Add(value); } - bool Add(TKey key,TValue value); - //--- methods of access to protected data - int Count(void) { return m_tree.Count(); } - bool Contains(CKeyValuePair*item) { return m_tree.Contains(item); } - bool Contains(TKey key,TValue value); - bool ContainsKey(TKey key); - bool ContainsValue(TValue value); - IComparer *Comparer(void) const { return(m_comparer); } - //--- methods of copy data from collection - int CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0); - int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0); - //--- methods of cleaning and deleting - void Clear(void); - bool Remove(CKeyValuePair*item) { return m_tree.Remove(item); } - bool Remove(TKey key); - //--- method of access to the data - bool TryGetValue(TKey key,TValue &value); - bool TrySetValue(TKey key,TValue value); - -private: - static void ClearNodes(CRedBlackTreeNode*>*node); - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedMap class | -//| that is empty, has the default initial capacity, and uses the | -//| default comparer for the key type. | -//+------------------------------------------------------------------+ -template -CSortedMap::CSortedMap(void) - { -//--- use default comaprer - m_comparer=new CDefaultComparer(); - m_delete_comparer=true; - m_tree=new CRedBlackTree*>(new CKeyValuePairComparer(m_comparer)); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedMap class | -//| that is empty, has the default initial capacity, and uses the | -//| specified IComparer. | -//+------------------------------------------------------------------+ -template -CSortedMap::CSortedMap(IComparer*comparer) - { -//--- check comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default comaprer - m_comparer=new CDefaultComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified comaprer - m_comparer=comparer; - m_delete_comparer=false; - } - m_tree=new CRedBlackTree*>(new CKeyValuePairComparer(m_comparer)); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedMap class | -//| that contains elements copied from the specified | -//| IMap and uses the default comparer for the key type.| -//+------------------------------------------------------------------+ -template -CSortedMap::CSortedMap(IMap*map) - { -//--- use default comaprer - m_comparer=new CDefaultComparer(); - m_delete_comparer=true; - m_tree=new CRedBlackTree*>(map,new CKeyValuePairComparer(m_comparer)); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedMap class | -//| that contains elements copied from the specified | -//| IMap and uses the specified IComparer. | -//+------------------------------------------------------------------+ -template -CSortedMap::CSortedMap(IMap*map,IComparer*comparer) - { -//--- check comaprer - if(CheckPointer(comparer)==POINTER_INVALID) - { - //--- use default comaprer - m_comparer=new CDefaultComparer(); - m_delete_comparer=true; - } - else - { - //--- use specified comaprer - m_comparer=comparer; - m_delete_comparer=false; - } - m_tree=new CRedBlackTree*>(map,new CKeyValuePairComparer(m_comparer)); - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -template -CSortedMap::~CSortedMap(void) - { -//--- delete comparer - if(m_delete_comparer) - delete m_comparer; -//--- delete tree comparer - delete m_tree.Comparer(); -//--- delete nodes values - ClearNodes(m_tree.Root()); -//--- delete tree and nodes - delete m_tree; - } -//+------------------------------------------------------------------+ -//| Walk all nodes of tree and delete their value. | -//+------------------------------------------------------------------+ -template -static void CSortedMap::ClearNodes(CRedBlackTreeNode*>*node) - { -//--- check node - if(CheckPointer(node)==POINTER_INVALID) - return; -//--- walk of a right subtree - if(!node.Right().IsLeaf()) - ClearNodes(node.Right()); -//--- delete value - delete node.Value(); -//--- walk of a left subtree - if(!node.Left().IsLeaf()) - ClearNodes(node.Left()); - } -//+------------------------------------------------------------------+ -//| Adds the specified key and value to the map. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::Add(TKey key,TValue value) - { -//--- create pair - CKeyValuePair*pair=new CKeyValuePair(key,value); -//--- add pair to tree - bool success=m_tree.Add(pair); -//--- if addition was not successful delte pair - if(!success) - delete pair; - return(success); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified key with value.| -//+------------------------------------------------------------------+ -template -bool CSortedMap::Contains(TKey key,TValue value) - { -//--- find node with specified key - CKeyValuePairpair(key,NULL); - CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); -//--- create value comparer - CDefaultEqualityComparercomaprer; -//--- determine whether the finding node contains specified value - if(CheckPointer(node)!=POINTER_INVALID && comaprer.Equals(value,node.Value().Value())) - return(true); - return(false); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified key. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::ContainsKey(TKey key) - { -//--- crete pair - CKeyValuePairpair(key,NULL); -//--- determines whether the tree contains the pair. - return m_tree.Contains(GetPointer(pair)); - } -//+------------------------------------------------------------------+ -//| Determines whether the map contains the specified value. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::ContainsValue(TValue value) - { -//--- copy all pairs in array - CKeyValuePair*array[]; - int count=m_tree.CopyTo(array); -//--- create value comparer - CDefaultEqualityComparercomaprer; -//--- determines whether the array contains the specified value - for(int i=0; i -int CSortedMap::CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0) - { - int result=m_tree.CopyTo(dst_array,dst_start); - if(result>0) - { - //--- create clones for each pair - for(int i=0; i -int CSortedMap::CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0) - { -//--- create array and copy all values from tree to there - CKeyValuePair*array[]; - int count=m_tree.CopyTo(array); -//--- check real cout - if(count>0) - { - //--- resize keys array - if(dst_start+count>ArraySize(dst_keys)) - ArrayResize(dst_keys,dst_start+count); - //--- resize values array - if(dst_start+count>ArraySize(dst_values)) - ArrayResize(dst_values,MathMin(ArraySize(dst_keys),dst_start+count)); - //--- start copy - int index=0; - while(index -void CSortedMap::Clear(void) - { -//--- check count - if(m_tree.Count()>0) - { - //--- delete nodes values - ClearNodes(m_tree.Root()); - //--- claer th tree - m_tree.Clear(); - } - } -//+------------------------------------------------------------------+ -//| Removes the value with the specified key from the map. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::Remove(TKey key) - { -//--- create pair with specified key - CKeyValuePairpair(key,NULL); -//--- find node - CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); -//--- check node - if(CheckPointer(node)!=POINTER_INVALID) - { - CKeyValuePair*real_pair=node.Value(); - //--- remove node from tree - if(m_tree.Remove(node)) - { - //--- check and delete node value - if(CheckPointer(real_pair)==POINTER_DYNAMIC) - delete real_pair; - return(true); - } - } - return(false); - } -//+------------------------------------------------------------------+ -//| Gets the value associated with the specified key. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::TryGetValue(TKey key,TValue &value) - { -//--- create pair with specified key - CKeyValuePairpair(key,NULL); -//--- find node with specified pair in the tree - CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); -//--- check node - if(CheckPointer(node)==POINTER_INVALID) - return(false); -//--- get value - value=node.Value().Value(); - return(true); - } -//+------------------------------------------------------------------+ -//| Sets the value associated with the specified key. | -//+------------------------------------------------------------------+ -template -bool CSortedMap::TrySetValue(TKey key,TValue value) - { -//--- create pair with specified key - CKeyValuePairpair(key,NULL); -//--- find node with specified pair in the tree - CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); -//--- check node - if(CheckPointer(node)==POINTER_INVALID) - return(false); -//--- set value - node.Value().Value(value); - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/SortedSet.mqh b/Include/Generic/SortedSet.mqh deleted file mode 100644 index 9df8d27..0000000 --- a/Include/Generic/SortedSet.mqh +++ /dev/null @@ -1,673 +0,0 @@ -//+------------------------------------------------------------------+ -//| SortedList.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include "RedBlackTree.mqh" -#include "HashSet.mqh" -//+------------------------------------------------------------------+ -//| Class CSortedSet. | -//| Usage: Represents a collection of objects that is maintained in | -//| sorted order. | -//+------------------------------------------------------------------+ -template -class CSortedSet: public ISet - { -protected: - CRedBlackTree*m_tree; - -public: - CSortedSet(void); - CSortedSet(IComparer*comparer); - CSortedSet(ICollection*collection); - CSortedSet(ICollection*collection,IComparer*comparer); - CSortedSet(T &array[]); - CSortedSet(T &array[],IComparer*comparer); - ~CSortedSet(void); - //--- methods of filling data - bool Add(T value) { return(m_tree.Add(value)); } - //--- methods of access to protected data - int Count(void) { return(m_tree.Count()); } - bool Contains(T item) { return(m_tree.Contains(item)); } - IComparer *Comparer(void) const { return(m_tree.Comparer()); } - bool TryGetMin(T &min) { return(m_tree.TryGetMin(min)); } - bool TryGetMax(T &max) { return(m_tree.TryGetMax(max)); } - //--- methods of copy data from collection - int CopyTo(T &dst_array[],const int dst_start=0); - //--- methods of cleaning and deleting - void Clear(void) { m_tree.Clear(); } - bool Remove(T item) { return(m_tree.Remove(item)); } - //--- methods of changing sets - void ExceptWith(ICollection*collection); - void ExceptWith(T &array[]); - void IntersectWith(ICollection*collection); - void IntersectWith(T &array[]); - void SymmetricExceptWith(ICollection*collection); - void SymmetricExceptWith(T &array[]); - void UnionWith(ICollection*collection); - void UnionWith(T &array[]); - //--- methods for determining the relationship between sets - bool IsProperSubsetOf(ICollection*collection); - bool IsProperSubsetOf(T &array[]); - bool IsProperSupersetOf(ICollection*collection); - bool IsProperSupersetOf(T &array[]); - bool IsSubsetOf(ICollection*collection); - bool IsSubsetOf(T &array[]); - bool IsSupersetOf(ICollection*collection); - bool IsSupersetOf(T &array[]); - bool Overlaps(ICollection*collection); - bool Overlaps(T &array[]); - bool SetEquals(ICollection*collection); - bool SetEquals(T &array[]); - //--- methods for working with an ordered set - bool GetViewBetween(T &array[],T lower_value,T upper_value); - bool GetReverse(T &array[]); - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that is | -//| empty and uses the default equality comparer for the set type. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(void) - { - m_tree=new CRedBlackTree(); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that is | -//| empty and uses the specified equality comparer for the set type. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(IComparer*comparer) - { - m_tree=new CRedBlackTree(comparer); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that uses | -//| the default equality comparer for the set type, contains elements| -//| copied from the specified collection, and has sufficient capacity| -//| to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(ICollection*collection) - { - m_tree=new CRedBlackTree(collection); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that uses | -//| the specified equality comparer for the set type, contains | -//| elements copied from the specified collection, and has sufficient| -//| capacity to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(ICollection*collection,IComparer*comparer) - { - m_tree=new CRedBlackTree(collection,comparer); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that uses | -//| the default equality comparer for the set type, contains | -//| elements copied from the specified array, and has sufficient | -//| capacity to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(T &array[]) - { - m_tree=new CRedBlackTree(array); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CSortedSet class that uses | -//| the specified equality comparer for the set type, contains | -//| elements copied from the specified array, and has sufficient | -//| capacity to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CSortedSet::CSortedSet(T &array[],IComparer*comparer) - { - m_tree=new CRedBlackTree(array,comparer); - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -template -CSortedSet::~CSortedSet(void) - { - delete m_tree; - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the set to a compatible | -//| one-dimensional array. | -//+------------------------------------------------------------------+ -template -int CSortedSet::CopyTo(T &dst_array[],const int dst_start=0) - { - return(m_tree.CopyTo(dst_array, dst_start)); - } -//+------------------------------------------------------------------+ -//| Removes all elements in the specified collection from the current| -//| set. | -//+------------------------------------------------------------------+ -template -void CSortedSet::ExceptWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- check tree count - if(m_tree.Count()==0) - return; -//--- special case if collection is this -//--- a set minus itself is the empty set - if(collection==GetPointer(this)) - { - Clear(); - return; - } -//--- copy collection to array - T array[]; - int size=collection.CopyTo(array); -//--- find max and min value - T max; - T min; -//--- get comaprer - IComparer*comparer=Comparer(); - if(!m_tree.TryGetMax(max)) - return; - if(!m_tree.TryGetMin(min)) - return; -//--- remove elements - for(int i=0; i0) && Contains(item)) - m_tree.Remove(item); - } - } -//+------------------------------------------------------------------+ -//| Removes all elements in the specified array from the current set.| -//+------------------------------------------------------------------+ -template -void CSortedSet::ExceptWith(T &array[]) - { -//--- check tree count - if(m_tree.Count()==0) - return; -//--- get array size - int size=ArraySize(array); -//--- find max and min value - T max; - T min; -//--- get comparer - IComparer*comparer=Comparer(); - if(!m_tree.TryGetMax(max)) - return; - if(!m_tree.TryGetMin(min)) - return; -//--- remove elements - for(int i=0; i0) && Contains(item)) - m_tree.Remove(item); - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present in that object and in the specified collection. | -//+------------------------------------------------------------------+ -template -void CSortedSet::IntersectWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- check tree count - if(m_tree.Count()==0) - return; -//--- special case if collection is this -//--- a set minus itself is the empty set - if(collection==GetPointer(this)) - return; -//--- copy collection to array - T array[]; - int size=collection.CopyTo(array); -//--- create emty tree - CRedBlackTree*tree=new CRedBlackTree(); -//--- store values conatin in tree and array - for(int i=0; i -void CSortedSet::IntersectWith(T &array[]) - { -//--- check tree count - if(m_tree.Count()==0) - return; -//--- get array size - int size=ArraySize(array); -//--- create emty tree - CRedBlackTree*tree=new CRedBlackTree(); -//--- store values conatin in tree and array - for(int i=0; i -void CSortedSet::SymmetricExceptWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- check collection count - if(collection.Count()==0) - return; -//--- check tree count - if(m_tree.Count()==0) - { - UnionWith(collection); - return; - } -//--- special case if collection is this -//--- a set minus itself is the empty set - if(collection==GetPointer(this)) - { - Clear(); - return; - } -//--- copy colleaction to array - T array[]; - int size=collection.CopyTo(array); -//--- get comparer - IComparer*comparer=m_tree.Comparer(); -//--- sort array - Introsortsort; - ArrayCopy(sort.keys,array); - sort.comparer=comparer; - sort.Sort(0, size); - ArrayCopy(array,sort.keys); -//--- modify tree - T last=array[0]; - for(int i=0; i=size) - break; - - if(m_tree.Contains(array[i])) - m_tree.Remove(array[i]); - else - m_tree.Add(array[i]); - - last=array[i]; - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain only elements that are | -//| present either in that set or in the specified array, but not | -//| both. | -//+------------------------------------------------------------------+ -template -void CSortedSet::SymmetricExceptWith(T &array[]) - { -//--- check array size - if(ArraySize(array)==0) - return; -//--- check tree count - if(m_tree.Count()==0) - { - UnionWith(array); - return; - } -//--- get size - int size=ArraySize(array); -//--- get comparer - IComparer*comparer=m_tree.Comparer(); -//--- sort array - Introsortsort; - ArrayCopy(sort.keys,array); - sort.comparer=comparer; - sort.Sort(0, size); - ArrayReverse(sort.keys,0,ArraySize(sort.keys)); -//--- modify tree - T last=sort.keys[0]; - for(int i=0; i=size) - break; - - if(m_tree.Contains(sort.keys[i])) - m_tree.Remove(sort.keys[i]); - else - m_tree.Add(sort.keys[i]); - - last=sort.keys[i]; - } - } -//+------------------------------------------------------------------+ -//| Modifies the current set to contain all elements that are present| -//| in itself, the specified collection, or both. | -//+------------------------------------------------------------------+ -template -void CSortedSet::UnionWith(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return; -//--- copy all elements from collecton to array - T array[]; - int size=collection.CopyTo(array); -//--- add all elemets from array to set - for(int i=0; i -void CSortedSet::UnionWith(T &array[]) - { -//--- get array size - int size=ArraySize(array); -//--- add all elemets from array to set - for(int i=0; i -bool CSortedSet::IsProperSubsetOf(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- check tree count - if(m_tree.Count()==0) - return(collection.Count() > 0); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return(ptr_set.IsProperSupersetOf(m_tree)); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return(set.IsProperSupersetOf(m_tree)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper subset of the specified | -//| array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsProperSubsetOf(T &array[]) - { - if(m_tree.Count()==0) - return(ArraySize(array) > 0); -//--- create a set based on a specified array - CHashSetset(array); - if(m_tree.Count()>=set.Count()) - return(false); - return(set.IsProperSupersetOf(m_tree)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper superset of the specified | -//| collection. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsProperSupersetOf(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(m_tree.Count()>0); -//--- check tree count - if(m_tree.Count()==0) - return(false); -//--- check collection count - if(collection.Count()==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return(ptr_set.IsProperSubsetOf(m_tree)); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return(set.IsProperSubsetOf(m_tree)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a proper superset of the specified | -//| array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsProperSupersetOf(T &array[]) - { - if(m_tree.Count()==0) - return(false); - if(ArraySize(array)==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - return(set.IsProperSubsetOf(m_tree)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a subset of the specified collection.| -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsSubsetOf(ICollection*collection) - { -//--- cehck collection - if(CheckPointer(collection)==POINTER_INVALID) - return(m_tree.Count()==0); -//--- check tree count - if(m_tree.Count()==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)==POINTER_DYNAMIC) - { - return(ptr_set.IsProperSupersetOf(m_tree)); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return(set.IsProperSupersetOf(m_tree)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a subset of the specified array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsSubsetOf(T &array[]) - { -//--- check tree count - if(m_tree.Count()==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - if(m_tree.Count()>set.Count()) - return(false); - return(set.IsProperSupersetOf(m_tree)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a superset of the specified | -//| collection. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsSupersetOf(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(m_tree.Count()>=0); -//--- check collection count - if(collection.Count()==0) - return(true); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return(ptr_set.IsSupersetOf(m_tree)); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return(set.IsSupersetOf(m_tree)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether a set is a superset of the specified array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::IsSupersetOf(T &array[]) - { -//--- check array size - if(ArraySize(array)==0) - return(true); -//--- create a set based on a specified array - CHashSetset(array); - return(set.IsSupersetOf(m_tree)); - } -//+------------------------------------------------------------------+ -//| Determines whether the current set and a specified collection | -//| share common elements. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::Overlaps(ICollection*collection) - { -//--- check collection - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- check tree count - if(m_tree.Count()==0) - return(false); -//--- check collection count - if(collection.Count()==0) - return(false); -//--- check collection is set - CHashSet*ptr_set=dynamic_cast*>(collection); - if(CheckPointer(ptr_set)!=POINTER_INVALID) - { - return(ptr_set.Overlaps(m_tree)); - } - else - { - //--- create a set based on a specified collection - CHashSetset(collection); - return(set.Overlaps(m_tree)); - } - } -//+------------------------------------------------------------------+ -//| Determines whether the current set and a specified array share | -//| common elements. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::Overlaps(T &array[]) - { -//--- check tree count - if(m_tree.Count()==0) - return(false); -//--- check array size - if(ArraySize(array)==0) - return(false); -//--- convert array to set - CHashSetset(array); - return(set.Overlaps(m_tree)); - } -//+------------------------------------------------------------------+ -//| Determines whether a set and the specified collection contain the| -//| same elements. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::SetEquals(ICollection*collection) - { - if(CheckPointer(collection)==POINTER_INVALID) - return(false); -//--- get array from collection - T array[]; - collection.CopyTo(array); -//--- check current set is equal specified array - return SetEquals(array); - } -//+------------------------------------------------------------------+ -//| Determines whether a set and the specified array contain the same| -//| elements. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::SetEquals(T &array[]) - { -//--- try find all elements in the tree - for(int i=0; i to array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::GetViewBetween(T &array[],T lower_value,T upper_value) - { -//--- get comparer - IComparer*comparer=m_tree.Comparer(); - if(comparer.Compare(lower_value,upper_value)>0) - return(false); -//--- copy all element from tree to array - T buff[]; - int size=m_tree.CopyTo(buff); -//--- check range - if(size==0 || comparer.Compare(buff[0],upper_value)>0 || comparer.Compare(buff[size-1],lower_value)<0) - return(false); -//--- find first element greater than lower_value - int index_lower=0; - while(index_lower0 && comparer.Compare(buff[index_upper],upper_value)>0) - index_upper--; -//--- check indices - if(index_lower>index_upper) - return(false); -//--- copy view between lower_value and upper_value to array - return(ArrayCopy(array,buff,0,index_lower,index_upper-index_lower+1)>=0); - } -//+------------------------------------------------------------------+ -//| Copy the CSortedSet in reverse order to array. | -//+------------------------------------------------------------------+ -template -bool CSortedSet::GetReverse(T &array[]) - { - int size=m_tree.CopyTo(array); - return ArrayReverse(array,0,size); - } -//+------------------------------------------------------------------+ diff --git a/Include/Generic/Stack.mqh b/Include/Generic/Stack.mqh deleted file mode 100644 index 1d3d54a..0000000 --- a/Include/Generic/Stack.mqh +++ /dev/null @@ -1,227 +0,0 @@ -//+------------------------------------------------------------------+ -//| Stack.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include -//+------------------------------------------------------------------+ -//| Class CStack. | -//| Usage: Represents a variable size last-in-first-out (LIFO) | -//| collection of instances of the same specified type. | -//+------------------------------------------------------------------+ -template -class CStack: public ICollection - { -protected: - T m_array[]; - int m_size; - const int m_default_capacity; - -public: - CStack(void); - CStack(const int capacity); - CStack(ICollection&collection[]); - CStack(T &array[]); - ~CStack(void); - //--- methods of filling data - bool Add(T value); - bool Push(T value); - //--- methods of access to protected data - int Count(void); - bool Contains(T item); - void TrimExcess(void); - //--- methods of copy data from collection - int CopyTo(T &dst_array[],const int dst_start=0); - //--- methods of cleaning and removing - void Clear(void); - bool Remove(T item); - //--- methods of access to protected data - T Peek(void); - T Pop(void); - }; -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CStack class that is empty | -//| and has the default initial capacity. | -//+------------------------------------------------------------------+ -template -CStack::CStack(void): m_default_capacity(4), - m_size(0) - { - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CStack class that is empty | -//| and has the specified initial capacity or the default initial | -//| capacity, whichever is greater. | -//+------------------------------------------------------------------+ -template -CStack::CStack(const int capacity): m_default_capacity(4), - m_size(0) - { - ArrayResize(m_array,capacity); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CStack class that contains | -//| elements copied from the specified array and has sufficient | -//| capacity to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CStack::CStack(T &array[]): m_default_capacity(4), - m_size(0) - { - m_size=ArrayCopy(m_array,array); - } -//+------------------------------------------------------------------+ -//| Initializes a new instance of the CStack class that contains | -//| elements copied from the specified collection and has sufficient | -//| capacity to accommodate the number of elements copied. | -//+------------------------------------------------------------------+ -template -CStack::CStack(ICollection*collection): m_default_capacity(4), - m_size(0) - { -//--- check collection - if(CheckPointer(collection)!=POINTER_INVALID) - m_size=collection.CopyTo(m_array,0); - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -template -CStack::~CStack(void) - { - } -//+------------------------------------------------------------------+ -//| Inserts an value at the top of the CStack. | -//+------------------------------------------------------------------+ -template -bool CStack::Add(T value) - { - return Push(value); - } -//+------------------------------------------------------------------+ -//| Gets the number of elements. | -//+------------------------------------------------------------------+ -template -int CStack::Count(void) - { - return(m_size); - } -//+------------------------------------------------------------------+ -//| Removes all values from the CStack. | -//+------------------------------------------------------------------+ -template -bool CStack::Contains(T item) - { - int count=m_size; -//--- try to find item in array - while(count-->0) - { - //--- use default equality function - if(::Equals(m_array[count],item)) - return(true); - } - return(false); - } -//+------------------------------------------------------------------+ -//| Copies a range of elements from the stack to a compatible | -//| one-dimensional array. | -//+------------------------------------------------------------------+ -template -int CStack::CopyTo(T &dst_array[],const int dst_start=0) - { -//--- resize array - if(dst_start+m_size>ArraySize(dst_array)) - ArrayResize(dst_array,dst_start+m_size); -//--- start copy - int src_index = m_size-1; - int dst_index = dst_start; - while(src_index>=0 && dst_index. | -//+------------------------------------------------------------------+ -template -void CStack::Clear(void) - { -//--- check current size - if(m_size>0) - { - ZeroMemory(m_array); - m_size=0; - } - } -//+------------------------------------------------------------------+ -//| Removes the first occurrence of a specific value from the stack. | -//+------------------------------------------------------------------+ -template -bool CStack::Remove(T item) - { -//--- find index of item - int index=ArrayIndexOf(m_array,item,0,m_size); -//--- check index - if(index==-1) - return(false); -//--- shift the values to the left - ArrayCopy(m_array,m_array,index,index+1); -//--- decrement size - m_size--; - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts an values at the top of the CStack. | -//+------------------------------------------------------------------+ -template -bool CStack::Push(T value) - { - int size=ArraySize(m_array); -//--- check array size - if(m_size==size) - { - //--- increase capacity - if(size==0) - ArrayResize(m_array,m_default_capacity); - else - ArrayResize(m_array,2*size); - } -//--- add value to the end - m_array[m_size++]=value; - return(true); - } -//+------------------------------------------------------------------+ -//| Returns the value at the top of the CStack without removing. | -//+------------------------------------------------------------------+ -template -T CStack::Peek(void) - { -//--- return last value - return(m_array[m_size-1]); - } -//+------------------------------------------------------------------+ -//| Removes and returns the value at the top of the CStack. | -//+------------------------------------------------------------------+ -template -T CStack::Pop(void) - { -//--- return last value and decrement size - T item=m_array[--m_size]; - return(item); - } -//+------------------------------------------------------------------+ -//| Sets the capacity to the actual number of elements in the | -//| CStack, if that number is less than 90 percent of current | -//| capacity. | -//+------------------------------------------------------------------+ -template -void CStack::TrimExcess(void) - { -//--- calculate threshold value - int threshold=(int)(((double)ArraySize(m_array)*0.9)); -//--- calculate resize array - if(m_sizem_max) - m_max=m_min; - if(!m_auto_scale) - { - if(m_max<=m_min) - ExtensionBoundaries(); - m_step=((m_max-m_min)>m_default_step && m_default_step>0) ? m_default_step : m_max-m_min; - return; - } - ExtensionBoundaries(); -//--- test for trivial condition of range = 0 and pick a suitable default - if(m_max-m_min<1.0e-30) - { - m_max=m_max+0.2 *(m_max==0 ? 1.0 : MathAbs(m_max)); - m_min=m_min-0.2 *(m_min==0 ? 1.0 : MathAbs(m_min)); - } -//--- this is the zero-lever test. If m_min is within the zero lever fraction of the data range,then use zero. - if(m_min>0 && m_min/(m_max-m_min)0) - m_step=CalcBoundedStepSize(m_max-m_min,m_max_labels); - else - m_step=CalcBoundedStepSize(m_max-m_min,labels); -//--- calculate the scale minimum - m_min=m_min-Mod(m_min,m_step); -//--- calculate the scale maximum - m_max=Mod(m_max,m_step)==0.0 ? m_max : m_max+m_step-Mod(m_max,m_step); - } -//+------------------------------------------------------------------+ -//| Expands the boundaries to the left and right. | -//+------------------------------------------------------------------+ -void CAxis::ExtensionBoundaries(void) - { - double range=m_max-m_min; -//--- do not let the grace value extend the axis below zero when all the values were positive - if(m_min<0 || m_min-m_min_grace*range>=0.0) - m_min=m_min-m_min_grace*range; -//--- do not let the grace value extend the axis above zero when all the values were negative - if(m_max>0 || m_max+m_max_grace*range<=0.0) - m_max=m_max+m_max_grace*range; -//--- calculate new min and max values if they equal - if(m_max==m_min) - { - if(MathAbs(m_max)>1e-100) - { - m_max *= (m_min < 0 ? 0.95 : 1.05 ); - m_min *= (m_min < 0 ? 1.05 : 0.95 ); - } - else - { - m_max = 1.0; - m_min = -1.0; - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Calculate a m_step size based on a data range. | -//+------------------------------------------------------------------+ -double CAxis::CalcStepSize(const double range,const double steps) - { -//--- calculate an initial guess at m_step size - double temp=range/steps; -//--- get the magnitude of the m_step size - double mag=MathFloor(MathLog10(temp)); - double magPow=MathPow(10.0,mag); -//--- calculate most significant digit of the new m_step size - double magMsd=NormalizeDouble(temp/magPow+.5,0); -//--- promote the MSD to either 1, 2, or 5 - if(magMsd>5.0) - magMsd=10.0; - else - if(magMsd>2.0) - magMsd=5.0; - else - if(magMsd>1.0) - magMsd=2.0; -//--- return step - return(magMsd * magPow); - } -//+------------------------------------------------------------------+ -//| Calculate the modulus (remainder) in a safe manner so that divide| -//| by zero errors are avoided | -//+------------------------------------------------------------------+ -double CAxis::Mod(const double x,const double y) - { -//--- check - if(y==0) - return(0); -//--- calculate modulus - return (x>0)? MathMod(x,y): MathMod(x,y)+y; - } -//+------------------------------------------------------------------+ -//| Calculate a m_step size based on a data range, limited to a max | -//| number of steps. | -//+------------------------------------------------------------------+ -double CAxis::CalcBoundedStepSize(const double range,const double max_steps) - { -//--- calculate an initial guess at m_step size - double temp=range/max_steps; -//--- get the magnitude of the m_step size - double mag=MathFloor(MathLog10(temp)); - double magPow=MathPow((double) 10.0,mag); -//--- calculate most significant digit of the new m_step size - double magMsd=MathCeil(temp/magPow); -//--- promote the MSD to either 1, 2, or 5 - if(magMsd>5.0) - magMsd=10.0; - else - if(magMsd>2.0) - magMsd=5.0; - else - if(magMsd>1.0) - magMsd=2.0; -//--- return step - return(magMsd * magPow); - } -//+------------------------------------------------------------------+ diff --git a/Include/Graphics/ColorGenerator.mqh b/Include/Graphics/ColorGenerator.mqh deleted file mode 100644 index e4b7376..0000000 --- a/Include/Graphics/ColorGenerator.mqh +++ /dev/null @@ -1,74 +0,0 @@ -//+------------------------------------------------------------------+ -//| ColorGenerator.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Class CColorGenerator | -//| Usage: class to generate the default colors | -//+------------------------------------------------------------------+ -class CColorGenerator - { -private: - int m_index; - bool m_generate; - uint m_current_palette[20]; - const static uint s_default_palette[20]; - -public: - CColorGenerator(void); - ~CColorGenerator(void); - //--- gets the next color - uint Next(void); - //--- reset generator - void Reset(void); - }; -const uint CColorGenerator::s_default_palette[20]= - { - 0x3366CC,0xDC3912,0xFF9900,0x109618,0x990099, - 0x3B3EAC,0x0099C6,0xDD4477,0x66AA00,0xB82E2E, - 0x316395,0x994499,0x22AA99,0xAAAA11,0x6633CC, - 0xE67300,0x8B0707,0x329262,0x5574A6,0x3B3EAC - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CColorGenerator::CColorGenerator(void): m_index(0), - m_generate(false) - { - ArrayCopy(m_current_palette,s_default_palette); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CColorGenerator::~CColorGenerator(void) - { - } -//+------------------------------------------------------------------+ -//| Gets or generates the following color from the palette | -//+------------------------------------------------------------------+ -uint CColorGenerator::Next(void) - { -//--- check the array out of range - if(m_index==20) - { - m_index=0; - if(!m_generate) - m_generate=true; - } -//--- check the default palette is over - if(m_generate) - m_current_palette[m_index]=(m_index==19 ? (m_current_palette[m_index]^m_current_palette[0]):(m_current_palette[m_index]^m_current_palette[m_index+1])); -//--- return next color - return(m_current_palette[m_index++]); - } -//+------------------------------------------------------------------+ -//| Resets all the new colors, set the index to 0 | -//+------------------------------------------------------------------+ -void CColorGenerator::Reset(void) - { - m_index=0; - m_generate=false; - ArrayCopy(m_current_palette,s_default_palette); - } -//+------------------------------------------------------------------+ diff --git a/Include/Graphics/Curve.mqh b/Include/Graphics/Curve.mqh deleted file mode 100644 index 6f3db80..0000000 --- a/Include/Graphics/Curve.mqh +++ /dev/null @@ -1,700 +0,0 @@ -//+------------------------------------------------------------------+ -//| Curve.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -//--- forward declaration -class CGraphic; -//--- fucntion for represent custom plot method -typedef void(*PlotFucntion)(double &x[],double &y[],int size,CGraphic *graphic,CCanvas *canvas,void *cbdata); -//--- function for represent curve -typedef double(*CurveFunction)(double); -//--- drawing type -enum ENUM_CURVE_TYPE - { - CURVE_POINTS, - CURVE_LINES, - CURVE_POINTS_AND_LINES, - CURVE_STEPS, - CURVE_HISTOGRAM, - CURVE_CUSTOM, - CURVE_NONE - }; -//--- type for the various point shapes that are available -enum ENUM_POINT_TYPE - { - POINT_CIRCLE, - POINT_SQUARE, - POINT_DIAMOND, - POINT_TRIANGLE, - POINT_TRIANGLE_DOWN, - POINT_X_CROSS, - POINT_PLUS, - POINT_STAR, - POINT_HORIZONTAL_DASH, - POINT_VERTICAL_DASH - }; -//+------------------------------------------------------------------+ -//| Structure CPoint2D | -//| Usage: 2d point on graphic in Cartesian coordinates | -//+------------------------------------------------------------------+ -struct CPoint2D - { - double x; - double y; - }; -//+------------------------------------------------------------------+ -//| Class CCurve | -//| Usage: class to represent the one-dimensional curve | -//+------------------------------------------------------------------+ -class CCurve : public CObject - { -private: - uint m_clr; - double m_x[]; - double m_y[]; - double m_xmin; - double m_xmax; - double m_ymin; - double m_ymax; - int m_size; - ENUM_CURVE_TYPE m_type; - string m_name; - //--- lines - ENUM_LINE_STYLE m_lines_style; - ENUM_LINE_END m_lines_end_style; - int m_lines_width; - bool m_lines_smooth; - double m_lines_tension; - double m_lines_step; - //--- points - int m_points_size; - ENUM_POINT_TYPE m_points_type; - bool m_points_fill; - uint m_points_clr; - //--- steps - int m_steps_dimension; - //--- histogram - int m_hisogram_width; - //--- custom - PlotFucntion m_custom_plot_func; - void *m_custom_plot_cbdata; - //--- general property - bool m_visible; - //--- trend line property - uint m_trend_clr; - bool m_trend_visible; - -protected: - bool m_trend_calc; - double m_trend_coeff[]; - -public: - CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name); - CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name); - CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name); - CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name); - ~CCurve(void); - //--- gets the general properties - void GetX(double &x[]) const { ArrayCopy(x,m_x); } - void GetY(double &y[]) const { ArrayCopy(y,m_y); } - double XMax(void) const { return(m_xmax); } - double XMin(void) const { return(m_xmin); } - double YMax(void) const { return(m_ymax); } - double YMin(void) const { return(m_ymin); } - int Size(void) const { return(m_size); } - //--- update - void Update(const double &y[]); - void Update(const double &x[],const double &y[]); - void Update(const CPoint2D &points[]); - void Update(CurveFunction function,const double from,const double to,const double step); - //--- gets or sets general options - uint Color(void) const { return(m_clr); } - int Type(void) const { return(m_type); } - string Name(void) const { return(m_name); } - bool Visible(void) const { return(m_visible); } - void Color(const uint clr) { m_clr=clr; } - void Type(const int type) { m_type=(ENUM_CURVE_TYPE)type; } - void Name(const string name) { m_name=name; } - void Visible(const bool visible) { m_visible=visible; } - //--- gets or sets the lines properties - ENUM_LINE_STYLE LinesStyle(void) const { return(m_lines_style); } - ENUM_LINE_END LinesEndStyle(void) const { return(m_lines_end_style); } - int LinesWidth(void) const { return(m_lines_width); } - bool LinesSmooth(void) const { return(m_lines_smooth); } - double LinesSmoothTension(void) const { return(m_lines_tension); } - double LinesSmoothStep(void) const { return(m_lines_step); } - void LinesStyle(ENUM_LINE_STYLE style) { m_lines_style=style; } - void LinesEndStyle(ENUM_LINE_END end_style) { m_lines_end_style=end_style; } - void LinesWidth(const int width) { m_lines_width=width; } - void LinesSmooth(const bool smooth) { m_lines_smooth=smooth; } - void LinesSmoothTension(const double tension) { m_lines_tension=tension; } - void LinesSmoothStep(const double step) { m_lines_step=step; } - //--- gets or sets the points properties - int PointsSize(void) const { return(m_points_size); } - ENUM_POINT_TYPE PointsType(void) const { return(m_points_type); } - bool PointsFill(void) const { return(m_points_fill); } - uint PointsColor(void) const { return(m_points_clr); } - void PointsSize(const int size) { m_points_size=size; } - void PointsType(ENUM_POINT_TYPE type) { m_points_type=type; } - void PointsFill(const bool fill) { m_points_fill=fill; } - void PointsColor(const uint clr) { m_points_clr=clr; } - //--- gets or sets the steps properties - int StepsDimension(void) const { return(m_steps_dimension); } - void StepsDimension(const int dimension) { m_steps_dimension=dimension; } - //--- gets or sets the histogram properties - int HistogramWidth(void) const { return(m_hisogram_width); } - void HistogramWidth(const int width) { m_hisogram_width=width; } - //--- gets or sets the custom properties - PlotFucntion CustomPlotFunction(void) const { return(m_custom_plot_func); } - void *CustomPlotCBData(void) const { return(m_custom_plot_cbdata); } - void CustomPlotFunction(PlotFucntion func) { m_custom_plot_func=func; } - void CustomPlotCBData(void *cbdata) { m_custom_plot_cbdata=cbdata; } - //--- gets or sets the trend line properties - bool TrendLineVisible(void) const { return(m_trend_visible); } - uint TrendLineColor(void) const { return(m_trend_clr); } - void TrendLineVisible(const bool visible) { m_trend_visible=visible; } - void TrendLineColor(const uint clr) { m_trend_clr=clr; } - void TrendLineCoefficients(double &coefficients[]); - -protected: - virtual void CalculateCoefficients(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCurve::CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name) - : m_name(name), - m_clr(clr), - m_type(type), - m_visible(false), - m_lines_style(STYLE_SOLID), - m_lines_end_style(LINE_END_ROUND), - m_lines_width(1), - m_lines_smooth(false), - m_lines_tension(0.5), - m_lines_step(1.0), - m_points_size(6), - m_points_type(POINT_CIRCLE), - m_points_fill(false), - m_points_clr(clr), - m_steps_dimension(0), - m_hisogram_width(1), - m_custom_plot_func(NULL), - m_custom_plot_cbdata(NULL), - m_trend_visible(false), - m_trend_clr(clr), - m_trend_calc(false) - { -//--- keep y array - m_size=ArraySize(y); - ArrayResize(m_x,m_size); - ArrayCopy(m_y,y); - m_xmax = m_size-1; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; -//--- find min and max values - for(int i=0; iy[i]) - m_ymin=y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCurve::CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name) - : m_name(name), - m_clr(clr), - m_type(type), - m_visible(false), - m_lines_style(STYLE_SOLID), - m_lines_end_style(LINE_END_ROUND), - m_lines_width(1), - m_lines_smooth(false), - m_lines_tension(0.5), - m_lines_step(1.0), - m_points_size(6), - m_points_type(POINT_CIRCLE), - m_points_fill(false), - m_points_clr(clr), - m_steps_dimension(0), - m_hisogram_width(1), - m_custom_plot_func(NULL), - m_custom_plot_cbdata(NULL), - m_trend_visible(false), - m_trend_clr(clr), - m_trend_calc(false) - { -//--- keep x and y array - ArrayCopy(m_x,x); - ArrayCopy(m_y,y); - m_size = ArraySize(x); - m_xmax = 0.0; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; - bool xvalid=false; -//--- find min and max values - for(int i=0; ix[i]) - m_xmin=x[i]; - } - } - if(MathIsValidNumber(m_y[i])) - { - if(!yvalid) - { - m_ymax = y[i]; - m_ymin = y[i]; - yvalid=true; - } - else - { - //--- find max and min of y - if(m_ymaxy[i]) - m_ymin=y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCurve::CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name) - : m_name(name), - m_clr(clr), - m_type(type), - m_visible(false), - m_lines_style(STYLE_SOLID), - m_lines_end_style(LINE_END_ROUND), - m_lines_width(1), - m_lines_smooth(false), - m_lines_tension(0.5), - m_lines_step(1.0), - m_points_size(6), - m_points_type(POINT_CIRCLE), - m_points_fill(false), - m_points_clr(clr), - m_steps_dimension(0), - m_hisogram_width(1), - m_custom_plot_func(NULL), - m_custom_plot_cbdata(NULL), - m_trend_visible(false), - m_trend_clr(clr), - m_trend_calc(false) - { -//--- preliminary calculation - m_size=ArraySize(points); - ArrayResize(m_x,m_size); - ArrayResize(m_y,m_size); - m_xmax = 0.0; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool xvalid=false; - bool yvalid=false; -//--- keep x and y array - for(int i=0; im_x[i]) - m_xmin=m_x[i]; - } - } - if(MathIsValidNumber(m_y[i])) - { - if(!yvalid) - { - m_ymax = m_y[i]; - m_ymin = m_y[i]; - yvalid=true; - } - else - { - //--- find max and min of y - if(m_ymaxm_y[i]) - m_ymin=m_y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCurve::CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name) - : m_name(name), - m_clr(clr), - m_type(type), - m_visible(false), - m_lines_style(STYLE_SOLID), - m_lines_end_style(LINE_END_ROUND), - m_lines_width(1), - m_lines_smooth(false), - m_lines_tension(0.5), - m_lines_step(1.0), - m_points_size(6), - m_points_type(POINT_CIRCLE), - m_points_fill(false), - m_points_clr(clr), - m_steps_dimension(0), - m_hisogram_width(1), - m_custom_plot_func(NULL), - m_custom_plot_cbdata(NULL), - m_trend_visible(false), - m_trend_clr(clr), - m_trend_calc(false) - { -//--- preliminary calculation - m_size=(int)((to-from)/step)+1; - ArrayResize(m_x,m_size); - ArrayResize(m_y,m_size); - m_xmax = to; - m_xmin = from; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; -//--- keep x and y array - for(int i=0; im_y[i]) - m_ymin=m_y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCurve::~CCurve(void) - { - } -//+------------------------------------------------------------------+ -//| Update x and y coordinates of curve | -//+------------------------------------------------------------------+ -void CCurve::Update(const double &y[]) - { - m_trend_calc=false; - ArrayFree(m_y); - int size=ArraySize(y); -//--- keep y array - if(m_size!=size) - { - m_size=size; - ArrayResize(m_x,m_size); - } - ArrayCopy(m_y,y); - m_xmax = m_size-1; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; -//--- find min and max values - for(int i=0; iy[i]) - m_ymin=y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Update x and y coordinates of curve | -//+------------------------------------------------------------------+ -void CCurve::Update(const double &x[],const double &y[]) - { - m_trend_calc=false; - ArrayFree(m_x); - ArrayFree(m_y); -//--- keep x and y array - ArrayCopy(m_x,x); - ArrayCopy(m_y,y); - m_size = ArraySize(x); - m_xmax = 0.0; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; - bool xvalid=false; -//--- find min and max values - for(int i=0; ix[i]) - m_xmin=x[i]; - } - } - if(MathIsValidNumber(m_y[i])) - { - if(!yvalid) - { - m_ymax = y[i]; - m_ymin = y[i]; - yvalid=true; - } - else - { - //--- find max and min of y - if(m_ymaxy[i]) - m_ymin=y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Update x and y coordinates of curve | -//+------------------------------------------------------------------+ -void CCurve::Update(const CPoint2D &points[]) - { - m_trend_calc=false; - int size=ArraySize(points); -//--- preliminary calculation - if(size!=m_size) - { - m_size=size; - ArrayResize(m_x,m_size); - ArrayResize(m_y,m_size); - } - m_xmax = 0.0; - m_xmin = 0.0; - m_ymax = 0.0; - m_ymin = 0.0; - bool xvalid=false; - bool yvalid=false; -//--- keep x and y array - for(int i=0; im_x[i]) - m_xmin=m_x[i]; - } - } - if(MathIsValidNumber(m_y[i])) - { - if(!yvalid) - { - m_ymax = m_y[i]; - m_ymin = m_y[i]; - yvalid=true; - } - else - { - //--- find max and min of y - if(m_ymaxm_y[i]) - m_ymin=m_y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Update x and y coordinates of curve | -//+------------------------------------------------------------------+ -void CCurve::Update(CurveFunction function,const double from,const double to,const double step) - { - m_trend_calc=false; - int size=(int)((to-from)/step)+1; -//--- preliminary calculation - if(size!=m_size) - { - m_size=size; - ArrayResize(m_x,m_size); - ArrayResize(m_y,m_size); - } - m_xmax = to; - m_xmin = from; - m_ymax = 0.0; - m_ymin = 0.0; - bool yvalid=false; -//--- keep x and y array - for(int i=0; im_y[i]) - m_ymin=m_y[i]; - } - } - } -//--- - } -//+------------------------------------------------------------------+ -//| Gets the coefficients for trend line | -//+------------------------------------------------------------------+ -void CCurve::TrendLineCoefficients(double &coefficients[]) - { - if(!m_trend_calc) - { - CalculateCoefficients(); - m_trend_calc=true; - } - ArrayCopy(coefficients,m_trend_coeff); - } -//+------------------------------------------------------------------+ -//| Calculate coefficients | -//+------------------------------------------------------------------+ -void CCurve::CalculateCoefficients(void) - { -//--- simple linear resgression - ArrayResize(m_trend_coeff,2); - double xmean=0.0; - double ymean=0.0; - double sum_xy=0.0; - double sum_xx=0.0; -//--- primary calculate - for(int i=0; iUva(1Vsv?QWdZ&!kN(%_9|W2&Mt>Wv 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 diff --git a/Include/Math/Alglib/alglib.mqh b/Include/Math/Alglib/alglib.mqh deleted file mode 100644 index f8085e6..0000000 --- a/Include/Math/Alglib/alglib.mqh +++ /dev/null @@ -1,23023 +0,0 @@ -//+------------------------------------------------------------------+ -//| alglib.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "alglibmisc.mqh" -#include "dataanalysis.mqh" -#include "diffequations.mqh" -#include "delegatefunctions.mqh" -#include "fasttransforms.mqh" -#include "integration.mqh" -#include "interpolation.mqh" -//+------------------------------------------------------------------+ -//| The main class, which includes functions for users | -//+------------------------------------------------------------------+ -class CAlglib - { -public: - //--- constructor, destructor - CAlglib(void); - ~CAlglib(void); - //--- function of package alglibmisc - //--- high quality random number generator - static void HQRndRandomize(CHighQualityRandStateShell &state); - static void HQRndSeed(const int s1,const int s2,CHighQualityRandStateShell &state); - static double HQRndUniformR(CHighQualityRandStateShell &state); - static int HQRndUniformI(CHighQualityRandStateShell &state,const int n); - static double HQRndNormal(CHighQualityRandStateShell &state); - static void HQRndUnit2(CHighQualityRandStateShell &state,double &x,double &y); - static void HQRndNormal2(CHighQualityRandStateShell &state,double &x1,double &x2); - static double HQRndExponential(CHighQualityRandStateShell &state,const double lambdav); - //--- build KD-trees - static void KDTreeSerialize(CKDTreeShell &obj,string &s_out); - static void KDTreeUnserialize(string s_in,CKDTreeShell &obj); - static void KDTreeBuild(CMatrixDouble &xy,const int n,const int nx,const int ny,const int normtype,CKDTreeShell &kdt); - static void KDTreeBuild(CMatrixDouble &xy,const int nx,const int ny,const int normtype,CKDTreeShell &kdt); - static void KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],const int n,const int nx,const int ny,const int normtype,CKDTreeShell &kdt); - static void KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],const int nx,const int ny,const int normtype,CKDTreeShell &kdt); - static int KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k,const bool selfmatch); - static int KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k); - static int KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r,const bool selfmatch); - static int KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r); - static int KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],const int k,const bool selfmatch,const double eps); - static int KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],const int k,const double eps); - static void KDTreeQueryResultsX(CKDTreeShell &kdt,CMatrixDouble &x); - static void KDTreeQueryResultsXY(CKDTreeShell &kdt,CMatrixDouble &xy); - static void KDTreeQueryResultsTags(CKDTreeShell &kdt,int &tags[]); - static void KDTreeQueryResultsDistances(CKDTreeShell &kdt,double &r[]); - static void KDTreeQueryResultsXI(CKDTreeShell &kdt,CMatrixDouble &x); - static void KDTreeQueryResultsXYI(CKDTreeShell &kdt,CMatrixDouble &xy); - static void KDTreeQueryResultsTagsI(CKDTreeShell &kdt,int &tags[]); - static void KDTreeQueryResultsDistancesI(CKDTreeShell &kdt,double &r[]); - //--- function of package dataanalysis - //--- data analysis - static void DSOptimalSplit2(double &a[],int &c[],const int n,int &info,double &threshold,double &pal,double &pbl,double &par,double &pbr,double &cve); - static void DSOptimalSplit2Fast(double &a[],int &c[],int &tiesbuf[],int &cntbuf[],double &bufr[],int &bufi[],const int n,const int nc,const double alpha,int &info,double &threshold,double &rms,double &cvrms); - //--- decision forest - static void DFSerialize(CDecisionForestShell &obj,string &s_out); - static void DFUnserialize(const string s_in,CDecisionForestShell &obj); - static void DFBuildRandomDecisionForest(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,const double r,int &info,CDecisionForestShell &df,CDFReportShell &rep); - static void DFBuildRandomDecisionForestX1(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,int nrndvars,const double r,int &info,CDecisionForestShell &df,CDFReportShell &rep); - static void DFProcess(CDecisionForestShell &df,double &x[],double &y[]); - static void DFProcessI(CDecisionForestShell &df,double &x[],double &y[]); - static double DFRelClsError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints); - static double DFAvgCE(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints); - static double DFRMSError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints); - static double DFAvgError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints); - static double DFAvgRelError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints); - //--- middle and clusterization - static void KMeansGenerate(CMatrixDouble &xy,const int npoints,const int nvars,const int k,const int restarts,int &info,CMatrixDouble &c,int &xyc[]); - //--- Fisher LDA functions - static void FisherLDA(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,double &w[]); - static void FisherLDAN(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,CMatrixDouble &w); - //--- linear regression - static void LRBuild(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar); - static void LRBuildS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar); - static void LRBuildZS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar); - static void LRBuildZ(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar); - static void LRUnpack(CLinearModelShell &lm,double &v[],int &nvars); - static void LRPack(double &v[],const int nvars,CLinearModelShell &lm); - static double LRProcess(CLinearModelShell &lm,double &x[]); - static double LRRMSError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints); - static double LRAvgError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints); - static double LRAvgRelError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints); - //--- multilayer perceptron - static void MLPSerialize(CMultilayerPerceptronShell &obj,string &s_out); - static void MLPUnserialize(const string s_in,CMultilayerPerceptronShell &obj); - static void MLPCreate0(const int nin,const int nout,CMultilayerPerceptronShell &network); - static void MLPCreate1(const int nin,int nhid,const int nout,CMultilayerPerceptronShell &network); - static void MLPCreate2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptronShell &network); - static void MLPCreateB0(const int nin,const int nout,const double b,const double d,CMultilayerPerceptronShell &network); - static void MLPCreateB1(const int nin,int nhid,const int nout,const double b,const double d,CMultilayerPerceptronShell &network); - static void MLPCreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,const double d,CMultilayerPerceptronShell &network); - static void MLPCreateR0(const int nin,const int nout,double a,const double b,CMultilayerPerceptronShell &network); - static void MLPCreateR1(const int nin,int nhid,const int nout,const double a,const double b,CMultilayerPerceptronShell &network); - static void MLPCreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,CMultilayerPerceptronShell &network); - static void MLPCreateC0(const int nin,const int nout,CMultilayerPerceptronShell &network); - static void MLPCreateC1(const int nin,int nhid,const int nout,CMultilayerPerceptronShell &network); - static void MLPCreateC2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptronShell &network); - static void MLPRandomize(CMultilayerPerceptronShell &network); - static void MLPRandomizeFull(CMultilayerPerceptronShell &network); - static void MLPProperties(CMultilayerPerceptronShell &network,int &nin,int &nout,int &wcount); - static bool MLPIsSoftMax(CMultilayerPerceptronShell &network); - static int MLPGetLayersCount(CMultilayerPerceptronShell &network); - static int MLPGetLayerSize(CMultilayerPerceptronShell &network,const int k); - static void MLPGetInputScaling(CMultilayerPerceptronShell &network,const int i,double &mean,double &sigma); - static void MLPGetOutputScaling(CMultilayerPerceptronShell &network,const int i,double &mean,double &sigma); - static void MLPGetNeuronInfo(CMultilayerPerceptronShell &network,const int k,const int i,int &fkind,double &threshold); - static double MLPGetWeight(CMultilayerPerceptronShell &network,const int k0,const int i0,const int k1,const int i1); - static void MLPSetInputScaling(CMultilayerPerceptronShell &network,const int i,const double mean,const double sigma); - static void MLPSetOutputScaling(CMultilayerPerceptronShell &network,const int i,const double mean,const double sigma); - static void MLPSetNeuronInfo(CMultilayerPerceptronShell &network,const int k,const int i,int fkind,double threshold); - static void MLPSetWeight(CMultilayerPerceptronShell &network,const int k0,const int i0,const int k1,const int i1,const double w); - static void MLPActivationFunction(const double net,const int k,double &f,double &df,double &d2f); - static void MLPProcess(CMultilayerPerceptronShell &network,double &x[],double &y[]); - static void MLPProcessI(CMultilayerPerceptronShell &network,double &x[],double &y[]); - static double MLPError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize); - static double MLPErrorN(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize); - static int MLPClsError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize); - static double MLPRelClsError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgCE(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints); - static double MLPRMSError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgRelError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints); - static void MLPGrad(CMultilayerPerceptronShell &network,double &x[],double &desiredy[],double &e,double &grad[]); - static void MLPGradN(CMultilayerPerceptronShell &network,double &x[],double &desiredy[],double &e,double &grad[]); - static void MLPGradBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]); - static void MLPGradNBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]); - static void MLPHessianNBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h); - static void MLPHessianBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h); - //--- logit model functions - static void MNLTrainH(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,CLogitModelShell &lm,CMNLReportShell &rep); - static void MNLProcess(CLogitModelShell &lm,double &x[],double &y[]); - static void MNLProcessI(CLogitModelShell &lm,double &x[],double &y[]); - static void MNLUnpack(CLogitModelShell &lm,CMatrixDouble &a,int &nvars,int &nclasses); - static void MNLPack(CMatrixDouble &a,const int nvars,const int nclasses,CLogitModelShell &lm); - static double MNLAvgCE(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints); - static double MNLRelClsError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints); - static double MNLRMSError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints); - static double MNLAvgError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints); - static double MNLAvgRelError(CLogitModelShell &lm,CMatrixDouble &xy,const int ssize); - static int MNLClsError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints); - //--- Markov chains - static void MCPDCreate(const int n,CMCPDStateShell &s); - static void MCPDCreateEntry(const int n,const int entrystate,CMCPDStateShell &s); - static void MCPDCreateExit(const int n,const int exitstate,CMCPDStateShell &s); - static void MCPDCreateEntryExit(const int n,const int entrystate,const int exitstate,CMCPDStateShell &s); - static void MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy,const int k); - static void MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy); - static void MCPDSetEC(CMCPDStateShell &s,CMatrixDouble &ec); - static void MCPDAddEC(CMCPDStateShell &s,const int i,const int j,const double c); - static void MCPDSetBC(CMCPDStateShell &s,CMatrixDouble &bndl,CMatrixDouble &bndu); - static void MCPDAddBC(CMCPDStateShell &s,const int i,const int j,const double bndl,const double bndu); - static void MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,int &ct[],const int k); - static void MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,int &ct[]); - static void MCPDSetTikhonovRegularizer(CMCPDStateShell &s,const double v); - static void MCPDSetPrior(CMCPDStateShell &s,CMatrixDouble &pp); - static void MCPDSetPredictionWeights(CMCPDStateShell &s,double &pw[]); - static void MCPDSolve(CMCPDStateShell &s); - static void MCPDResults(CMCPDStateShell &s,CMatrixDouble &p,CMCPDReportShell &rep); - //--- training neural networks - static void MLPTrainLM(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep); - static void MLPTrainLBFGS(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,int maxits,int &info,CMLPReportShell &rep); - static void MLPTrainES(CMultilayerPerceptronShell &network,CMatrixDouble &trnxy,const int trnsize,CMatrixDouble &valxy,const int valsize,const double decay,const int restarts,int &info,CMLPReportShell &rep); - static void MLPKFoldCVLBFGS(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,const int foldscount,int &info,CMLPReportShell &rep,CMLPCVReportShell &cvrep); - static void MLPKFoldCVLM(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const int foldscount,int &info,CMLPReportShell &rep,CMLPCVReportShell &cvrep); - //--- neural networks ensemble functions - static void MLPECreate0(const int nin,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreate1(const int nin,int nhid,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreate2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateB0(const int nin,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateB1(const int nin,int nhid,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateR0(const int nin,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateR1(const int nin,int nhid,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateC0(const int nin,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateC1(const int nin,int nhid,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateC2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPECreateFromNetwork(CMultilayerPerceptronShell &network,const int ensemblesize,CMLPEnsembleShell &ensemble); - static void MLPERandomize(CMLPEnsembleShell &ensemble); - static void MLPEProperties(CMLPEnsembleShell &ensemble,int &nin,int &nout); - static bool MLPEIsSoftMax(CMLPEnsembleShell &ensemble); - static void MLPEProcess(CMLPEnsembleShell &ensemble,double &x[],double &y[]); - static void MLPEProcessI(CMLPEnsembleShell &ensemble,double &x[],double &y[]); - static double MLPERelClsError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgCE(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPERMSError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgRelError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints); - static void MLPEBaggingLM(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep,CMLPCVReportShell &ooberrors); - static void MLPEBaggingLBFGS(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,int &info,CMLPReportShell &rep,CMLPCVReportShell &ooberrors); - static void MLPETrainES(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep); - //--- principal components analysis - static void PCABuildBasis(CMatrixDouble &x,const int npoints,const int nvars,int &info,double &s2[],CMatrixDouble &v); - //--- function of package diffequations - static void ODESolverRKCK(double &y[],const int n,double &x[],const int m,const double eps,const double h,CODESolverStateShell &state); - static void ODESolverRKCK(double &y[],double &x[],const double eps,const double h,CODESolverStateShell &state); - static bool ODESolverIteration(CODESolverStateShell &state); - static void ODESolverSolve(CODESolverStateShell &state,CNDimensional_ODE_RP &diff,CObject &obj); - static void ODESolverResults(CODESolverStateShell &state,int &m,double &xtbl[],CMatrixDouble &ytbl,CODESolverReportShell &rep); - //--- function of package fasttransforms - //--- fast Fourier transform - static void FFTC1D(al_complex &a[],const int n); - static void FFTC1D(al_complex &a[]); - static void FFTC1DInv(al_complex &a[],const int n); - static void FFTC1DInv(al_complex &a[]); - static void FFTR1D(double &a[],const int n,al_complex &f[]); - static void FFTR1D(double &a[],al_complex &f[]); - static void FFTR1DInv(al_complex &f[],const int n,double &a[]); - static void FFTR1DInv(al_complex &f[],double &a[]); - //--- convolution - static void ConvC1D(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvC1DInv(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvC1DCircular(al_complex &s[],const int m,al_complex &r[],const int n,al_complex &c[]); - static void ConvC1DCircularInv(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvR1D(double &a[],const int m,double &b[],const int n,double &r[]); - static void ConvR1DInv(double &a[],const int m,double &b[],const int n,double &r[]); - static void ConvR1DCircular(double &s[],const int m,double &r[],const int n,double &c[]); - static void ConvR1DCircularInv(double &a[],const int m,double &b[],const int n,double &r[]); - static void CorrC1D(al_complex &signal[],const int n,al_complex &pattern[],const int m,al_complex &r[]); - static void CorrC1DCircular(al_complex &signal[],const int m,al_complex &pattern[],const int n,al_complex &c[]); - static void CorrR1D(double &signal[],const int n,double &pattern[],const int m,double &r[]); - static void CorrR1DCircular(double &signal[],const int m,double &pattern[],const int n,double &c[]); - //--- fast Hartley transform - static void FHTR1D(double &a[],const int n); - static void FHTR1DInv(double &a[],const int n); - //--- function of package integration - //--- Gauss quadrature formula - static void GQGenerateRec(double &alpha[],double &beta[],const double mu0,const int n,int &info,double &x[],double &w[]); - static void GQGenerateGaussLobattoRec(double &alpha[],double &beta[],const double mu0,const double a,const double b,const int n,int &info,double &x[],double &w[]); - static void GQGenerateGaussRadauRec(double &alpha[],double &beta[],const double mu0,const double a,const int n,int &info,double &x[],double &w[]); - static void GQGenerateGaussLegendre(const int n,int &info,double &x[],double &w[]); - static void GQGenerateGaussJacobi(const int n,const double alpha,const double beta,int &info,double &x[],double &w[]); - static void GQGenerateGaussLaguerre(const int n,const double alpha,int &info,double &x[],double &w[]); - static void GQGenerateGaussHermite(const int n,int &info,double &x[],double &w[]); - //--- Gauss-Kronrod quadrature formula - static void GKQGenerateRec(double &alpha[],double &beta[],const double mu0,const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]); - static void GKQGenerateGaussLegendre(const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]); - static void GKQGenerateGaussJacobi(const int n,const double alpha,const double beta,int &info,double &x[],double &wkronrod[],double &wgauss[]); - static void GKQLegendreCalc(const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]); - static void GKQLegendreTbl(const int n,double &x[],double &wkronrod[],double &wgauss[],double &eps); - //--- auto Gauss-Kronrod - static void AutoGKSmooth(const double a,const double b,CAutoGKStateShell &state); - static void AutoGKSmoothW(const double a,const double b,double xwidth,CAutoGKStateShell &state); - static void AutoGKSingular(const double a,const double b,const double alpha,const double beta,CAutoGKStateShell &state); - static bool AutoGKIteration(CAutoGKStateShell &state); - static void AutoGKIntegrate(CAutoGKStateShell &state,CIntegrator1_Func &func,CObject &obj); - static void AutoGKResults(CAutoGKStateShell &state,double &v,CAutoGKReportShell &rep); - //--- function of package interpolation - //--- inverse distance weighting interpolation - static double IDWCalc(CIDWInterpolantShell &z,double &x[]); - static void IDWBuildModifiedShepard(CMatrixDouble &xy,const int n,const int nx,const int d,const int nq,const int nw,CIDWInterpolantShell &z); - static void IDWBuildModifiedShepardR(CMatrixDouble &xy,const int n,const int nx,const double r,CIDWInterpolantShell &z); - static void IDWBuildNoisy(CMatrixDouble &xy,const int n,const int nx,const int d,const int nq,const int nw,CIDWInterpolantShell &z); - //--- rational interpolation - static double BarycentricCalc(CBarycentricInterpolantShell &b,const double t); - static void BarycentricDiff1(CBarycentricInterpolantShell &b,const double t,double &f,double &df); - static void BarycentricDiff2(CBarycentricInterpolantShell &b,const double t,double &f,double &df,double &d2f); - static void BarycentricLinTransX(CBarycentricInterpolantShell &b,const double ca,const double cb); - static void BarycentricLinTransY(CBarycentricInterpolantShell &b,const double ca,const double cb); - static void BarycentricUnpack(CBarycentricInterpolantShell &b,int &n,double &x[],double &y[],double &w[]); - static void BarycentricBuildXYW(double &x[],double &y[],double &w[],const int n,CBarycentricInterpolantShell &b); - static void BarycentricBuildFloaterHormann(double &x[],double &y[],const int n,const int d,CBarycentricInterpolantShell &b); - //--- polynomial interpolant - static void PolynomialBar2Cheb(CBarycentricInterpolantShell &p,const double a,const double b,double &t[]); - static void PolynomialCheb2Bar(double &t[],const int n,const double a,const double b,CBarycentricInterpolantShell &p); - static void PolynomialCheb2Bar(double &t[],const double a,const double b,CBarycentricInterpolantShell &p); - static void PolynomialBar2Pow(CBarycentricInterpolantShell &p,const double c,const double s,double &a[]); - static void PolynomialBar2Pow(CBarycentricInterpolantShell &p,double &a[]); - static void PolynomialPow2Bar(double &a[],const int n,const double c,const double s,CBarycentricInterpolantShell &p); - static void PolynomialPow2Bar(double &a[],CBarycentricInterpolantShell &p); - static void PolynomialBuild(double &x[],double &y[],const int n,CBarycentricInterpolantShell &p); - static void PolynomialBuild(double &x[],double &y[],CBarycentricInterpolantShell &p); - static void PolynomialBuildEqDist(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p); - static void PolynomialBuildEqDist(const double a,const double b,double &y[],CBarycentricInterpolantShell &p); - static void PolynomialBuildCheb1(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p); - static void PolynomialBuildCheb1(const double a,const double b,double &y[],CBarycentricInterpolantShell &p); - static void PolynomialBuildCheb2(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p); - static void PolynomialBuildCheb2(const double a,const double b,double &y[],CBarycentricInterpolantShell &p); - static double PolynomialCalcEqDist(const double a,const double b,double &f[],const int n,const double t); - static double PolynomialCalcEqDist(const double a,const double b,double &f[],const double t); - static double PolynomialCalcCheb1(const double a,const double b,double &f[],const int n,const double t); - static double PolynomialCalcCheb1(const double a,const double b,double &f[],const double t); - static double PolynomialCalcCheb2(const double a,const double b,double &f[],const int n,const double t); - static double PolynomialCalcCheb2(const double a,const double b,double &f[],const double t); - //--- 1-dimensional spline interpolation - static void Spline1DBuildLinear(double &x[],double &y[],const int n,CSpline1DInterpolantShell &c); - static void Spline1DBuildLinear(double &x[],double &y[],CSpline1DInterpolantShell &c); - static void Spline1DBuildCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,CSpline1DInterpolantShell &c); - static void Spline1DBuildCubic(double &x[],double &y[],CSpline1DInterpolantShell &c); - static void Spline1DGridDiffCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d[]); - static void Spline1DGridDiffCubic(double &x[],double &y[],double &d[]); - static void Spline1DGridDiff2Cubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d1[],double &d2[]); - static void Spline1DGridDiff2Cubic(double &x[],double &y[],double &d1[],double &d2[]); - static void Spline1DConvCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],int n2,double &y2[]); - static void Spline1DConvCubic(double &x[],double &y[],double &x2[],double &y2[]); - static void Spline1DConvDiffCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],int n2,double &y2[],double &d2[]); - static void Spline1DConvDiffCubic(double &x[],double &y[],double &x2[],double &y2[],double &d2[]); - static void Spline1DConvDiff2Cubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],const int n2,double &y2[],double &d2[],double &dd2[]); - static void Spline1DConvDiff2Cubic(double &x[],double &y[],double &x2[],double &y2[],double &d2[],double &dd2[]); - static void Spline1DBuildCatmullRom(double &x[],double &y[],const int n,const int boundtype,const double tension,CSpline1DInterpolantShell &c); - static void Spline1DBuildCatmullRom(double &x[],double &y[],CSpline1DInterpolantShell &c); - static void Spline1DBuildHermite(double &x[],double &y[],double &d[],const int n,CSpline1DInterpolantShell &c); - static void Spline1DBuildHermite(double &x[],double &y[],double &d[],CSpline1DInterpolantShell &c); - static void Spline1DBuildAkima(double &x[],double &y[],const int n,CSpline1DInterpolantShell &c); - static void Spline1DBuildAkima(double &x[],double &y[],CSpline1DInterpolantShell &c); - static double Spline1DCalc(CSpline1DInterpolantShell &c,const double x); - static void Spline1DDiff(CSpline1DInterpolantShell &c,const double x,double &s,double &ds,double &d2s); - static void Spline1DUnpack(CSpline1DInterpolantShell &c,int &n,CMatrixDouble &tbl); - static void Spline1DLinTransX(CSpline1DInterpolantShell &c,const double a,const double b); - static void Spline1DLinTransY(CSpline1DInterpolantShell &c,const double a,const double b); - static double Spline1DIntegrate(CSpline1DInterpolantShell &c,const double x); - //--- least squares fitting - static void PolynomialFit(double &x[],double &y[],const int n,const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep); - static void PolynomialFit(double &x[],double &y[],const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep); - static void PolynomialFitWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep); - static void PolynomialFitWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep); - static void BarycentricFitFloaterHormannWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CBarycentricInterpolantShell &b,CBarycentricFitReportShell &rep); - static void BarycentricFitFloaterHormann(double &x[],double &y[],const int n,const int m,int &info,CBarycentricInterpolantShell &b,CBarycentricFitReportShell &rep); - static void Spline1DFitPenalized(double &x[],double &y[],const int n,const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitPenalized(double &x[],double &y[],const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitPenalizedW(double &x[],double &y[],double &w[],const int n,const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitPenalizedW(double &x[],double &y[],double &w[],const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitCubicWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitCubicWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitHermiteWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitHermiteWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitCubic(double &x[],double &y[],const int n,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitCubic(double &x[],double &y[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitHermite(double &x[],double &y[],const int n,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void Spline1DFitHermite(double &x[],double &y[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep); - static void LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,const int n,const int m,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,const int n,const int m,const int k,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinear(double &y[],CMatrixDouble &fmatrix,const int n,const int m,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinear(double &y[],CMatrixDouble &fmatrix,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinearC(double &y[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,const int n,const int m,const int k,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitLinearC(double &y[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,int &info,double &c[],CLSFitReportShell &rep); - static void LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,const double diffstep,CLSFitStateShell &state); - static void LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],double &c[],const double diffstep,CLSFitStateShell &state); - static void LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,const double diffstep,CLSFitStateShell &state); - static void LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],const double diffstep,CLSFitStateShell &state); - static void LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,const bool cheapfg,CLSFitStateShell &state); - static void LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],double &c[],const bool cheapfg,CLSFitStateShell &state); - static void LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,const bool cheapfg,CLSFitStateShell &state); - static void LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],const bool cheapfg,CLSFitStateShell &state); - static void LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,CLSFitStateShell &state); - static void LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],double &c[],CLSFitStateShell &state); - static void LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,CLSFitStateShell &state); - static void LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],CLSFitStateShell &state); - static void LSFitSetCond(CLSFitStateShell &state,const double epsf,const double epsx,const int maxits); - static void LSFitSetStpMax(CLSFitStateShell &state,const double stpmax); - static void LSFitSetXRep(CLSFitStateShell &state,const bool needxrep); - static void LSFitSetScale(CLSFitStateShell &state,double &s[]); - static void LSFitSetBC(CLSFitStateShell &state,double &bndl[],double &bndu[]); - static bool LSFitIteration(CLSFitStateShell &state); - static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_PGrad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_PGrad &grad,CNDimensional_PHess &hess,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void LSFitResults(CLSFitStateShell &state,int &info,double &c[],CLSFitReportShell &rep); - //--- parametric spline - static void PSpline2Build(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline2InterpolantShell &p); - static void PSpline3Build(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline3InterpolantShell &p); - static void PSpline2BuildPeriodic(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline2InterpolantShell &p); - static void PSpline3BuildPeriodic(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline3InterpolantShell &p); - static void PSpline2ParameterValues(CPSpline2InterpolantShell &p,int &n,double &t[]); - static void PSpline3ParameterValues(CPSpline3InterpolantShell &p,int &n,double &t[]); - static void PSpline2Calc(CPSpline2InterpolantShell &p,const double t,double &x,double &y); - static void PSpline3Calc(CPSpline3InterpolantShell &p,const double t,double &x,double &y,double &z); - static void PSpline2Tangent(CPSpline2InterpolantShell &p,const double t,double &x,double &y); - static void PSpline3Tangent(CPSpline3InterpolantShell &p,const double t,double &x,double &y,double &z); - static void PSpline2Diff(CPSpline2InterpolantShell &p,const double t,double &x,double &dx,double &y,double &dy); - static void PSpline3Diff(CPSpline3InterpolantShell &p,const double t,double &x,double &dx,double &y,double &dy,double &z,double &dz); - static void PSpline2Diff2(CPSpline2InterpolantShell &p,const double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y); - static void PSpline3Diff2(CPSpline3InterpolantShell &p,const double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y,double &z,double &dz,double &d2z); - static double PSpline2ArcLength(CPSpline2InterpolantShell &p,const double a,const double b); - static double PSpline3ArcLength(CPSpline3InterpolantShell &p,const double a,const double b); - //--- 2-dimensional spline interpolation - static void Spline2DBuildBilinear(double &x[],double &y[],CMatrixDouble &f,const int m,const int n,CSpline2DInterpolantShell &c); - static void Spline2DBuildBicubic(double &x[],double &y[],CMatrixDouble &f,const int m,const int n,CSpline2DInterpolantShell &c); - static double Spline2DCalc(CSpline2DInterpolantShell &c,const double x,const double y); - static void Spline2DDiff(CSpline2DInterpolantShell &c,const double x,const double y,double &f,double &fx,double &fy,double &fxy); - static void Spline2DUnpack(CSpline2DInterpolantShell &c,int &m,int &n,CMatrixDouble &tbl); - static void Spline2DLinTransXY(CSpline2DInterpolantShell &c,const double ax,const double bx,const double ay,const double by); - static void Spline2DLinTransF(CSpline2DInterpolantShell &c,const double a,const double b); - static void Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth); - static void Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth); - //--- function of package linalg - //--- working with matrix forms - static void CMatrixTranspose(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb); - static void RMatrixTranspose(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb); - static void CMatrixCopy(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb); - static void RMatrixCopy(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb); - static void CMatrixRank1(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,al_complex &u[],const int iu,al_complex &v[],const int iv); - static void RMatrixRank1(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,double &u[],const int iu,double &v[],const int iv); - static void CMatrixMVect(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,const int opa,al_complex &x[],const int ix,al_complex &y[],const int iy); - static void RMatrixMVect(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,const int opa,double &x[],const int ix,double &y[],const int iy); - static void CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixComplex &x,const int i2,const int j2); - static void CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixComplex &x,const int i2,const int j2); - static void RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixDouble &x,const int i2,const int j2); - static void RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixDouble &x,const int i2,const int j2); - static void CMatrixSyrk(const int n,const int k,const double alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,const double beta,CMatrixComplex &c,const int ic,const int jc,const bool isupper); - static void RMatrixSyrk(const int n,const int k,const double alpha,CMatrixDouble &a,const int ia,const int ja,const int optypea,const double beta,CMatrixDouble &c,const int ic,const int jc,const bool isupper); - static void CMatrixGemm(const int m,const int n,const int k,al_complex &alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,CMatrixComplex &b,const int ib,const int jb,const int optypeb,al_complex &beta,CMatrixComplex &c,const int ic,const int jc); - static void RMatrixGemm(const int m,const int n,const int k,const double alpha,CMatrixDouble &a,const int ia,const int ja,const int optypea,CMatrixDouble &b,const int ib,const int jb,const int optypeb,const double beta,CMatrixDouble &c,const int ic,const int jc); - //--- orthogonal factorizations - static void RMatrixQR(CMatrixDouble &a,const int m,const int n,double &tau[]); - static void RMatrixLQ(CMatrixDouble &a,const int m,const int n,double &tau[]); - static void CMatrixQR(CMatrixComplex &a,const int m,const int n,al_complex &tau[]); - static void CMatrixLQ(CMatrixComplex &a,const int m,const int n,al_complex &tau[]); - static void RMatrixQRUnpackQ(CMatrixDouble &a,const int m,const int n,double &tau[],const int qcolumns,CMatrixDouble &q); - static void RMatrixQRUnpackR(CMatrixDouble &a,const int m,const int n,CMatrixDouble &r); - static void RMatrixLQUnpackQ(CMatrixDouble &a,const int m,const int n,double &tau[],const int qrows,CMatrixDouble &q); - static void RMatrixLQUnpackL(CMatrixDouble &a,const int m,const int n,CMatrixDouble &l); - static void CMatrixQRUnpackQ(CMatrixComplex &a,const int m,const int n,al_complex &tau[],const int qcolumns,CMatrixComplex &q); - static void CMatrixQRUnpackR(CMatrixComplex &a,const int m,const int n,CMatrixComplex &r); - static void CMatrixLQUnpackQ(CMatrixComplex &a,const int m,const int n,al_complex &tau[],const int qrows,CMatrixComplex &q); - static void CMatrixLQUnpackL(CMatrixComplex &a,const int m,const int n,CMatrixComplex &l); - static void RMatrixBD(CMatrixDouble &a,const int m,const int n,double &tauq[],double &taup[]); - static void RMatrixBDUnpackQ(CMatrixDouble &qp,const int m,const int n,double &tauq[],const int qcolumns,CMatrixDouble &q); - static void RMatrixBDMultiplyByQ(CMatrixDouble &qp,const int m,const int n,double &tauq[],CMatrixDouble &z,const int zrows,const int zcolumns,const bool fromtheright,const bool dotranspose); - static void RMatrixBDUnpackPT(CMatrixDouble &qp,const int m,const int n,double &taup[],const int ptrows,CMatrixDouble &pt); - static void RMatrixBDMultiplyByP(CMatrixDouble &qp,const int m,const int n,double &taup[],CMatrixDouble &z,const int zrows,const int zcolumns,const bool fromtheright,const bool dotranspose); - static void RMatrixBDUnpackDiagonals(CMatrixDouble &b,const int m,const int n,bool &isupper,double &d[],double &e[]); - static void RMatrixHessenberg(CMatrixDouble &a,const int n,double &tau[]); - static void RMatrixHessenbergUnpackQ(CMatrixDouble &a,const int n,double &tau[],CMatrixDouble &q); - static void RMatrixHessenbergUnpackH(CMatrixDouble &a,const int n,CMatrixDouble &h); - static void SMatrixTD(CMatrixDouble &a,const int n,const bool isupper,double &tau[],double &d[],double &e[]); - static void SMatrixTDUnpackQ(CMatrixDouble &a,const int n,const bool isupper,double &tau[],CMatrixDouble &q); - static void HMatrixTD(CMatrixComplex &a,const int n,const bool isupper,al_complex &tau[],double &d[],double &e[]); - static void HMatrixTDUnpackQ(CMatrixComplex &a,const int n,const bool isupper,al_complex &tau[],CMatrixComplex &q); - //--- eigenvalues and eigenvectors - static bool SMatrixEVD(CMatrixDouble &a,const int n,int zneeded,const bool isupper,double &d[],CMatrixDouble &z); - static bool SMatrixEVDR(CMatrixDouble &a,const int n,int zneeded,const bool isupper,double b1,double b2,int &m,double &w[],CMatrixDouble &z); - static bool SMatrixEVDI(CMatrixDouble &a,const int n,int zneeded,const bool isupper,const int i1,const int i2,double &w[],CMatrixDouble &z); - static bool HMatrixEVD(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,double &d[],CMatrixComplex &z); - static bool HMatrixEVDR(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,double b1,double b2,int &m,double &w[],CMatrixComplex &z); - static bool HMatrixEVDI(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,const int i1,const int i2,double &w[],CMatrixComplex &z); - static bool SMatrixTdEVD(double &d[],double &e[],const int n,const int zneeded,CMatrixDouble &z); - static bool SMatrixTdEVDR(double &d[],double &e[],const int n,const int zneeded,const double a,const double b,int &m,CMatrixDouble &z); - static bool SMatrixTdEVDI(double &d[],double &e[],const int n,const int zneeded,const int i1,const int i2,CMatrixDouble &z); - static bool RMatrixEVD(CMatrixDouble &a,const int n,const int vneeded,double &wr[],double &wi[],CMatrixDouble &vl,CMatrixDouble &vr); - //--- random matrix generation - static void RMatrixRndOrthogonal(const int n,CMatrixDouble &a); - static void RMatrixRndCond(const int n,const double c,CMatrixDouble &a); - static void CMatrixRndOrthogonal(const int n,CMatrixComplex &a); - static void CMatrixRndCond(const int n,const double c,CMatrixComplex &a); - static void SMatrixRndCond(const int n,const double c,CMatrixDouble &a); - static void SPDMatrixRndCond(const int n,const double c,CMatrixDouble &a); - static void HMatrixRndCond(const int n,const double c,CMatrixComplex &a); - static void HPDMatrixRndCond(const int n,const double c,CMatrixComplex &a); - static void RMatrixRndOrthogonalFromTheRight(CMatrixDouble &a,const int m,const int n); - static void RMatrixRndOrthogonalFromTheLeft(CMatrixDouble &a,const int m,const int n); - static void CMatrixRndOrthogonalFromTheRight(CMatrixComplex &a,const int m,const int n); - static void CMatrixRndOrthogonalFromTheLeft(CMatrixComplex &a,const int m,const int n); - static void SMatrixRndMultiply(CMatrixDouble &a,const int n); - static void HMatrixRndMultiply(CMatrixComplex &a,const int n); - //--- triangular factorizations - static void RMatrixLU(CMatrixDouble &a,const int m,const int n,int &pivots[]); - static void CMatrixLU(CMatrixComplex &a,const int m,const int n,int &pivots[]); - static bool HPDMatrixCholesky(CMatrixComplex &a,const int n,const bool isupper); - static bool SPDMatrixCholesky(CMatrixDouble &a,const int n,const bool isupper); - //--- estimate of the condition numbers - static double RMatrixRCond1(CMatrixDouble &a,const int n); - static double RMatrixRCondInf(CMatrixDouble &a,const int n); - static double SPDMatrixRCond(CMatrixDouble &a,const int n,const bool isupper); - static double RMatrixTrRCond1(CMatrixDouble &a,const int n,const bool isupper,const bool isunit); - static double RMatrixTrRCondInf(CMatrixDouble &a,const int n,const bool isupper,const bool isunit); - static double HPDMatrixRCond(CMatrixComplex &a,const int n,const bool isupper); - static double CMatrixRCond1(CMatrixComplex &a,const int n); - static double CMatrixRCondInf(CMatrixComplex &a,const int n); - static double RMatrixLURCond1(CMatrixDouble &lua,const int n); - static double RMatrixLURCondInf(CMatrixDouble &lua,const int n); - static double SPDMatrixCholeskyRCond(CMatrixDouble &a,const int n,const bool isupper); - static double HPDMatrixCholeskyRCond(CMatrixComplex &a,const int n,const bool isupper); - static double CMatrixLURCond1(CMatrixComplex &lua,const int n); - static double CMatrixLURCondInf(CMatrixComplex &lua,const int n); - static double CMatrixTrRCond1(CMatrixComplex &a,const int n,const bool isupper,const bool isunit); - static double CMatrixTrRCondInf(CMatrixComplex &a,const int n,const bool isupper,const bool isunit); - //--- matrix inversion - static void RMatrixLUInverse(CMatrixDouble &a,int &pivots[],const int n,int &info,CMatInvReportShell &rep); - static void RMatrixLUInverse(CMatrixDouble &a,int &pivots[],int &info,CMatInvReportShell &rep); - static void RMatrixInverse(CMatrixDouble &a,const int n,int &info,CMatInvReportShell &rep); - static void RMatrixInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep); - static void CMatrixLUInverse(CMatrixComplex &a,int &pivots[],const int n,int &info,CMatInvReportShell &rep); - static void CMatrixLUInverse(CMatrixComplex &a,int &pivots[],int &info,CMatInvReportShell &rep); - static void CMatrixInverse(CMatrixComplex &a,const int n,int &info,CMatInvReportShell &rep); - static void CMatrixInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep); - static void SPDMatrixCholeskyInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep); - static void SPDMatrixCholeskyInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep); - static void SPDMatrixInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep); - static void SPDMatrixInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep); - static void HPDMatrixCholeskyInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep); - static void HPDMatrixCholeskyInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep); - static void HPDMatrixInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep); - static void HPDMatrixInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep); - static void RMatrixTrInverse(CMatrixDouble &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReportShell &rep); - static void RMatrixTrInverse(CMatrixDouble &a,const bool isupper,int &info,CMatInvReportShell &rep); - static void CMatrixTrInverse(CMatrixComplex &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReportShell &rep); - static void CMatrixTrInverse(CMatrixComplex &a,const bool isupper,int &info,CMatInvReportShell &rep); - //--- singular value decomposition of a bidiagonal matrix - static bool RMatrixBdSVD(double &d[],double &e[],const int n,const bool isupper,bool isfractionalaccuracyrequired,CMatrixDouble &u,const int nru,CMatrixDouble &c,const int ncc,CMatrixDouble &vt,const int ncvt); - //--- singular value decomposition - static bool RMatrixSVD(CMatrixDouble &a,const int m,const int n,const int uneeded,const int vtneeded,const int additionalmemory,double &w[],CMatrixDouble &u,CMatrixDouble &vt); - //--- calculation determinant of the matrix - static double RMatrixLUDet(CMatrixDouble &a,int &pivots[],const int n); - static double RMatrixLUDet(CMatrixDouble &a,int &pivots[]); - static double RMatrixDet(CMatrixDouble &a,const int n); - static double RMatrixDet(CMatrixDouble &a); - static al_complex CMatrixLUDet(CMatrixComplex &a,int &pivots[],const int n); - static al_complex CMatrixLUDet(CMatrixComplex &a,int &pivots[]); - static al_complex CMatrixDet(CMatrixComplex &a,const int n); - static al_complex CMatrixDet(CMatrixComplex &a); - static double SPDMatrixCholeskyDet(CMatrixDouble &a,const int n); - static double SPDMatrixCholeskyDet(CMatrixDouble &a); - static double SPDMatrixDet(CMatrixDouble &a,const int n,const bool isupper); - static double SPDMatrixDet(CMatrixDouble &a); - //--- generalized symmetric positive definite eigenproblem - static bool SMatrixGEVD(CMatrixDouble &a,const int n,const bool isuppera,CMatrixDouble &b,const bool isupperb,const int zneeded,const int problemtype,double &d[],CMatrixDouble &z); - static bool SMatrixGEVDReduce(CMatrixDouble &a,const int n,const bool isuppera,CMatrixDouble &b,const bool isupperb,const int problemtype,CMatrixDouble &r,bool &isupperr); - //--- update of the inverse matrix by the Sherman-Morrison formula - static void RMatrixInvUpdateSimple(CMatrixDouble &inva,const int n,const int updrow,const int updcolumn,const double updval); - static void RMatrixInvUpdateRow(CMatrixDouble &inva,const int n,const int updrow,double &v[]); - static void RMatrixInvUpdateColumn(CMatrixDouble &inva,const int n,const int updcolumn,double &u[]); - static void RMatrixInvUpdateUV(CMatrixDouble &inva,const int n,double &u[],double &v[]); - //--- Schur decomposition - static bool RMatrixSchur(CMatrixDouble &a,const int n,CMatrixDouble &s); - //--- function of package optimization - //--- conjugate gradient method - static void MinCGCreate(const int n,double &x[],CMinCGStateShell &state); - static void MinCGCreate(double &x[],CMinCGStateShell &state); - static void MinCGCreateF(const int n,double &x[],double diffstep,CMinCGStateShell &state); - static void MinCGCreateF(double &x[],double diffstep,CMinCGStateShell &state); - static void MinCGSetCond(CMinCGStateShell &state,double epsg,double epsf,double epsx,int maxits); - static void MinCGSetScale(CMinCGStateShell &state,double &s[]); - static void MinCGSetXRep(CMinCGStateShell &state,bool needxrep); - static void MinCGSetCGType(CMinCGStateShell &state,int cgtype); - static void MinCGSetStpMax(CMinCGStateShell &state,double stpmax); - static void MinCGSuggestStep(CMinCGStateShell &state,double stp); - static void MinCGSetPrecDefault(CMinCGStateShell &state); - static void MinCGSetPrecDiag(CMinCGStateShell &state,double &d[]); - static void MinCGSetPrecScale(CMinCGStateShell &state); - static bool MinCGIteration(CMinCGStateShell &state); - static void MinCGOptimize(CMinCGStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinCGOptimize(CMinCGStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinCGResults(CMinCGStateShell &state,double &x[],CMinCGReportShell &rep); - static void MinCGResultsBuf(CMinCGStateShell &state,double &x[],CMinCGReportShell &rep); - static void MinCGRestartFrom(CMinCGStateShell &state,double &x[]); - //--- bound constrained optimization with additional linear equality and inequality constraints - static void MinBLEICCreate(const int n,double &x[],CMinBLEICStateShell &state); - static void MinBLEICCreate(double &x[],CMinBLEICStateShell &state); - static void MinBLEICCreateF(const int n,double &x[],double diffstep,CMinBLEICStateShell &state); - static void MinBLEICCreateF(double &x[],double diffstep,CMinBLEICStateShell &state); - static void MinBLEICSetBC(CMinBLEICStateShell &state,double &bndl[],double &bndu[]); - static void MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,int &ct[],const int k); - static void MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,int &ct[]); - static void MinBLEICSetInnerCond(CMinBLEICStateShell &state,const double epsg,const double epsf,const double epsx); - static void MinBLEICSetOuterCond(CMinBLEICStateShell &state,const double epsx,const double epsi); - static void MinBLEICSetScale(CMinBLEICStateShell &state,double &s[]); - static void MinBLEICSetPrecDefault(CMinBLEICStateShell &state); - static void MinBLEICSetPrecDiag(CMinBLEICStateShell &state,double &d[]); - static void MinBLEICSetPrecScale(CMinBLEICStateShell &state); - static void MinBLEICSetMaxIts(CMinBLEICStateShell &state,const int maxits); - static void MinBLEICSetXRep(CMinBLEICStateShell &state,bool needxrep); - static void MinBLEICSetStpMax(CMinBLEICStateShell &state,double stpmax); - static bool MinBLEICIteration(CMinBLEICStateShell &state); - static void MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinBLEICResults(CMinBLEICStateShell &state,double &x[],CMinBLEICReportShell &rep); - static void MinBLEICResultsBuf(CMinBLEICStateShell &state,double &x[],CMinBLEICReportShell &rep); - static void MinBLEICRestartFrom(CMinBLEICStateShell &state,double &x[]); - //--- limited memory BFGS method for large scale optimization - static void MinLBFGSCreate(const int n,const int m,double &x[],CMinLBFGSStateShell &state); - static void MinLBFGSCreate(const int m,double &x[],CMinLBFGSStateShell &state); - static void MinLBFGSCreateF(const int n,const int m,double &x[],const double diffstep,CMinLBFGSStateShell &state); - static void MinLBFGSCreateF(const int m,double &x[],const double diffstep,CMinLBFGSStateShell &state); - static void MinLBFGSSetCond(CMinLBFGSStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits); - static void MinLBFGSSetXRep(CMinLBFGSStateShell &state,const bool needxrep); - static void MinLBFGSSetStpMax(CMinLBFGSStateShell &state,const double stpmax); - static void MinLBFGSSetScale(CMinLBFGSStateShell &state,double &s[]); - static void MinLBFGSSetPrecDefault(CMinLBFGSStateShell &state); - static void MinLBFGSSetPrecCholesky(CMinLBFGSStateShell &state,CMatrixDouble &p,const bool isupper); - static void MinLBFGSSetPrecDiag(CMinLBFGSStateShell &state,double &d[]); - static void MinLBFGSSetPrecScale(CMinLBFGSStateShell &state); - static bool MinLBFGSIteration(CMinLBFGSStateShell &state); - static void MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLBFGSResults(CMinLBFGSStateShell &state,double &x[],CMinLBFGSReportShell &rep); - static void MinLBFGSresultsbuf(CMinLBFGSStateShell &state,double &x[],CMinLBFGSReportShell &rep); - static void MinLBFGSRestartFrom(CMinLBFGSStateShell &state,double &x[]); - //--- constrained quadratic programming - static void MinQPCreate(const int n,CMinQPStateShell &state); - static void MinQPSetLinearTerm(CMinQPStateShell &state,double &b[]); - static void MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a,const bool isupper); - static void MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a); - static void MinQPSetStartingPoint(CMinQPStateShell &state,double &x[]); - static void MinQPSetOrigin(CMinQPStateShell &state,double &xorigin[]); - static void MinQPSetAlgoCholesky(CMinQPStateShell &state); - static void MinQPSetBC(CMinQPStateShell &state,double &bndl[],double &bndu[]); - static void MinQPOptimize(CMinQPStateShell &state); - static void MinQPResults(CMinQPStateShell &state,double &x[],CMinQPReportShell &rep); - static void MinQPResultsBuf(CMinQPStateShell &state,double &x[],CMinQPReportShell &rep); - //--- Levenberg-Marquardt method - static void MinLMCreateVJ(const int n,const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateVJ(const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateV(const int n,const int m,double &x[],double diffstep,CMinLMStateShell &state); - static void MinLMCreateV(const int m,double &x[],const double diffstep,CMinLMStateShell &state); - static void MinLMCreateFGH(const int n,double &x[],CMinLMStateShell &state); - static void MinLMCreateFGH(double &x[],CMinLMStateShell &state); - static void MinLMSetCond(CMinLMStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits); - static void MinLMSetXRep(CMinLMStateShell &state,const bool needxrep); - static void MinLMSetStpMax(CMinLMStateShell &state,const double stpmax); - static void MinLMSetScale(CMinLMStateShell &state,double &s[]); - static void MinLMSetBC(CMinLMStateShell &state,double &bndl[],double &bndu[]); - static void MinLMSetAccType(CMinLMStateShell &state,const int acctype); - static bool MinLMIteration(CMinLMStateShell &state); - static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Grad &grad,CNDimensional_Hess &hess,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Grad &grad,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinLMResults(CMinLMStateShell &state,double &x[],CMinLMReportShell &rep); - static void MinLMResultsBuf(CMinLMStateShell &state,double &x[],CMinLMReportShell &rep); - static void MinLMRestartFrom(CMinLMStateShell &state,double &x[]); - static void MinLMCreateVGJ(const int n,const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateVGJ(const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateFGJ(const int n,const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateFGJ(const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateFJ(const int n,const int m,double &x[],CMinLMStateShell &state); - static void MinLMCreateFJ(const int m,double &x[],CMinLMStateShell &state); - //--- optimization - static void MinLBFGSSetDefaultPreconditioner(CMinLBFGSStateShell &state); - static void MinLBFGSSetCholeskyPreconditioner(CMinLBFGSStateShell &state,CMatrixDouble &p,bool isupper); - static void MinBLEICSetBarrierWidth(CMinBLEICStateShell &state,const double mu); - static void MinBLEICSetBarrierDecay(CMinBLEICStateShell &state,const double mudecay); - static void MinASACreate(const int n,double &x[],double &bndl[],double &bndu[],CMinASAStateShell &state); - static void MinASACreate(double &x[],double &bndl[],double &bndu[],CMinASAStateShell &state); - static void MinASASetCond(CMinASAStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits); - static void MinASASetXRep(CMinASAStateShell &state,const bool needxrep); - static void MinASASetAlgorithm(CMinASAStateShell &state,const int algotype); - static void MinASASetStpMax(CMinASAStateShell &state,const double stpmax); - static bool MinASAIteration(CMinASAStateShell &state); - static void MinASAOptimize(CMinASAStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void MinASAResults(CMinASAStateShell &state,double &x[],CMinASAReportShell &rep); - static void MinASAResultsBuf(CMinASAStateShell &state,double &x[],CMinASAReportShell &rep); - static void MinASARestartFrom(CMinASAStateShell &state,double &x[],double &bndl[],double &bndu[]); - //--- function of package solvers - //--- dense solver - static void RMatrixSolve(CMatrixDouble &a,const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]); - static void RMatrixSolveM(CMatrixDouble &a,const int n,CMatrixDouble &b,const int m,const bool rfs,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x); - static void RMatrixLUSolve(CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]); - static void RMatrixLUSolveM(CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x); - static void RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]); - static void RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x); - static void CMatrixSolveM(CMatrixComplex &a,const int n,CMatrixComplex &b,const int m,const bool rfs,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x); - static void CMatrixSolve(CMatrixComplex &a,const int n,al_complex &b[],int &info,CDenseSolverReportShell &rep,al_complex &x[]); - static void CMatrixLUSolveM(CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x); - static void CMatrixLUSolve(CMatrixComplex &lua,int &p[],const int n,al_complex &b[],int &info,CDenseSolverReportShell &rep,al_complex &x[]); - static void CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x); - static void CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,al_complex &b[],int &info,CDenseSolverReportShell &rep,al_complex &x[]); - static void SPDMatrixSolveM(CMatrixDouble &a,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x); - static void SPDMatrixSolve(CMatrixDouble &a,const int n,const bool isupper,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]); - static void SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x); - static void SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n,const bool isupper,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]); - static void HPDMatrixSolveM(CMatrixComplex &a,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x); - static void HPDMatrixSolve(CMatrixComplex &a,const int n,const bool isupper,al_complex &b[],int &info,CDenseSolverReportShell &rep,al_complex &x[]); - static void HPDMatrixCholeskySolveM(CMatrixComplex &cha,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x); - static void HPDMatrixCholeskySolve(CMatrixComplex &cha,const int n,const bool isupper,al_complex &b[],int &info,CDenseSolverReportShell &rep,al_complex &x[]); - static void RMatrixSolveLS(CMatrixDouble &a,const int nrows,const int ncols,double &b[],const double threshold,int &info,CDenseSolverLSReportShell &rep,double &x[]); - //--- solving systems of nonlinear equations - static void NlEqCreateLM(const int n,const int m,double &x[],CNlEqStateShell &state); - static void NlEqCreateLM(const int m,double &x[],CNlEqStateShell &state); - static void NlEqSetCond(CNlEqStateShell &state,const double epsf,const int maxits); - static void NlEqSetXRep(CNlEqStateShell &state,const bool needxrep); - static void NlEqSetStpMax(CNlEqStateShell &state,const double stpmax); - static bool NlEqIteration(CNlEqStateShell &state); - static void NlEqSolve(CNlEqStateShell &state,CNDimensional_Func &func,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj); - static void NlEqResults(CNlEqStateShell &state,double &x[],CNlEqReportShell &rep); - static void NlEqResultsBuf(CNlEqStateShell &state,double &x[],CNlEqReportShell &rep); - static void NlEqRestartFrom(CNlEqStateShell &state,double &x[]); - //--- function of package specialfunctions - //--- gamma function - static double GammaFunction(const double x); - static double LnGamma(const double x,double &sgngam); - //--- normal distribution - static double ErrorFunction(const double x); - static double ErrorFunctionC(const double x); - static double NormalDistribution(const double x); - static double InvErF(double e); - static double InvNormalDistribution(const double y0); - //--- incomplete gamma function - static double IncompleteGamma(const double a,const double x); - static double IncompleteGammaC(const double a,const double x); - static double InvIncompleteGammaC(const double a,const double y0); - //--- airy function - static void Airy(const double x,double &ai,double &aip,double &bi,double &bip); - //--- Bessel function - static double BesselJ0(const double x); - static double BesselJ1(const double x); - static double BesselJN(const int n,const double x); - static double BesselY0(const double x); - static double BesselY1(const double x); - static double BesselYN(const int n,const double x); - static double BesselI0(const double x); - static double BesselI1(const double x); - static double BesselK0(const double x); - static double BesselK1(const double x); - static double BesselKN(const int nn,const double x); - //--- beta function - static double Beta(const double a,const double b); - static double IncompleteBeta(const double a,const double b,const double x); - static double InvIncompleteBeta(const double a,const double b,double y); - //--- binomial distribution - static double BinomialDistribution(const int k,const int n,const double p); - static double BinomialComplDistribution(const int k,const int n,const double p); - static double InvBinomialDistribution(const int k,const int n,const double y); - //--- Chebyshev polynom - static double ChebyshevCalculate(int r,const int n,const double x); - static double ChebyshevSum(double &c[],const int r,const int n,const double x); - static void ChebyshevCoefficients(const int n,double &c[]); - static void FromChebyshev(double &a[],const int n,double &b[]); - //--- chi-square distribution - static double ChiSquareDistribution(const double v,const double x); - static double ChiSquareComplDistribution(const double v,const double x); - static double InvChiSquareDistribution(const double v,const double y); - //--- Dawson's Integral - static double DawsonIntegral(const double x); - //--- elliptic integral - static double EllipticIntegralK(const double m); - static double EllipticIntegralKhighPrecision(const double m1); - static double IncompleteEllipticIntegralK(const double phi,const double m); - static double EllipticIntegralE(const double m); - static double IncompleteEllipticIntegralE(const double phi,const double m); - //--- exponential integral - static double ExponentialIntegralEi(const double x); - static double ExponentialIntegralEn(const double x,const int n); - //--- F distribution functions - static double FDistribution(const int a,const int b,const double x); - static double FComplDistribution(const int a,const int b,const double x); - static double InvFDistribution(const int a,const int b,const double y); - //--- Fresnel integral - static void FresnelIntegral(const double x,double &c,double &s); - //--- Hermite polynomial - static double HermiteCalculate(const int n,const double x); - static double HermiteSum(double &c[],const int n,const double x); - static void HermiteCoefficients(const int n,double &c[]); - //--- Jacobian elliptic functions - static void JacobianEllipticFunctions(const double u,const double m,double &sn,double &cn,double &dn,double &ph); - //--- Laguerre polynomial - static double LaguerreCalculate(const int n,const double x); - static double LaguerreSum(double &c[],const int n,const double x); - static void LaguerreCoefficients(const int n,double &c[]); - //--- Legendre polynomial - static double LegendreCalculate(const int n,const double x); - static double LegendreSum(double &c[],const int n,const double x); - static void LegendreCoefficients(const int n,double &c[]); - //--- Poisson distribution - static double PoissonDistribution(const int k,const double m); - static double PoissonComplDistribution(const int k,const double m); - static double InvPoissonDistribution(const int k,const double y); - //--- psi function - static double Psi(const double x); - //--- Student's t distribution - static double StudenttDistribution(const int k,const double t); - static double InvStudenttDistribution(const int k,const double p); - //--- trigonometric integrals - static void SineCosineIntegrals(const double x,double &si,double &ci); - static void HyperbolicSineCosineIntegrals(const double x,double &shi,double &chi); - //--- function of package statistics - //--- basic statistics methods - static void SampleMoments(const double &x[],const int n,double &mean,double &variance,double &skewness,double &kurtosis); - static void SampleMoments(const double &x[],double &mean,double &variance,double &skewness,double &kurtosis); - static void SampleAdev(const double &x[],const int n,double &adev); - static void SampleAdev(const double &x[],double &adev); - static void SampleMedian(const double &x[],const int n,double &median); - static void SampleMedian(const double &x[],double &median); - static void SamplePercentile(const double &x[],const int n,const double p,double &v); - static void SamplePercentile(const double &x[],const double p,double &v); - static double Cov2(const double &x[],const double &y[],const int n); - static double Cov2(const double &x[],const double &y[]); - static double PearsonCorr2(const double &x[],const double &y[],const int n); - static double PearsonCorr2(const double &x[],const double &y[]); - static double SpearmanCorr2(const double &x[],const double &y[],const int n); - static double SpearmanCorr2(const double &x[],const double &y[]); - static void CovM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c); - static void CovM(const CMatrixDouble &x,CMatrixDouble &c); - static void PearsonCorrM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c); - static void PearsonCorrM(CMatrixDouble &x,CMatrixDouble &c); - static void SpearmanCorrM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c); - static void SpearmanCorrM(const CMatrixDouble &x,CMatrixDouble &c); - static void CovM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c); - static void CovM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c); - static void PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c); - static void PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c); - static void SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c); - static void SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c); - //--- correlation tests - static void PearsonCorrelationSignificance(const double r,const int n,double &bothTails,double &leftTail,double &rightTail); - static void SpearmanRankCorrelationSignificance(const double r,const int n,double &bothTails,double &leftTail,double &rightTail); - //--- Jarque-Bera test - static void JarqueBeraTest(const double &x[],const int n,double &p); - //--- Mann-Whitney U-test - static void MannWhitneyUTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - //--- sign test - static void OneSampleSignTest(const double &x[],const int n,const double median,double &bothTails,double &leftTail,double &rightTail); - //--- Studentt Tests - static void StudentTest1(const double &x[],const int n,const double mean,double &bothTails,double &leftTail,double &rightTail); - static void StudentTest2(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - static void UnequalVarianceTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - //--- variance tests - static void FTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - static void OneSampleVarianceTest(double &x[],int n,double variance,double &bothTails,double &leftTail,double &rightTail); - //--- Wilcoxon signed-rank test - static void WilcoxonSignedRankTest(const double &x[],const int n,const double e,double &bothTails,double &leftTail,double &rightTail); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CAlglib::CAlglib(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CAlglib::~CAlglib(void) - { - - } -//+------------------------------------------------------------------+ -//| HQRNDState initialization with random values which come from | -//| standard RNG. | -//+------------------------------------------------------------------+ -static void CAlglib::HQRndRandomize(CHighQualityRandStateShell &state) - { -//--- function call - CHighQualityRand::HQRndRandomize(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| HQRNDState initialization with seed values | -//+------------------------------------------------------------------+ -static void CAlglib::HQRndSeed(const int s1,const int s2,CHighQualityRandStateShell &state) - { -//--- function call - CHighQualityRand::HQRndSeed(s1,s2,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function generates random real number in (0,1), | -//| not including interval boundaries | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static double CAlglib::HQRndUniformR(CHighQualityRandStateShell &state) - { -//--- return result - return(CHighQualityRand::HQRndUniformR(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This function generates random integer number in [0, N) | -//| 1. N must be less than HQRNDMax-1. | -//| 2. State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed() | -//+------------------------------------------------------------------+ -static int CAlglib::HQRndUniformI(CHighQualityRandStateShell &state,const int n) - { -//--- return result - return(CHighQualityRand::HQRndUniformI(state.GetInnerObj(),n)); - } -//+------------------------------------------------------------------+ -//| Random number generator: normal numbers | -//| This function generates one random number from normal | -//| distribution. | -//| Its performance is equal to that of HQRNDNormal2() | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static double CAlglib::HQRndNormal(CHighQualityRandStateShell &state) - { -//--- return result - return(CHighQualityRand::HQRndNormal(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| Random number generator: random X and Y such that X^2+Y^2=1 | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static void CAlglib::HQRndUnit2(CHighQualityRandStateShell &state, - double &x,double &y) - { -//--- initialization - x=0; - y=0; -//--- function call - CHighQualityRand::HQRndUnit2(state.GetInnerObj(),x,y); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Random number generator: normal numbers | -//| This function generates two independent random numbers from | -//| normal distribution. Its performance is equal to that of | -//| HQRNDNormal() | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static void CAlglib::HQRndNormal2(CHighQualityRandStateShell &state, - double &x1,double &x2) - { -//--- initialization - x1=0; - x2=0; -//--- function call - CHighQualityRand::HQRndNormal2(state.GetInnerObj(),x1,x2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Random number generator: exponential distribution | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static double CAlglib::HQRndExponential(CHighQualityRandStateShell &state, - const double lambdav) - { -//--- return result - return(CHighQualityRand::HQRndExponential(state.GetInnerObj(),lambdav)); - } -//+------------------------------------------------------------------+ -//| This function serializes data structure to string. | -//| Important properties of s_out: | -//| * it contains alphanumeric characters, dots, underscores, minus | -//| signs | -//| * these symbols are grouped into words, which are separated by | -//| spaces and Windows-style (CR+LF) newlines | -//| * although serializer uses spaces and CR+LF as separators, you | -//| can replace any separator character by arbitrary combination | -//| of spaces, tabs, Windows or Unix newlines. It allows flexible | -//| reformatting of the string in case you want to include it into | -//| text or XML file. But you should not insert separators into the| -//| middle of the "words" nor you should change case of letters. | -//| * s_out can be freely moved between 32-bit and 64-bit systems, | -//| little and big endian machines, and so on. You can serialize | -//| structure on 32-bit machine and unserialize it on 64-bit one | -//| (or vice versa), or serialize it on SPARC and unserialize on | -//| x86. You can also serialize it in C# version of ALGLIB and | -//| unserialize in C++ one, and vice versa. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeSerialize(CKDTreeShell &obj,string &s_out) - { -//--- object of class - CSerializer s; - s.Alloc_Start(); -//--- function call - CNearestNeighbor::KDTreeAlloc(s,obj.GetInnerObj()); - s.SStart_Str(); -//--- function call - CNearestNeighbor::KDTreeSerialize(s,obj.GetInnerObj()); - s.Stop(); -//--- get result - s_out=s.Get_String(); - } -//+------------------------------------------------------------------+ -//| This function unserializes data structure from string. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeUnserialize(string s_in,CKDTreeShell &obj) - { -//--- object of class - CSerializer s; - s.UStart_Str(s_in); -//--- function call - CNearestNeighbor::KDTreeUnserialize(s,obj.GetInnerObj()); - s.Stop(); - } -//+------------------------------------------------------------------+ -//| KD-tree creation | -//| This subroutine creates KD-tree from set of X-values and optional| -//| Y-values | -//| INPUT PARAMETERS | -//| XY - dataset, array[0..N-1,0..NX+NY-1]. | -//| one row corresponds to one point. | -//| first NX columns contain X-values, next NY (NY | -//| may be zero) | -//| columns may contain associated Y-values | -//| N - number of points, N>=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because | -//| simple binary search (without additional structures) is | -//| much more efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeBuild(CMatrixDouble &xy,const int n,const int nx, - const int ny,const int normtype,CKDTreeShell &kdt) - { -//--- function call - CNearestNeighbor::KDTreeBuild(xy,n,nx,ny,normtype,kdt.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| KD-tree creation | -//| This subroutine creates KD-tree from set of X-values and optional| -//| Y-values | -//| INPUT PARAMETERS | -//| XY - dataset, array[0..N-1,0..NX+NY-1]. | -//| one row corresponds to one point. | -//| first NX columns contain X-values, next NY (NY | -//| may be zero) | -//| columns may contain associated Y-values | -//| N - number of points, N>=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because | -//| simple binary search (without additional structures) is | -//| much more efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeBuild(CMatrixDouble &xy,const int nx,const int ny, - const int normtype,CKDTreeShell &kdt) - { -//--- create a variable - int n=CAp::Rows(xy); -//--- function call - CNearestNeighbor::KDTreeBuild(xy,n,nx,ny,normtype,kdt.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| KD-tree creation | -//| This subroutine creates KD-tree from set of X-values, integer | -//| tags and optional Y-values | -//| INPUT PARAMETERS | -//| XY - dataset, array[0..N-1,0..NX+NY-1]. | -//| one row corresponds to one point. | -//| first NX columns contain X-values, next NY (NY | -//| may be zero) | -//| columns may contain associated Y-values | -//| Tags - tags, array[0..N-1], contains integer tags | -//| associated with points. | -//| N - number of points, N>=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because simple| -//| binary search (without additional structures) is much more | -//| efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeBuildTagged(CMatrixDouble &xy,int &tags[], - const int n,const int nx, - const int ny,const int normtype, - CKDTreeShell &kdt) - { -//--- function call - CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,ny,normtype,kdt.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| KD-tree creation | -//| This subroutine creates KD-tree from set of X-values, integer | -//| tags and optional Y-values | -//| INPUT PARAMETERS | -//| XY - dataset, array[0..N-1,0..NX+NY-1]. | -//| one row corresponds to one point. | -//| first NX columns contain X-values, next NY (NY | -//| may be zero) | -//| columns may contain associated Y-values | -//| Tags - tags, array[0..N-1], contains integer tags | -//| associated with points. | -//| N - number of points, N>=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because simple| -//| binary search (without additional structures) is much more | -//| efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeBuildTagged(CMatrixDouble &xy,int &tags[], - const int nx,const int ny, - const int normtype,CKDTreeShell &kdt) - { -//--- create a variable - int n; - if((CAp::Rows(xy)!=CAp::Len(tags))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - n=CAp::Rows(xy); -//--- function call - CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,ny,normtype,kdt.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| K-NN query: K nearest neighbors | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| K - number of neighbors to return, K>=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain these results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryKNN(CKDTreeShell &kdt,double &x[], - const int k,const bool selfmatch) - { -//--- return result - return(CNearestNeighbor::KDTreeQueryKNN(kdt.GetInnerObj(),x,k,selfmatch)); - } -//+------------------------------------------------------------------+ -//| K-NN query: K nearest neighbors | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| K - number of neighbors to return, K>=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain these results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k) - { -//--- create a variable - bool selfmatch=true; -//--- return result - return(CNearestNeighbor::KDTreeQueryKNN(kdt.GetInnerObj(),x,k,selfmatch)); - } -//+------------------------------------------------------------------+ -//| R-NN query: all points within R-sphere centered at X | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| R - radius of sphere (in corresponding norm), R>0| -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of neighbors found, >=0 | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain actual results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryRNN(CKDTreeShell &kdt,double &x[], - const double r,const bool selfmatch) - { -//--- return result - return(CNearestNeighbor::KDTreeQueryRNN(kdt.GetInnerObj(),x,r,selfmatch)); - } -//+------------------------------------------------------------------+ -//| R-NN query: all points within R-sphere centered at X | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| R - radius of sphere (in corresponding norm), R>0| -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of neighbors found, >=0 | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain actual results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r) - { -//--- create a variable - bool selfmatch=true; -//--- return result - return(CNearestNeighbor::KDTreeQueryRNN(kdt.GetInnerObj(),x,r,selfmatch)); - } -//+------------------------------------------------------------------+ -//| K-NN query: approximate K nearest neighbors | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| K - number of neighbors to return, K>=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| Eps - approximation factor, Eps>=0. eps-approximate| -//| nearest neighbor is a neighbor whose distance| -//| from X is at most (1+eps) times distance of | -//| true nearest neighbor. | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| NOTES | -//| significant performance gain may be achieved only when Eps is| -//| on the order of magnitude of 1 or larger. | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| these subroutines to obtain results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[], - const int k,const bool selfmatch, - const double eps) - { -//--- return result - return(CNearestNeighbor::KDTreeQueryAKNN(kdt.GetInnerObj(),x,k,selfmatch,eps)); - } -//+------------------------------------------------------------------+ -//| K-NN query: approximate K nearest neighbors | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| K - number of neighbors to return, K>=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| Eps - approximation factor, Eps>=0. eps-approximate| -//| nearest neighbor is a neighbor whose distance| -//| from X is at most (1+eps) times distance of | -//| true nearest neighbor. | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| NOTES | -//| significant performance gain may be achieved only when Eps is| -//| on the order of magnitude of 1 or larger. | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| these subroutines to obtain results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CAlglib::KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[], - const int k,const double eps) - { -//--- create a variable - bool selfmatch=true; -//--- return result - return(CNearestNeighbor::KDTreeQueryAKNN(kdt.GetInnerObj(),x,k,selfmatch,eps)); - } -//+------------------------------------------------------------------+ -//| X-values from last query | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - possibly pre-allocated buffer. If X is too small | -//| to store result, it is resized. If size(X) is | -//| enough to store result, it is left unchanged. | -//| OUTPUT PARAMETERS | -//| X - rows are filled with X-values | -//| NOTES | -//| 1. points are ordered by distance from the query point (first = | -//| closest) | -//| 2. if XY is larger than required to store result, only leading | -//| part will be overwritten; trailing part will be left | -//| unchanged. So if on input XY = [[A,B],[C,D]], and result is | -//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is | -//| done purposely to increase performance; if you want function | -//| to resize array according to result size, use function with | -//| same name and suffix 'I'. | -//| SEE ALSO | -//| * KDTreeQueryResultsXY() X- and Y-values | -//| * KDTreeQueryResultsTags() tag values | -//| * KDTreeQueryResultsDistances() distances | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsX(CKDTreeShell &kdt,CMatrixDouble &x) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsX(kdt.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| X- and Y-values from last query | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| XY - possibly pre-allocated buffer. If XY is too small| -//| to store result, it is resized. If size(XY) is | -//| enough to store result, it is left unchanged. | -//| OUTPUT PARAMETERS | -//| XY - rows are filled with points: first NX columns | -//| with X-values, next NY columns - with Y-values. | -//| NOTES | -//| 1. points are ordered by distance from the query point (first = | -//| closest) | -//| 2. if XY is larger than required to store result, only leading | -//| part will be overwritten; trailing part will be left | -//| unchanged. So if on input XY = [[A,B],[C,D]], and result is | -//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is | -//| done purposely to increase performance; if you want function | -//| to resize array according to result size, use function with | -//| same name and suffix 'I'. | -//| SEE ALSO | -//| * KDTreeQueryResultsX() X-values | -//| * KDTreeQueryResultsTags() tag values | -//| * KDTreeQueryResultsDistances() distances | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsXY(CKDTreeShell &kdt,CMatrixDouble &xy) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsXY(kdt.GetInnerObj(),xy); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Tags from last query | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| Tags - possibly pre-allocated buffer. If X is too small | -//| to store result, it is resized. If size(X) is | -//| enough to store result, it is left unchanged. | -//| OUTPUT PARAMETERS | -//| Tags - filled with tags associated with points, | -//| or, when no tags were supplied, with zeros | -//| NOTES | -//| 1. points are ordered by distance from the query point (first | -//| = closest) | -//| 2. if XY is larger than required to store result, only leading | -//| part will be overwritten; trailing part will be left | -//| unchanged. So if on input XY = [[A,B],[C,D]], and result is | -//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is | -//| done purposely to increase performance; if you want function | -//| to resize array according to result size, use function with | -//| same name and suffix 'I'. | -//| SEE ALSO | -//| * KDTreeQueryResultsX() X-values | -//| * KDTreeQueryResultsXY() X- and Y-values | -//| * KDTreeQueryResultsDistances() distances | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsTags(CKDTreeShell &kdt,int &tags[]) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsTags(kdt.GetInnerObj(),tags); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Distances from last query | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| R - possibly pre-allocated buffer. If X is too small | -//| to store result, it is resized. If size(X) is | -//| enough to store result, it is left unchanged. | -//| OUTPUT PARAMETERS | -//| R - filled with distances (in corresponding norm) | -//| NOTES | -//| 1. points are ordered by distance from the query point (first | -//| = closest) | -//| 2. if XY is larger than required to store result, only leading | -//| part will be overwritten; trailing part will be left | -//| unchanged. So if on input XY = [[A,B],[C,D]], and result is | -//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is | -//| done purposely to increase performance; if you want function | -//| to resize array according to result size, use function with | -//| same name and suffix 'I'. | -//| SEE ALSO | -//| * KDTreeQueryResultsX() X-values | -//| * KDTreeQueryResultsXY() X- and Y-values | -//| * KDTreeQueryResultsTags() tag values | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsDistances(CKDTreeShell &kdt,double &r[]) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsDistances(kdt.GetInnerObj(),r); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| X-values from last query; 'interactive' variant for languages | -//| like Python which support constructs like "X = | -//| KDTreeQueryResultsXI(KDT)" and interactive mode of interpreter. | -//| This function allocates new array on each call, so it is | -//| significantly slower than its 'non-interactive' counterpart, but | -//| it is more convenient when you call it from command line. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsXI(CKDTreeShell &kdt,CMatrixDouble &x) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsXI(kdt.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| XY-values from last query; 'interactive' variant for languages | -//| like Python which support constructs like "XY = | -//| KDTreeQueryResultsXYI(KDT)" and interactive mode of interpreter. | -//| This function allocates new array on each call, so it is | -//| significantly slower than its 'non-interactive' counterpart, but | -//| it is more convenient when you call it from command line. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsXYI(CKDTreeShell &kdt,CMatrixDouble &xy) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsXYI(kdt.GetInnerObj(),xy); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Tags from last query; 'interactive' variant for languages like | -//| Python which support constructs like "Tags = | -//| KDTreeQueryResultsTagsI(KDT)" and interactive mode of | -//| interpreter. | -//| This function allocates new array on each call, so it is | -//| significantly slower than its 'non-interactive' counterpart, but | -//| it is more convenient when you call it from command line. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsTagsI(CKDTreeShell &kdt,int &tags[]) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsTagsI(kdt.GetInnerObj(),tags); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Distances from last query; 'interactive' variant for languages | -//| like Python which support constructs like "R = | -//| KDTreeQueryResultsDistancesI(KDT)" and interactive mode of | -//| interpreter. | -//| This function allocates new array on each call, so it is | -//| significantly slower than its 'non-interactive' counterpart, but | -//| it is more convenient when you call it from command line. | -//+------------------------------------------------------------------+ -static void CAlglib::KDTreeQueryResultsDistancesI(CKDTreeShell &kdt,double &r[]) - { -//--- function call - CNearestNeighbor::KDTreeQueryResultsDistancesI(kdt.GetInnerObj(),r); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Optimal binary classification | -//| Algorithms finds optimal (=with minimal cross-entropy) binary | -//| partition. | -//| Internal subroutine. | -//| INPUT PARAMETERS: | -//| A - array[0..N-1], variable | -//| C - array[0..N-1], class numbers (0 or 1). | -//| N - array size | -//| OUTPUT PARAMETERS: | -//| Info - completetion code: | -//| * -3, all values of A[] are same (partition is | -//| impossible) | -//| * -2, one of C[] is incorrect (<0, >1) | -//| * -1, incorrect pararemets were passed (N<=0). | -//| * 1, OK | -//| Threshold- partiton boundary. Left part contains values | -//| which are strictly less than Threshold. Right | -//| part contains values which are greater than or | -//| equal to Threshold. | -//| PAL, PBL- probabilities P(0|v=Threshold) and | -//| P(1|v>=Threshold) | -//| CVE - cross-validation estimate of cross-entropy | -//+------------------------------------------------------------------+ -static void CAlglib::DSOptimalSplit2(double &a[],int &c[],const int n, - int &info,double &threshold, - double &pal,double &pbl,double &par, - double &pbr,double &cve) - { -//--- initialization - info=0; - threshold=0; - pal=0; - pbl=0; - par=0; - pbr=0; - cve=0; -//--- function call - CBdSS::DSOptimalSplit2(a,c,n,info,threshold,pal,pbl,par,pbr,cve); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Optimal partition, internal subroutine. Fast version. | -//| Accepts: | -//| A array[0..N-1] array of attributes array[0..N-1]| -//| C array[0..N-1] array of class labels | -//| TiesBuf array[0..N] temporaries (ties) | -//| CntBuf array[0..2*NC-1] temporaries (counts) | -//| Alpha centering factor (0<=alpha<=1, | -//| recommended value - 0.05) | -//| BufR array[0..N-1] temporaries | -//| BufI array[0..N-1] temporaries | -//| Output: | -//| Info error code (">0"=OK, "<0"=bad) | -//| RMS training set RMS error | -//| CVRMS leave-one-out RMS error | -//| Note: | -//| content of all arrays is changed by subroutine; | -//| it doesn't allocate temporaries. | -//+------------------------------------------------------------------+ -static void CAlglib::DSOptimalSplit2Fast(double &a[],int &c[],int &tiesbuf[], - int &cntbuf[],double &bufr[], - int &bufi[],const int n, - const int nc,const double alpha, - int &info,double &threshold, - double &rms,double &cvrms) - { -//--- initialization - info=0; - threshold=0; - rms=0; - cvrms=0; -//--- function call - CBdSS::DSOptimalSplit2Fast(a,c,tiesbuf,cntbuf,bufr,bufi,n,nc,alpha,info,threshold,rms,cvrms); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function serializes data structure to string. | -//| Important properties of s_out: | -//| * it contains alphanumeric characters, dots, underscores, minus | -//| signs | -//| * these symbols are grouped into words, which are separated by | -//| spaces and Windows-style (CR+LF) newlines | -//| * although serializer uses spaces and CR+LF as separators, you| -//| can replace any separator character by arbitrary combination of| -//| spaces, tabs, Windows or Unix newlines. It allows flexible | -//| reformatting of the string in case you want to include it into | -//| text or XML file. But you should not insert separators into the| -//| middle of the "words" nor you should change case of letters. | -//| * s_out can be freely moved between 32-bit and 64-bit systems, | -//| little and big endian machines, and so on. You can serialize | -//| structure on 32-bit machine and unserialize it on 64-bit one | -//| (or vice versa), or serialize it on SPARC and unserialize on | -//| x86. You can also serialize it in C# version of ALGLIB and | -//| unserialize in C++ one, and vice versa. | -//+------------------------------------------------------------------+ -static void CAlglib::DFSerialize(CDecisionForestShell &obj,string &s_out) - { -//--- create a variable - CSerializer s; -//--- serialization start - s.Alloc_Start(); -//--- function call - CDForest::DFAlloc(s,obj.GetInnerObj()); -//--- serialization - s.SStart_Str(); -//--- function call - CDForest::DFSerialize(s,obj.GetInnerObj()); -//--- stop - s.Stop(); -//--- change value - s_out=s.Get_String(); - } -//+------------------------------------------------------------------+ -//| This function unserializes data structure from string. | -//+------------------------------------------------------------------+ -static void CAlglib::DFUnserialize(const string s_in,CDecisionForestShell &obj) - { -//--- create a variable - CSerializer s; -//--- unserialization - s.UStart_Str(s_in); -//--- function call - CDForest::DFUnserialize(s,obj.GetInnerObj()); -//--- stop - s.Stop(); - } -//+------------------------------------------------------------------+ -//| This subroutine builds random decision forest. | -//| INPUT PARAMETERS: | -//| XY - training set | -//| NPoints - training set size, NPoints>=1 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - task type: | -//| * NClasses=1 - regression task with one | -//| dependent variable | -//| * NClasses>1 - classification task with | -//| NClasses classes. | -//| NTrees - number of trees in a forest, NTrees>=1. | -//| recommended values: 50-100. | -//| R - percent of a training set used to build | -//| individual trees. 01). | -//| * 1, if task has been solved | -//| DF - model built | -//| Rep - training report, contains error on a training| -//| set and out-of-bag estimates of | -//| generalization error. | -//+------------------------------------------------------------------+ -static void CAlglib::DFBuildRandomDecisionForest(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - const int ntrees,const double r, - int &info,CDecisionForestShell &df, - CDFReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CDForest::DFBuildRandomDecisionForest(xy,npoints,nvars,nclasses,ntrees,r,info,df.GetInnerObj(),rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine builds random decision forest. | -//| This function gives ability to tune number of variables used when| -//| choosing best split. | -//| INPUT PARAMETERS: | -//| XY - training set | -//| NPoints - training set size, NPoints>=1 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - task type: | -//| * NClasses=1 - regression task with one | -//| dependent variable | -//| * NClasses>1 - classification task with | -//| NClasses classes. | -//| NTrees - number of trees in a forest, NTrees>=1. | -//| recommended values: 50-100. | -//| NRndVars - number of variables used when choosing best | -//| split | -//| R - percent of a training set used to build | -//| individual trees. 01). | -//| * 1, if task has been solved | -//| DF - model built | -//| Rep - training report, contains error on a training| -//| set and out-of-bag estimates of | -//| generalization error. | -//+------------------------------------------------------------------+ -static void CAlglib::DFBuildRandomDecisionForestX1(CMatrixDouble &xy, - const int npoints, - const int nvars, - const int nclasses, - const int ntrees, - int nrndvars, - const double r, - int &info, - CDecisionForestShell &df, - CDFReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CDForest::DFBuildRandomDecisionForestX1(xy,npoints,nvars,nclasses,ntrees,nrndvars,r,info,df.GetInnerObj(),rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| X - input vector, array[0..NVars-1]. | -//| OUTPUT PARAMETERS: | -//| Y - result. Regression estimate when solving | -//| regression task, vector of posterior | -//| probabilities for classification task. | -//| See also DFProcessI. | -//+------------------------------------------------------------------+ -static void CAlglib::DFProcess(CDecisionForestShell &df,double &x[], - double &y[]) - { -//--- function call - CDForest::DFProcess(df.GetInnerObj(),x,y); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| 'interactive' variant of DFProcess for languages like Python | -//| which support constructs like "Y = DFProcessI(DF,X)" and | -//| interactive mode of interpreter | -//| This function allocates new array on each call, so it is | -//| significantly slower than its 'non-interactive' counterpart, but | -//| it is more convenient when you call it from command line. | -//+------------------------------------------------------------------+ -static void CAlglib::DFProcessI(CDecisionForestShell &df, - double &x[],double &y[]) - { -//--- function call - CDForest::DFProcessI(df.GetInnerObj(),x,y); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Relative classification error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| percent of incorrectly classified cases. | -//| Zero if model solves regression task. | -//+------------------------------------------------------------------+ -static double CAlglib::DFRelClsError(CDecisionForestShell &df,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return(CDForest::DFRelClsError(df.GetInnerObj(),xy,npoints)); - } -//+------------------------------------------------------------------+ -//| Average cross-entropy (in bits per element) on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| CrossEntropy/(NPoints*LN(2)). | -//| Zero if model solves regression task. | -//+------------------------------------------------------------------+ -static double CAlglib::DFAvgCE(CDecisionForestShell &df,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return(CDForest::DFAvgCE(df.GetInnerObj(),xy,npoints)); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| root mean square error. | -//| Its meaning for regression task is obvious. As for | -//| classification task,RMS error means error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CAlglib::DFRMSError(CDecisionForestShell &df,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return(CDForest::DFRMSError(df.GetInnerObj(),xy,npoints)); - } -//+------------------------------------------------------------------+ -//| Average error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task, it means average error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CAlglib::DFAvgError(CDecisionForestShell &df,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return(CDForest::DFAvgError(df.GetInnerObj(),xy,npoints)); - } -//+------------------------------------------------------------------+ -//| Average relative error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task, it means average relative error when | -//| estimating posterior probability of belonging to the correct | -//| class. | -//+------------------------------------------------------------------+ -static double CAlglib::DFAvgRelError(CDecisionForestShell &df,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return(CDForest::DFAvgRelError(df.GetInnerObj(),xy,npoints)); - } -//+------------------------------------------------------------------+ -//| k-means++ clusterization | -//| INPUT PARAMETERS: | -//| XY - dataset, array [0..NPoints-1,0..NVars-1]. | -//| NPoints - dataset size, NPoints>=K | -//| NVars - number of variables, NVars>=1 | -//| K - desired number of clusters, K>=1 | -//| Restarts - number of restarts, Restarts>=1 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -3, if task is degenerate (number of | -//| distinct points is less than K) | -//| * -1, if incorrect | -//| NPoints/NFeatures/K/Restarts was passed| -//| * 1, if subroutine finished successfully | -//| C - array[0..NVars-1,0..K-1].matrix whose columns| -//| store cluster's centers | -//| XYC - array[NPoints], which contains cluster | -//| indexes | -//+------------------------------------------------------------------+ -static void CAlglib::KMeansGenerate(CMatrixDouble &xy,const int npoints, - const int nvars,const int k, - const int restarts,int &info, - CMatrixDouble &c,int &xyc[]) - { -//--- initialization - info=0; -//--- function call - CKMeans::KMeansGenerate(xy,npoints,nvars,k,restarts,info,c,xyc); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiclass Fisher LDA | -//| Subroutine finds coefficients of linear combination which | -//| optimally separates training set on classes. | -//| INPUT PARAMETERS: | -//| XY - training set, array[0..NPoints-1,0..NVars]. | -//| First NVars columns store values of | -//| independent variables, next column stores | -//| number of class (from 0 to NClasses-1) which | -//| dataset element belongs to. Fractional values| -//| are rounded to nearest integer. | -//| NPoints - training set size, NPoints>=0 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - number of classes, NClasses>=2 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -4, if internal EVD subroutine hasn't | -//| converged | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, NVars<1, NClasses<2) | -//| * 1, if task has been solved | -//| * 2, if there was a multicollinearity in | -//| training set, but task has been solved.| -//| W - linear combination coefficients, | -//| array[0..NVars-1] | -//+------------------------------------------------------------------+ -static void CAlglib::FisherLDA(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - int &info,double &w[]) - { -//--- initialization - info=0; -//--- function call - CLDA::FisherLDA(xy,npoints,nvars,nclasses,info,w); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| N-dimensional multiclass Fisher LDA | -//| Subroutine finds coefficients of linear combinations which | -//| optimally separates | -//| training set on classes. It returns N-dimensional basis whose | -//| vector are sorted | -//| by quality of training set separation (in descending order). | -//| INPUT PARAMETERS: | -//| XY - training set, array[0..NPoints-1,0..NVars]. | -//| First NVars columns store values of | -//| independent variables, next column stores | -//| number of class (from 0 to NClasses-1) which | -//| dataset element belongs to. Fractional values| -//| are rounded to nearest integer. | -//| NPoints - training set size, NPoints>=0 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - number of classes, NClasses>=2 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -4, if internal EVD subroutine hasn't | -//| converged | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, NVars<1, NClasses<2) | -//| * 1, if task has been solved | -//| * 2, if there was a multicollinearity in | -//| training set, but task has been solved.| -//| W - basis, array[0..NVars-1,0..NVars-1] | -//| columns of matrix stores basis vectors, | -//| sorted by quality of training set separation | -//| (in descending order) | -//+------------------------------------------------------------------+ -static void CAlglib::FisherLDAN(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - int &info,CMatrixDouble &w) - { -//--- initialization - info=0; -//--- function call - CLDA::FisherLDAN(xy,npoints,nvars,nclasses,info,w); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Linear regression | -//| Subroutine builds model: | -//| Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) | -//| and model found in ALGLIB format, covariation matrix, training | -//| set errors (rms, average, average relative) and leave-one-out | -//| cross-validation estimate of the generalization error. CV | -//| estimate calculated using fast algorithm with O(NPoints*NVars) | -//| complexity. | -//| When covariation matrix is calculated standard deviations of| -//| function values are assumed to be equal to RMS error on the | -//| training set. | -//| INPUT PARAMETERS: | -//| XY - training set, array [0..NPoints-1,0..NVars]: | -//| * NVars columns - independent variables | -//| * last column - dependent variable | -//| NPoints - training set size, NPoints>NVars+1 | -//| NVars - number of independent variables | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -255, in case of unknown internal error | -//| * -4, if internal SVD subroutine haven't | -//| converged | -//| * -1, if incorrect parameters was passed | -//| (NPoints0. | -//| NPoints - training set size, NPoints>NVars+1 | -//| NVars - number of independent variables | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -255, in case of unknown internal error | -//| * -4, if internal SVD subroutine haven't | -//| converged | -//| * -1, if incorrect parameters was passed | -//| (NPointsA will result in positive length returned | -//| * B=2, N>=2 | -//| Output parameters: | -//| C - spline interpolant | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DBuildBilinear(double &x[],double &y[], - CMatrixDouble &f,const int m, - const int n,CSpline2DInterpolantShell &c) - { -//--- function call - CSpline2D::Spline2DBuildBilinear(x,y,f,m,n,c.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine builds bicubic spline coefficients table. | -//| Input parameters: | -//| X - spline abscissas, array[0..N-1] | -//| Y - spline ordinates, array[0..M-1] | -//| F - function values, array[0..M-1,0..N-1] | -//| M,N - grid size, M>=2, N>=2 | -//| Output parameters: | -//| C - spline interpolant | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DBuildBicubic(double &x[],double &y[],CMatrixDouble &f, - const int m,const int n, - CSpline2DInterpolantShell &c) - { -//--- function call - CSpline2D::Spline2DBuildBicubic(x,y,f,m,n,c.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates the value of the bilinear or bicubic | -//| spline at the given point X. | -//| Input parameters: | -//| C - coefficients table. | -//| Built by BuildBilinearSpline or BuildBicubicSpline. | -//| X, Y- point | -//| Result: | -//| S(x,y) | -//+------------------------------------------------------------------+ -static double CAlglib::Spline2DCalc(CSpline2DInterpolantShell &c, - const double x,const double y) - { -//--- return result - return(CSpline2D::Spline2DCalc(c.GetInnerObj(),x,y)); - } -//+------------------------------------------------------------------+ -//| This subroutine calculates the value of the bilinear or bicubic | -//| spline at the given point X and its derivatives. | -//| Input parameters: | -//| C - spline interpolant. | -//| X, Y- point | -//| Output parameters: | -//| F - S(x,y) | -//| FX - dS(x,y)/dX | -//| FY - dS(x,y)/dY | -//| FXY - d2S(x,y)/dXdY | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DDiff(CSpline2DInterpolantShell &c,const double x, - const double y,double &f,double &fx, - double &fy,double &fxy) - { -//--- initialization - f=0; - fx=0; - fy=0; - fxy=0; -//--- function call - CSpline2D::Spline2DDiff(c.GetInnerObj(),x,y,f,fx,fy,fxy); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine unpacks two-dimensional spline into the | -//| coefficients table | -//| Input parameters: | -//| C - spline interpolant. | -//| Result: | -//| M, N- grid size (x-axis and y-axis) | -//| Tbl - coefficients table, unpacked format, | -//| [0..(N-1)*(M-1)-1, 0..19]. | -//| For I = 0...M-2, J=0..N-2: | -//| K = I*(N-1)+J | -//| Tbl[K,0] = X[j] | -//| Tbl[K,1] = X[j+1] | -//| Tbl[K,2] = Y[i] | -//| Tbl[K,3] = Y[i+1] | -//| Tbl[K,4] = C00 | -//| Tbl[K,5] = C01 | -//| Tbl[K,6] = C02 | -//| Tbl[K,7] = C03 | -//| Tbl[K,8] = C10 | -//| Tbl[K,9] = C11 | -//| ... | -//| Tbl[K,19] = C33 | -//| On each grid square spline is equals to: | -//| S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3) | -//| t = x-x[j] | -//| u = y-y[i] | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DUnpack(CSpline2DInterpolantShell &c,int &m, - int &n,CMatrixDouble &tbl) - { -//--- initialization - m=0; - n=0; -//--- function call - CSpline2D::Spline2DUnpack(c.GetInnerObj(),m,n,tbl); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline | -//| argument. | -//| Input parameters: | -//| C - spline interpolant | -//| AX, BX - transformation coefficients: x = A*t + B | -//| AY, BY - transformation coefficients: y = A*u + B | -//| Result: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DLinTransXY(CSpline2DInterpolantShell &c, - const double ax,const double bx, - const double ay,const double by) - { -//--- function call - CSpline2D::Spline2DLinTransXY(c.GetInnerObj(),ax,bx,ay,by); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline. | -//| Input parameters: | -//| C - spline interpolant. | -//| A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B | -//| Output parameters: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DLinTransF(CSpline2DInterpolantShell &c, - const double a,const double b) - { -//--- function call - CSpline2D::Spline2DLinTransF(c.GetInnerObj(),a,b); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Bicubic spline resampling | -//| Input parameters: | -//| A - function values at the old grid, | -//| array[0..OldHeight-1, 0..OldWidth-1] | -//| OldHeight - old grid height, OldHeight>1 | -//| OldWidth - old grid width, OldWidth>1 | -//| NewHeight - new grid height, NewHeight>1 | -//| NewWidth - new grid width, NewWidth>1 | -//| Output parameters: | -//| B - function values at the new grid, | -//| array[0..NewHeight-1, 0..NewWidth-1] | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight, - const int oldwidth,CMatrixDouble &b, - const int newheight,const int newwidth) - { -//--- function call - CSpline2D::Spline2DResampleBicubic(a,oldheight,oldwidth,b,newheight,newwidth); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Bilinear spline resampling | -//| Input parameters: | -//| A - function values at the old grid, | -//| array[0..OldHeight-1, 0..OldWidth-1] | -//| OldHeight - old grid height, OldHeight>1 | -//| OldWidth - old grid width, OldWidth>1 | -//| NewHeight - new grid height, NewHeight>1 | -//| NewWidth - new grid width, NewWidth>1 | -//| Output parameters: | -//| B - function values at the new grid, | -//| array[0..NewHeight-1, 0..NewWidth-1] | -//+------------------------------------------------------------------+ -static void CAlglib::Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight, - const int oldwidth,CMatrixDouble &b, - const int newheight,const int newwidth) - { -//--- function call - CSpline2D::Spline2DResampleBilinear(a,oldheight,oldwidth,b,newheight,newwidth); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Cache-oblivous complex "copy-and-transpose" | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| A - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixTranspose(const int m,const int n,CMatrixComplex &a, - const int ia,const int ja,CMatrixComplex &b, - const int ib,const int jb) - { -//--- function call - CAblas::CMatrixTranspose(m,n,a,ia,ja,b,ib,jb); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Cache-oblivous real "copy-and-transpose" | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| A - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixTranspose(const int m,const int n,CMatrixDouble &a, - const int ia,const int ja,CMatrixDouble &b, - const int ib,const int jb) - { -//--- function call - CAblas::RMatrixTranspose(m,n,a,ia,ja,b,ib,jb); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Copy | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| B - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixCopy(const int m,const int n,CMatrixComplex &a, - const int ia,const int ja,CMatrixComplex &b, - const int ib,const int jb) - { -//--- function call - CAblas::CMatrixCopy(m,n,a,ia,ja,b,ib,jb); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Copy | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| B - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixCopy(const int m,const int n,CMatrixDouble &a, - const int ia,const int ja,CMatrixDouble &b, - const int ib,const int jb) - { -//--- function call - CAblas::RMatrixCopy(m,n,a,ia,ja,b,ib,jb); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Rank-1 correction: A := A + u*v' | -//| INPUT PARAMETERS: | -//| M - number of rows | -//| N - number of columns | -//| A - target matrix, MxN submatrix is updated | -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| U - vector #1 | -//| IU - subvector offset | -//| V - vector #2 | -//| IV - subvector offset | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRank1(const int m,const int n,CMatrixComplex &a, - const int ia,const int ja,al_complex &u[], - const int iu,al_complex &v[],const int iv) - { -//--- function call - CAblas::CMatrixRank1(m,n,a,ia,ja,u,iu,v,iv); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Rank-1 correction: A := A + u*v' | -//| INPUT PARAMETERS: | -//| M - number of rows | -//| N - number of columns | -//| A - target matrix, MxN submatrix is updated | -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| U - vector #1 | -//| IU - subvector offset | -//| V - vector #2 | -//| IV - subvector offset | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRank1(const int m,const int n,CMatrixDouble &a, - const int ia,const int ja,double &u[], - const int iu,double &v[],const int iv) - { -//--- function call - CAblas::RMatrixRank1(m,n,a,ia,ja,u,iu,v,iv); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Matrix-vector product: y := op(A)*x | -//| INPUT PARAMETERS: | -//| M - number of rows of op(A) | -//| M>=0 | -//| N - number of columns of op(A) | -//| N>=0 | -//| A - target matrix | -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| OpA - operation type: | -//| * OpA=0 => op(A) = A | -//| * OpA=1 => op(A) = A^T | -//| * OpA=2 => op(A) = A^H | -//| X - input vector | -//| IX - subvector offset | -//| IY - subvector offset | -//| OUTPUT PARAMETERS: | -//| Y - vector which stores result | -//| if M=0, then subroutine does nothing. | -//| if N=0, Y is filled by zeros. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixMVect(const int m,const int n,CMatrixComplex &a, - const int ia,const int ja,const int opa, - al_complex &x[],const int ix,al_complex &y[], - const int iy) - { -//--- function call - CAblas::CMatrixMVect(m,n,a,ia,ja,opa,x,ix,y,iy); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Matrix-vector product: y := op(A)*x | -//| INPUT PARAMETERS: | -//| M - number of rows of op(A) | -//| N - number of columns of op(A) | -//| A - target matrix | -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| OpA - operation type: | -//| * OpA=0 => op(A) = A | -//| * OpA=1 => op(A) = A^T | -//| X - input vector | -//| IX - subvector offset | -//| IY - subvector offset | -//| OUTPUT PARAMETERS: | -//| Y - vector which stores result | -//| if M=0, then subroutine does nothing. | -//| if N=0, Y is filled by zeros. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixMVect(const int m,const int n,CMatrixDouble &a, - const int ia,const int ja,const int opa, - double &x[],const int ix,double &y[], - const int iy) - { -//--- function call - CAblas::RMatrixMVect(m,n,a,ia,ja,opa,x,ix,y,iy); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates X*op(A^-1) where: | -//| * X is MxN general matrix | -//| * A is NxN upper/lower triangular/unitriangular matrix | -//| * "op" may be identity transformation, transposition, conjugate | -//| transposition | -//| Multiplication result replaces X. | -//| Cache-oblivious algorithm is used. | -//| INPUT PARAMETERS | -//| N - matrix size, N>=0 | -//| M - matrix size, N>=0 | -//| A - matrix, actial matrix is stored in | -//| A[I1:I1+N-1,J1:J1+N-1] | -//| I1 - submatrix offset | -//| J1 - submatrix offset | -//| IsUpper - whether matrix is upper triangular | -//| IsUnit - whether matrix is unitriangular | -//| OpType - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| C - matrix, actial matrix is stored in | -//| C[I2:I2+M-1,J2:J2+N-1] | -//| I2 - submatrix offset | -//| J2 - submatrix offset | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a, - const int i1,const int j1,const bool isupper, - const bool isunit,const int optype, - CMatrixComplex &x,const int i2,const int j2) - { -//--- function call - CAblas::CMatrixRightTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates op(A^-1)*X where: | -//| * X is MxN general matrix | -//| * A is MxM upper/lower triangular/unitriangular matrix | -//| * "op" may be identity transformation, transposition, conjugate | -//| transposition | -//| Multiplication result replaces X. | -//| Cache-oblivious algorithm is used. | -//| INPUT PARAMETERS | -//| N - matrix size, N>=0 | -//| M - matrix size, N>=0 | -//| A - matrix, actial matrix is stored in | -//| A[I1:I1+M-1,J1:J1+M-1] | -//| I1 - submatrix offset | -//| J1 - submatrix offset | -//| IsUpper - whether matrix is upper triangular | -//| IsUnit - whether matrix is unitriangular | -//| OpType - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| C - matrix, actial matrix is stored in | -//| C[I2:I2+M-1,J2:J2+N-1] | -//| I2 - submatrix offset | -//| J2 - submatrix offset | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a, - const int i1,const int j1,const bool isupper, - const bool isunit,const int optype, - CMatrixComplex &x,const int i2,const int j2) - { -//--- function call - CAblas::CMatrixLeftTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixRightTRSM, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a, - const int i1,const int j1,const bool isupper, - const bool isunit,const int optype, - CMatrixDouble &x,const int i2,const int j2) - { -//--- function call - CAblas::RMatrixRightTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixLeftTRSM, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a, - const int i1,const int j1,const bool isupper, - const bool isunit,const int optype, - CMatrixDouble &x,const int i2,const int j2) - { -//--- function call - CAblas::RMatrixLeftTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates C=alpha*A*A^H+beta*C or | -//| C=alpha*A^H*A+beta*C where: | -//| * C is NxN Hermitian matrix given by its upper/lower triangle | -//| * A is NxK matrix when A*A^H is calculated, KxN matrix otherwise | -//| Additional info: | -//| * cache-oblivious algorithm is used. | -//| * multiplication result replaces C. If Beta=0, C elements are not| -//| used in calculations (not multiplied by zero - just not | -//| referenced) | -//| * if Alpha=0, A is not used (not multiplied by zero - just not | -//| referenced) | -//| * if both Beta and Alpha are zero, C is filled by zeros. | -//| INPUT PARAMETERS | -//| N - matrix size, N>=0 | -//| K - matrix size, K>=0 | -//| Alpha - coefficient | -//| A - matrix | -//| IA - submatrix offset | -//| JA - submatrix offset | -//| OpTypeA - multiplication type: | -//| * 0 - A*A^H is calculated | -//| * 2 - A^H*A is calculated | -//| Beta - coefficient | -//| C - matrix | -//| IC - submatrix offset | -//| JC - submatrix offset | -//| IsUpper - whether C is upper triangular or lower triangular| -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixSyrk(const int n,const int k,const double alpha, - CMatrixComplex &a,const int ia,const int ja, - const int optypea,const double beta,CMatrixComplex &c, - const int ic,const int jc,const bool isupper) - { -//--- function call - CAblas::CMatrixSyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixSYRK, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixSyrk(const int n,const int k,const double alpha, - CMatrixDouble &a,const int ia,const int ja, - const int optypea,const double beta, - CMatrixDouble &c,const int ic, - const int jc,const bool isupper) - { -//--- function call - CAblas::RMatrixSyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:| -//| * C is MxN general matrix | -//| * op1(A) is MxK matrix | -//| * op2(B) is KxN matrix | -//| * "op" may be identity transformation, transposition, conjugate | -//| transposition | -//| Additional info: | -//| * cache-oblivious algorithm is used. | -//| * multiplication result replaces C. If Beta=0, C elements are not| -//| used in calculations (not multiplied by zero - just not | -//| referenced) | -//| * if Alpha=0, A is not used (not multiplied by zero - just not | -//| referenced) | -//| * if both Beta and Alpha are zero, C is filled by zeros. | -//| INPUT PARAMETERS | -//| N - matrix size, N>0 | -//| M - matrix size, N>0 | -//| K - matrix size, K>0 | -//| Alpha - coefficient | -//| A - matrix | -//| IA - submatrix offset | -//| JA - submatrix offset | -//| OpTypeA - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| B - matrix | -//| IB - submatrix offset | -//| JB - submatrix offset | -//| OpTypeB - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| Beta - coefficient | -//| C - matrix | -//| IC - submatrix offset | -//| JC - submatrix offset | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixGemm(const int m,const int n,const int k, - al_complex &alpha,CMatrixComplex &a, - const int ia,const int ja,const int optypea, - CMatrixComplex &b,const int ib,const int jb, - const int optypeb,al_complex &beta,CMatrixComplex &c, - const int ic,const int jc) - { -//--- function call - CAblas::CMatrixGemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixGEMM, but for real numbers. | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixGemm(const int m,const int n,const int k, - const double alpha,CMatrixDouble &a, - const int ia,const int ja,const int optypea, - CMatrixDouble &b,const int ib,const int jb, - const int optypeb,const double beta, - CMatrixDouble &c,const int ic,const int jc) - { -//--- function call - CAblas::RMatrixGemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| QR decomposition of a rectangular matrix of size MxN | -//| Input parameters: | -//| A - matrix A whose indexes range within [0..M-1, 0..N-1].| -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| Output parameters: | -//| A - matrices Q and R in compact form (see below). | -//| Tau - array of scalar factors which are used to form | -//| matrix Q. Array whose index ranges within | -//| [0.. Min(M-1,N-1)]. | -//| Matrix A is represented as A = QR, where Q is an orthogonal | -//| matrix of size MxM, R - upper triangular (or upper trapezoid) | -//| matrix of size M x N. | -//| The elements of matrix R are located on and above the main | -//| diagonal of matrix A. The elements which are located in Tau | -//| array and below the main diagonal of matrix A are used to form | -//| matrix Q as follows: | -//| Matrix Q is represented as a product of elementary reflections | -//| Q = H(0)*H(2)*...*H(k-1), | -//| where k = min(m,n), and each H(i) is in the form | -//| H(i) = 1 - tau * v * (v^T) | -//| where tau is a scalar stored in Tau[I]; v - real vector, | -//| so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in | -//| A(i+1:m-1,i). | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixQR(CMatrixDouble &a,const int m,const int n, - double &tau[]) - { -//--- function call - COrtFac::RMatrixQR(a,m,n,tau); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LQ decomposition of a rectangular matrix of size MxN | -//| Input parameters: | -//| A - matrix A whose indexes range within [0..M-1, 0..N-1].| -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| Output parameters: | -//| A - matrices L and Q in compact form (see below) | -//| Tau - array of scalar factors which are used to form | -//| matrix Q. Array whose index ranges within | -//| [0..Min(M,N)-1]. | -//| Matrix A is represented as A = LQ, where Q is an orthogonal | -//| matrix of size MxM, L - lower triangular (or lower trapezoid) | -//| matrix of size M x N. | -//| The elements of matrix L are located on and below the main | -//| diagonal of matrix A. The elements which are located in Tau | -//| array and above the main diagonal of matrix A are used to form | -//| matrix Q as follows: | -//| Matrix Q is represented as a product of elementary reflections | -//| Q = H(k-1)*H(k-2)*...*H(1)*H(0), | -//| where k = min(m,n), and each H(i) is of the form | -//| H(i) = 1 - tau * v * (v^T) | -//| where tau is a scalar stored in Tau[I]; v - real vector, so that | -//| v(0:i-1)=0, v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLQ(CMatrixDouble &a,const int m,const int n, - double &tau[]) - { -//--- function call - COrtFac::RMatrixLQ(a,m,n,tau); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| QR decomposition of a rectangular complex matrix of size MxN | -//| Input parameters: | -//| A - matrix A whose indexes range within [0..M-1, 0..N-1] | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| Output parameters: | -//| A - matrices Q and R in compact form | -//| Tau - array of scalar factors which are used to form | -//| matrix Q. Array whose indexes range within | -//| [0.. Min(M,N)-1] | -//| Matrix A is represented as A = QR, where Q is an orthogonal | -//| matrix of size MxM, R - upper triangular (or upper trapezoid) | -//| matrix of size MxN. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixQR(CMatrixComplex &a,const int m,const int n, - al_complex &tau[]) - { -//--- function call - COrtFac::CMatrixQR(a,m,n,tau); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LQ decomposition of a rectangular complex matrix of size MxN | -//| Input parameters: | -//| A - matrix A whose indexes range within [0..M-1, 0..N-1] | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| Output parameters: | -//| A - matrices Q and L in compact form | -//| Tau - array of scalar factors which are used to form | -//| matrix Q. Array whose indexes range within | -//| [0.. Min(M,N)-1] | -//| Matrix A is represented as A = LQ, where Q is an orthogonal | -//| matrix of size MxM, L - lower triangular (or lower trapezoid) | -//| matrix of size MxN. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLQ(CMatrixComplex &a,const int m,const int n, - al_complex &tau[]) - { -//--- function call - COrtFac::CMatrixLQ(a,m,n,tau); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Partial unpacking of matrix Q from the QR decomposition of a | -//| matrix A | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of RMatrixQR subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of the RMatrixQR subroutine. | -//| QColumns - required number of columns of matrix Q. | -//| M>=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array whose indexes range within | -//| [0..M-1, 0..QColumns-1]. | -//| If QColumns=0, the array remains unchanged. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixQRUnpackQ(CMatrixDouble &a,const int m,const int n, - double &tau[],const int qcolumns, - CMatrixDouble &q) - { -//--- function call - COrtFac::RMatrixQRUnpackQ(a,m,n,tau,qcolumns,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix R from the QR decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of RMatrixQR subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| R - matrix R, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixQRUnpackR(CMatrixDouble &a,const int m, - const int n,CMatrixDouble &r) - { -//--- function call - COrtFac::RMatrixQRUnpackR(a,m,n,r); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Partial unpacking of matrix Q from LQ decomposition of a complex | -//| matrix A. | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of CMatrixLQ subroutine. | -//| M - number of rows in matrix A. M>=0. | -//| N - number of columns in matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of CMatrixLQ subroutine . | -//| QRows - required number of rows in matrix Q. | -//| N>=QColumns>=0. | -//| Output parameters: | -//| Q - first QRows rows of matrix Q. | -//| Array whose index ranges within [0..QRows-1, | -//| 0..N-1]. | -//| If QRows=0, array isn't changed. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLQUnpackQ(CMatrixDouble &a,const int m,const int n, - double &tau[],const int qrows, - CMatrixDouble &q) - { -//--- function call - COrtFac::RMatrixLQUnpackQ(a,m,n,tau,qrows,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix L from the LQ decomposition of a matrix A | -//| Input parameters: | -//| A -matrices Q and L in compact form. | -//| Output of RMatrixLQ subroutine. | -//| M -number of rows in given matrix A. M>=0. | -//| N -number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| L -matrix L, array[0..M-1,0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLQUnpackL(CMatrixDouble &a,const int m, - const int n,CMatrixDouble &l) - { -//--- function call - COrtFac::RMatrixLQUnpackL(a,m,n,l); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Partial unpacking of matrix Q from QR decomposition of a complex | -//| matrix A. | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of CMatrixQR subroutine . | -//| M - number of rows in matrix A. M>=0. | -//| N - number of columns in matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of CMatrixQR subroutine . | -//| QColumns - required number of columns in matrix Q. | -//| M>=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array whose index ranges within [0..M-1, | -//| 0..QColumns-1]. | -//| If QColumns=0, array isn't changed. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixQRUnpackQ(CMatrixComplex &a,const int m, - const int n,al_complex &tau[], - const int qcolumns,CMatrixComplex &q) - { -//--- function call - COrtFac::CMatrixQRUnpackQ(a,m,n,tau,qcolumns,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix R from the QR decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of CMatrixQR subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| R - matrix R, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixQRUnpackR(CMatrixComplex &a,const int m, - const int n,CMatrixComplex &r) - { -//--- function call - COrtFac::CMatrixQRUnpackR(a,m,n,r); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Partial unpacking of matrix Q from LQ decomposition of a complex | -//| matrix A. | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of CMatrixLQ subroutine. | -//| M - number of rows in matrix A. M>=0. | -//| N - number of columns in matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of CMatrixLQ subroutine . | -//| QRows - required number of rows in matrix Q. | -//| N>=QColumns>=0. | -//| Output parameters: | -//| Q - first QRows rows of matrix Q. | -//| Array whose index ranges within [0..QRows-1, | -//| 0..N-1]. | -//| If QRows=0, array isn't changed. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLQUnpackQ(CMatrixComplex &a,const int m, - const int n,al_complex &tau[], - const int qrows,CMatrixComplex &q) - { -//--- function call - COrtFac::CMatrixLQUnpackQ(a,m,n,tau,qrows,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix L from the LQ decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and L in compact form. | -//| Output of CMatrixLQ subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| L - matrix L, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLQUnpackL(CMatrixComplex &a,const int m, - const int n,CMatrixComplex &l) - { -//--- function call - COrtFac::CMatrixLQUnpackL(a,m,n,l); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Reduction of a rectangular matrix to bidiagonal form | -//| The algorithm reduces the rectangular matrix A to bidiagonal | -//| form by orthogonal transformations P and Q: A = Q*B*P. | -//| Input parameters: | -//| A - source matrix. array[0..M-1, 0..N-1] | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| Output parameters: | -//| A - matrices Q, B, P in compact form (see below). | -//| TauQ - scalar factors which are used to form matrix Q. | -//| TauP - scalar factors which are used to form matrix P. | -//| The main diagonal and one of the secondary diagonals of matrix A | -//| are replaced with bidiagonal matrix B. Other elements contain | -//| elementary reflections which form MxM matrix Q and NxN matrix P, | -//| respectively. | -//| If M>=N, B is the upper bidiagonal MxN matrix and is stored in | -//| the corresponding elements of matrix A. Matrix Q is represented | -//| as a product of elementary reflections Q = H(0)*H(1)*...*H(n-1), | -//| where H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in | -//| TauQ[i], and vector v has the following structure: v(0:i-1)=0, | -//| v(i)=1, v(i+1:m-1) is stored in elements A(i+1:m-1,i).Matrix P is| -//| as follows: P = G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. | -//| Tau is stored in TauP[i], u(0:i)=0, u(i+1)=1, u(i+2:n-1) is | -//| stored in elements A(i,i+2:n-1). | -//| If M n): m=5, n=6 (m < n): | -//| ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) | -//| ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) | -//| ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) | -//| ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) | -//| ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) | -//| ( v1 v2 v3 v4 v5 ) | -//| Here vi and ui are vectors which form H(i) and G(i), and d and | -//| e - are the diagonal and off-diagonal elements of matrix B. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBD(CMatrixDouble &a,const int m,const int n, - double &tauq[],double &taup[]) - { -//--- function call - COrtFac::RMatrixBD(a,m,n,tauq,taup); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix Q which reduces a matrix to bidiagonal form. | -//| Input parameters: | -//| QP - matrices Q and P in compact form. | -//| Output of ToBidiagonal subroutine. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| TAUQ - scalar factors which are used to form Q. | -//| Output of ToBidiagonal subroutine. | -//| QColumns - required number of columns in matrix Q. | -//| M>=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array[0..M-1, 0..QColumns-1] | -//| If QColumns=0, the array is not modified. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBDUnpackQ(CMatrixDouble &qp,const int m, - const int n,double &tauq[], - const int qcolumns,CMatrixDouble &q) - { -//--- function call - COrtFac::RMatrixBDUnpackQ(qp,m,n,tauq,qcolumns,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication by matrix Q which reduces matrix A to bidiagonal | -//| form. | -//| The algorithm allows pre- or post-multiply by Q or Q'. | -//| Input parameters: | -//| QP - matrices Q and P in compact form. | -//| Output of ToBidiagonal subroutine. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| TAUQ - scalar factors which are used to form Q. | -//| Output of ToBidiagonal subroutine. | -//| Z - multiplied matrix. | -//| array[0..ZRows-1,0..ZColumns-1] | -//| ZRows - number of rows in matrix Z. If FromTheRight= | -//| =False, ZRows=M, otherwise ZRows can be | -//| arbitrary. | -//| ZColumns - number of columns in matrix Z. If | -//| FromTheRight=True, ZColumns=M, otherwise | -//| ZColumns can be arbitrary. | -//| FromTheRight - pre- or post-multiply. | -//| DoTranspose - multiply by Q or Q'. | -//| Output parameters: | -//| Z - product of Z and Q. | -//| Array[0..ZRows-1,0..ZColumns-1] | -//| If ZRows=0 or ZColumns=0, the array is not | -//| modified. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBDMultiplyByQ(CMatrixDouble &qp,const int m, - const int n,double &tauq[], - CMatrixDouble &z,const int zrows, - const int zcolumns,const bool fromtheright, - const bool dotranspose) - { -//--- function call - COrtFac::RMatrixBDMultiplyByQ(qp,m,n,tauq,z,zrows,zcolumns,fromtheright,dotranspose); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix P which reduces matrix A to bidiagonal form. | -//| The subroutine returns transposed matrix P. | -//| Input parameters: | -//| QP - matrices Q and P in compact form. | -//| Output of ToBidiagonal subroutine. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| TAUP - scalar factors which are used to form P. | -//| Output of ToBidiagonal subroutine. | -//| PTRows - required number of rows of matrix P^T. | -//| N >= PTRows >= 0. | -//| Output parameters: | -//| PT - first PTRows columns of matrix P^T | -//| Array[0..PTRows-1, 0..N-1] | -//| If PTRows=0, the array is not modified. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBDUnpackPT(CMatrixDouble &qp,const int m, - const int n,double &taup[], - const int ptrows,CMatrixDouble &pt) - { -//--- function call - COrtFac::RMatrixBDUnpackPT(qp,m,n,taup,ptrows,pt); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication by matrix P which reduces matrix A to bidiagonal | -//| form. | -//| The algorithm allows pre- or post-multiply by P or P'. | -//| Input parameters: | -//| QP - matrices Q and P in compact form. | -//| Output of RMatrixBD subroutine. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| TAUP - scalar factors which are used to form P. | -//| Output of RMatrixBD subroutine. | -//| Z - multiplied matrix. | -//| Array whose indexes range within | -//| [0..ZRows-1,0..ZColumns-1]. | -//| ZRows - number of rows in matrix Z. If | -//| FromTheRight=False, ZRows=N, otherwise ZRows | -//| can be arbitrary. | -//| ZColumns - number of columns in matrix Z. If | -//| FromTheRight=True, ZColumns=N, otherwise | -//| ZColumns can be arbitrary. | -//| FromTheRight - pre- or post-multiply. | -//| DoTranspose - multiply by P or P'. | -//| Output parameters: | -//| Z - product of Z and P. | -//| Array whose indexes range within | -//| [0..ZRows-1,0..ZColumns-1]. If ZRows=0 or | -//| ZColumns=0, the array is not modified. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBDMultiplyByP(CMatrixDouble &qp,const int m, - const int n,double &taup[], - CMatrixDouble &z,const int zrows, - const int zcolumns,const bool fromtheright, - const bool dotranspose) - { -//--- function call - COrtFac::RMatrixBDMultiplyByP(qp,m,n,taup,z,zrows,zcolumns,fromtheright,dotranspose); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking of the main and secondary diagonals of bidiagonal | -//| decomposition of matrix A. | -//| Input parameters: | -//| B - output of RMatrixBD subroutine. | -//| M - number of rows in matrix B. | -//| N - number of columns in matrix B. | -//| Output parameters: | -//| IsUpper - True, if the matrix is upper bidiagonal. | -//| otherwise IsUpper is False. | -//| D - the main diagonal. | -//| Array whose index ranges within [0..Min(M,N)-1]. | -//| E - the secondary diagonal (upper or lower, depending| -//| on the value of IsUpper). | -//| Array index ranges within [0..Min(M,N)-1], the | -//| last element is not used. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixBDUnpackDiagonals(CMatrixDouble &b,const int m, - const int n,bool &isupper, - double &d[],double &e[]) - { -//--- initialization - isupper=false; -//--- function call - COrtFac::RMatrixBDUnpackDiagonals(b,m,n,isupper,d,e); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Reduction of a square matrix to upper Hessenberg form: | -//| Q'*A*Q = H, where Q is an orthogonal matrix, H - Hessenberg | -//| matrix. | -//| Input parameters: | -//| A - matrix A with elements [0..N-1, 0..N-1] | -//| N - size of matrix A. | -//| Output parameters: | -//| A - matrices Q and P in compact form (see below). | -//| Tau - array of scalar factors which are used to form | -//| matrix Q. | -//| Array whose index ranges within [0..N-2] | -//| Matrix H is located on the main diagonal, on the lower secondary | -//| diagonal and above the main diagonal of matrix A. The elements | -//| which are used to form matrix Q are situated in array Tau and | -//| below the lower secondary diagonal of matrix A as follows: | -//| Matrix Q is represented as a product of elementary reflections | -//| Q = H(0)*H(2)*...*H(n-2), | -//| where each H(i) is given by | -//| H(i) = 1 - tau * v * (v^T) | -//| where tau is a scalar stored in Tau[I]; v - is a real vector, | -//| so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in | -//| A(i+2:n-1,i). | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1992 | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixHessenberg(CMatrixDouble &a,const int n, - double &tau[]) - { -//--- function call - COrtFac::RMatrixHessenberg(a,n,tau); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix Q which reduces matrix A to upper Hessenberg | -//| form | -//| Input parameters: | -//| A - output of RMatrixHessenberg subroutine. | -//| N - size of matrix A. | -//| Tau - scalar factors which are used to form Q. | -//| Output of RMatrixHessenberg subroutine. | -//| Output parameters: | -//| Q - matrix Q. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixHessenbergUnpackQ(CMatrixDouble &a,const int n, - double &tau[],CMatrixDouble &q) - { -//--- function call - COrtFac::RMatrixHessenbergUnpackQ(a,n,tau,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix H (the result of matrix A reduction to upper | -//| Hessenberg form) | -//| Input parameters: | -//| A - output of RMatrixHessenberg subroutine. | -//| N - size of matrix A. | -//| Output parameters: | -//| H - matrix H. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixHessenbergUnpackH(CMatrixDouble &a,const int n, - CMatrixDouble &h) - { -//--- function call - COrtFac::RMatrixHessenbergUnpackH(a,n,h); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Reduction of a symmetric matrix which is given by its higher or | -//| lower triangular part to a tridiagonal matrix using orthogonal | -//| similarity transformation: Q'*A*Q=T. | -//| Input parameters: | -//| A - matrix to be transformed | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. If IsUpper = True, then matrix A | -//| is given by its upper triangle, and the lower | -//| triangle is not used and not modified by the | -//| algorithm, and vice versa if IsUpper = False. | -//| Output parameters: | -//| A - matrices T and Q in compact form (see lower) | -//| Tau - array of factors which are forming matrices H(i) | -//| array with elements [0..N-2]. | -//| D - main diagonal of symmetric matrix T. | -//| array with elements [0..N-1]. | -//| E - secondary diagonal of symmetric matrix T. | -//| array with elements [0..N-2]. | -//| If IsUpper=True, the matrix Q is represented as a product of | -//| elementary reflectors | -//| Q = H(n-2) . . . H(2) H(0). | -//| Each H(i) has the form | -//| H(i) = I - tau * v * v' | -//| where tau is a real scalar, and v is a real vector with | -//| v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in | -//| A(0:i-1,i+1), and tau in TAU(i). | -//| If IsUpper=False, the matrix Q is represented as a product of | -//| elementary reflectors | -//| Q = H(0) H(2) . . . H(n-2). | -//| Each H(i) has the form | -//| H(i) = I - tau * v * v' | -//| where tau is a real scalar, and v is a real vector with | -//| v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in | -//| A(i+2:n-1,i), and tau in TAU(i). | -//| The contents of A on exit are illustrated by the following | -//| examples with n = 5: | -//| if UPLO = 'U': if UPLO = 'L': | -//| ( d e v1 v2 v3 ) ( d ) | -//| ( d e v2 v3 ) ( e d ) | -//| ( d e v3 ) ( v0 e d ) | -//| ( d e ) ( v0 v1 e d ) | -//| ( d ) ( v0 v1 v2 e d ) | -//| where d and e denote diagonal and off-diagonal elements of T, | -//| and vi denotes an element of the vector defining H(i). | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1992 | -//+------------------------------------------------------------------+ -static void CAlglib::SMatrixTD(CMatrixDouble &a,const int n,const bool isupper, - double &tau[],double &d[],double &e[]) - { -//--- function call - COrtFac::SMatrixTD(a,n,isupper,tau,d,e); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix Q which reduces symmetric matrix to a | -//| tridiagonal form. | -//| Input parameters: | -//| A - the result of a SMatrixTD subroutine | -//| N - size of matrix A. | -//| IsUpper - storage format (a parameter of SMatrixTD | -//| subroutine) | -//| Tau - the result of a SMatrixTD subroutine | -//| Output parameters: | -//| Q - transformation matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::SMatrixTDUnpackQ(CMatrixDouble &a,const int n, - const bool isupper,double &tau[], - CMatrixDouble &q) - { -//--- function call - COrtFac::SMatrixTDUnpackQ(a,n,isupper,tau,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Reduction of a Hermitian matrix which is given by its higher or | -//| lower triangular part to a real tridiagonal matrix using unitary | -//| similarity transformation: Q'*A*Q = T. | -//| Input parameters: | -//| A - matrix to be transformed | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. If IsUpper = True, then matrix A | -//| is given by its upper triangle, and the lower | -//| triangle is not used and not modified by the | -//| algorithm, and vice versa if IsUpper = False. | -//| Output parameters: | -//| A - matrices T and Q in compact form (see lower) | -//| Tau - array of factors which are forming matrices H(i) | -//| array with elements [0..N-2]. | -//| D - main diagonal of real symmetric matrix T. | -//| array with elements [0..N-1]. | -//| E - secondary diagonal of real symmetric matrix T. | -//| array with elements [0..N-2]. | -//| If IsUpper=True, the matrix Q is represented as a product of | -//| elementary reflectors | -//| Q = H(n-2) . . . H(2) H(0). | -//| Each H(i) has the form | -//| H(i) = I - tau * v * v' | -//| where tau is a complex scalar, and v is a complex vector with | -//| v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in | -//| A(0:i-1,i+1), and tau in TAU(i). | -//| If IsUpper=False, the matrix Q is represented as a product of | -//| elementary reflectors | -//| Q = H(0) H(2) . . . H(n-2). | -//| Each H(i) has the form | -//| H(i) = I - tau * v * v' | -//| where tau is a complex scalar, and v is a complex vector with | -//| v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in | -//| A(i+2:n-1,i), and tau in TAU(i). | -//| The contents of A on exit are illustrated by the following | -//| examples with n = 5: | -//| if UPLO = 'U': if UPLO = 'L': | -//| ( d e v1 v2 v3 ) ( d ) | -//| ( d e v2 v3 ) ( e d ) | -//| ( d e v3 ) ( v0 e d ) | -//| ( d e ) ( v0 v1 e d ) | -//| ( d ) ( v0 v1 v2 e d ) | -//| where d and e denote diagonal and off-diagonal elements of T, and| -//| vi denotes an element of the vector defining H(i). | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1992 | -//+------------------------------------------------------------------+ -static void CAlglib::HMatrixTD(CMatrixComplex &a,const int n,const bool isupper, - al_complex &tau[],double &d[],double &e[]) - { -//--- function call - COrtFac::HMatrixTD(a,n,isupper,tau,d,e); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Unpacking matrix Q which reduces a Hermitian matrix to a real | -//| tridiagonal form. | -//| Input parameters: | -//| A - the result of a HMatrixTD subroutine | -//| N - size of matrix A. | -//| IsUpper - storage format (a parameter of HMatrixTD | -//| subroutine) | -//| Tau - the result of a HMatrixTD subroutine | -//| Output parameters: | -//| Q - transformation matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void CAlglib::HMatrixTDUnpackQ(CMatrixComplex &a,const int n, - const bool isupper,al_complex &tau[], - CMatrixComplex &q) - { -//--- function call - COrtFac::HMatrixTDUnpackQ(a,n,isupper,tau,q); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Finding the eigenvalues and eigenvectors of a symmetric matrix | -//| The algorithm finds eigen pairs of a symmetric matrix by reducing| -//| it to tridiagonal form and using the QL/QR algorithm. | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper or | -//| lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. | -//| If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpper - storage format. | -//| Output parameters: | -//| D - eigenvalues in ascending order. | -//| Array whose index ranges within [0..N-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains the eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged (rare case). | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixEVD(CMatrixDouble &a,const int n,int zneeded, - const bool isupper,double &d[], - CMatrixDouble &z) - { -//--- return result - return(CEigenVDetect::SMatrixEVD(a,n,zneeded,isupper,d,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the eigenvalues (and eigenvectors) of a | -//| symmetric matrix in a given half open interval (A, B] by using a | -//| bisection and inverse iteration | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper or | -//| lower triangular part. Array [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. | -//| If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpperA - storage format of matrix A. | -//| B1, B2 - half open interval (B1, B2] to search | -//| eigenvalues in. | -//| Output parameters: | -//| M - number of eigenvalues found in a given | -//| half-interval (M>=0). | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if successful. M contains the number of eigenvalues in | -//| the given half-interval (could be equal to 0), W contains the| -//| eigenvalues, Z contains the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues | -//| and eigenvectors are not returned, M is equal to 0. | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixEVDR(CMatrixDouble &a,const int n,int zneeded, - const bool isupper,double b1,double b2, - int &m,double &w[],CMatrixDouble &z) - { -//--- initialization - m=0; -//--- return result - return(CEigenVDetect::SMatrixEVDR(a,n,zneeded,isupper,b1,b2,m,w,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the eigenvalues and eigenvectors of a | -//| symmetric matrix with given indexes by using bisection and | -//| inverse iteration methods. | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper or | -//| lower triangular part. Array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. | -//| If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpperA - storage format of matrix A. | -//| I1, I2 - index interval for searching (from I1 to I2). | -//| 0 <= I1 <= I2 <= N-1. | -//| Output parameters: | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..I2-I1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..I2-I1]. | -//| In that case, the eigenvectors are stored in the | -//| matrix columns. | -//| Result: | -//| True, if successful. W contains the eigenvalues, Z contains | -//| the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues | -//| and eigenvectors are not returned. | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixEVDI(CMatrixDouble &a,const int n,int zneeded, - const bool isupper,const int i1, - const int i2,double &w[],CMatrixDouble &z) - { -//--- return result - return(CEigenVDetect::SMatrixEVDI(a,n,zneeded,isupper,i1,i2,w,z)); - } -//+------------------------------------------------------------------+ -//| Finding the eigenvalues and eigenvectors of a Hermitian matrix | -//| The algorithm finds eigen pairs of a Hermitian matrix by reducing| -//| it to real tridiagonal form and using the QL/QR algorithm. | -//| Input parameters: | -//| A - Hermitian matrix which is given by its upper or | -//| lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| Output parameters: | -//| D - eigenvalues in ascending order. | -//| Array whose index ranges within [0..N-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains the eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged (rare case). | -//| Note: | -//| eigenvectors of Hermitian matrix are defined up to | -//| multiplication by a complex number L, such that |L|=1. | -//+------------------------------------------------------------------+ -static bool CAlglib::HMatrixEVD(CMatrixComplex &a,const int n,const int zneeded, - const bool isupper,double &d[],CMatrixComplex &z) - { -//--- return result - return(CEigenVDetect::HMatrixEVD(a,n,zneeded,isupper,d,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the eigenvalues (and eigenvectors) of a | -//| Hermitian matrix in a given half-interval (A, B] by using a | -//| bisection and inverse iteration | -//| Input parameters: | -//| A - Hermitian matrix which is given by its upper or | -//| lower triangular part. Array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpperA - storage format of matrix A. | -//| B1, B2 - half-interval (B1, B2] to search eigenvalues in. | -//| Output parameters: | -//| M - number of eigenvalues found in a given | -//| half-interval, M>=0 | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if successful. M contains the number of eigenvalues | -//| in the given half-interval (could be equal to 0), W contains | -//| the eigenvalues, Z contains the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned, M is equal to 0. | -//| Note: | -//| eigen vectors of Hermitian matrix are defined up to | -//| multiplication by a complex number L, such as |L|=1. | -//+------------------------------------------------------------------+ -static bool CAlglib::HMatrixEVDR(CMatrixComplex &a,const int n,const int zneeded, - const bool isupper,double b1,double b2, - int &m,double &w[],CMatrixComplex &z) - { -//--- initialization - m=0; -//--- return result - return(CEigenVDetect::HMatrixEVDR(a,n,zneeded,isupper,b1,b2,m,w,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the eigenvalues and eigenvectors of a | -//| Hermitian matrix with given indexes by using bisection and | -//| inverse iteration methods | -//| Input parameters: | -//| A - Hermitian matrix which is given by its upper or | -//| lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpperA - storage format of matrix A. | -//| I1, I2 - index interval for searching (from I1 to I2). | -//| 0 <= I1 <= I2 <= N-1. | -//| Output parameters: | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..I2-I1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..I2-I1]. | -//| In that case, the eigenvectors are stored in | -//| the matrix columns. | -//| Result: | -//| True, if successful. W contains the eigenvalues, Z contains | -//| the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| corresponding eigenvectors. iteration subroutine wasn't able | -//| to find all the corresponding eigenvectors. In that case, | -//| the eigenvalues and eigenvectors are not returned. | -//| Note: | -//| eigen vectors of Hermitian matrix are defined up to | -//| multiplication by a complex number L, such as |L|=1. | -//+------------------------------------------------------------------+ -static bool CAlglib::HMatrixEVDI(CMatrixComplex &a,const int n,const int zneeded, - const bool isupper,const int i1,const int i2, - double &w[],CMatrixComplex &z) - { -//--- return result - return(CEigenVDetect::HMatrixEVDI(a,n,zneeded,isupper,i1,i2,w,z)); - } -//+------------------------------------------------------------------+ -//| Finding the eigenvalues and eigenvectors of a tridiagonal | -//| symmetric matrix | -//| The algorithm finds the eigen pairs of a tridiagonal symmetric | -//| matrix by using an QL/QR algorithm with implicit shifts. | -//| Input parameters: | -//| D - the main diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-1]. | -//| E - the secondary diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-2]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. | -//| If ZNeeded is equal to: | -//| * 0, the eigenvectors are not needed; | -//| * 1, the eigenvectors of a tridiagonal matrix | -//| are multiplied by the square matrix Z. It is | -//| used if the tridiagonal matrix is obtained by | -//| the similarity transformation of a symmetric | -//| matrix; | -//| * 2, the eigenvectors of a tridiagonal matrix | -//| replace the square matrix Z; | -//| * 3, matrix Z contains the first row of the | -//| eigenvectors matrix. | -//| Z - if ZNeeded=1, Z contains the square matrix by | -//| which the eigenvectors are multiplied. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| Output parameters: | -//| D - eigenvalues in ascending order. | -//| Array whose index ranges within [0..N-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains the product of a given matrix | -//| (from the left) and the eigenvectors matrix | -//| (from the right); | -//| * 2, Z contains the eigenvectors. | -//| * 3, Z contains the first row of the | -//| eigenvectors matrix. | -//| If ZNeeded<3, Z is the array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| In that case, the eigenvectors are stored in the | -//| matrix columns. | -//| If ZNeeded=3, Z is the array whose indexes range | -//| within [0..0, 0..N-1]. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixTdEVD(double &d[],double &e[],const int n, - const int zneeded,CMatrixDouble &z) - { -//--- return result - return(CEigenVDetect::SMatrixTdEVD(d,e,n,zneeded,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the tridiagonal matrix eigenvalues/vectors| -//| in a given half-interval (A, B] by using bisection and inverse | -//| iteration. | -//| Input parameters: | -//| D - the main diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-1]. | -//| E - the secondary diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-2]. | -//| N - size of matrix, N>=0. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not needed; | -//| * 1, the eigenvectors of a tridiagonal matrix | -//| are multiplied by the square matrix Z. It is | -//| used if the tridiagonal matrix is obtained by | -//| the similarity transformation of a symmetric | -//| matrix. | -//| * 2, the eigenvectors of a tridiagonal matrix | -//| replace matrix Z. | -//| A, B - half-interval (A, B] to search eigenvalues in. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z isn't used and remains unchanged; | -//| * 1, Z contains the square matrix (array whose | -//| indexes range within [0..N-1, 0..N-1]) which | -//| reduces the given symmetric matrix to | -//| tridiagonal form; | -//| * 2, Z isn't used (but changed on the exit). | -//| Output parameters: | -//| D - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| M - number of eigenvalues found in the given | -//| half-interval (M>=0). | -//| Z - if ZNeeded is equal to: | -//| * 0, doesn't contain any information; | -//| * 1, contains the product of a given NxN matrix | -//| Z (from the left) and NxM matrix of the | -//| eigenvectors found (from the right). Array | -//| whose indexes range within [0..N-1, 0..M-1]. | -//| * 2, contains the matrix of the eigenvectors | -//| found. Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| Result: | -//| True, if successful. In that case, M contains the number of | -//| eigenvalues in the given half-interval (could be equal to 0),| -//| D contains the eigenvalues, Z contains the eigenvectors (if | -//| needed). It should be noted that the subroutine changes the | -//| size of arrays D and Z. | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned, M is equal to 0. | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixTdEVDR(double &d[],double &e[],const int n, - const int zneeded,const double a, - const double b,int &m,CMatrixDouble &z) - { -//--- initialization - m=0; -//--- return result - return(CEigenVDetect::SMatrixTdEVDR(d,e,n,zneeded,a,b,m,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding tridiagonal matrix eigenvalues/vectors | -//| with given indexes (in ascending order) by using the bisection | -//| and inverse iteraion. | -//| Input parameters: | -//| D - the main diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-1]. | -//| E - the secondary diagonal of a tridiagonal matrix. | -//| Array whose index ranges within [0..N-2]. | -//| N - size of matrix. N>=0. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not needed; | -//| * 1, the eigenvectors of a tridiagonal matrix | -//| are multiplied by the square matrix Z. It is | -//| used if the tridiagonal matrix is obtained by | -//| the similarity transformation of a symmetric | -//| matrix. | -//| * 2, the eigenvectors of a tridiagonal matrix | -//| replace matrix Z. | -//| I1, I2 - index interval for searching (from I1 to I2). | -//| 0 <= I1 <= I2 <= N-1. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z isn't used and remains unchanged; | -//| * 1, Z contains the square matrix (array whose | -//| indexes range within [0..N-1, 0..N-1]) which | -//| reduces the given symmetric matrix to | -//| tridiagonal form; | -//| * 2, Z isn't used (but changed on the exit). | -//| Output parameters: | -//| D - array of the eigenvalues found. | -//| Array whose index ranges within [0..I2-I1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, doesn't contain any information; | -//| * 1, contains the product of a given NxN matrix | -//| Z (from the left) and Nx(I2-I1) matrix of the | -//| eigenvectors found (from the right). Array | -//| whose indexes range within [0..N-1, 0..I2-I1].| -//| * 2, contains the matrix of the eigenvalues | -//| found. Array whose indexes range within | -//| [0..N-1, 0..I2-I1]. | -//| Result: | -//| True, if successful. In that case, D contains the | -//| eigenvalues, Z contains the eigenvectors (if needed). | -//| It should be noted that the subroutine changes the size of | -//| arrays D and Z. | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned. | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixTdEVDI(double &d[],double &e[],const int n, - const int zneeded,const int i1, - const int i2,CMatrixDouble &z) - { -//--- return result - return(CEigenVDetect::SMatrixTdEVDI(d,e,n,zneeded,i1,i2,z)); - } -//+------------------------------------------------------------------+ -//| Finding eigenvalues and eigenvectors of a general matrix | -//| The algorithm finds eigenvalues and eigenvectors of a general | -//| matrix by using the QR algorithm with multiple shifts. The | -//| algorithm can find eigenvalues and both left and right | -//| eigenvectors. | -//| The right eigenvector is a vector x such that A*x = w*x, and the | -//| left eigenvector is a vector y such that y'*A = w*y' (here y' | -//| implies a complex conjugate transposition of vector y). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| VNeeded - flag controlling whether eigenvectors are needed | -//| or not. If VNeeded is equal to: | -//| * 0, eigenvectors are not returned; | -//| * 1, right eigenvectors are returned; | -//| * 2, left eigenvectors are returned; | -//| * 3, both left and right eigenvectors are | -//| returned. | -//| Output parameters: | -//| WR - real parts of eigenvalues. | -//| Array whose index ranges within [0..N-1]. | -//| WR - imaginary parts of eigenvalues. | -//| Array whose index ranges within [0..N-1]. | -//| VL, VR - arrays of left and right eigenvectors (if they | -//| are needed). If WI[i]=0, the respective | -//| eigenvalue is a real number, and it corresponds | -//| to the column number I of matrices VL/VR. If | -//| WI[i]>0, we have a pair of complex conjugate | -//| numbers with positive and negative imaginary | -//| parts: the first eigenvalue WR[i] + | -//| + sqrt(-1)*WI[i]; the second eigenvalue | -//| WR[i+1] + sqrt(-1)*WI[i+1]; | -//| WI[i]>0 | -//| WI[i+1] = -WI[i] < 0 | -//| In that case, the eigenvector corresponding to | -//| the first eigenvalue is located in i and i+1 | -//| columns of matrices VL/VR (the column number i | -//| contains the real part, and the column number | -//| i+1 contains the imaginary part), and the vector | -//| corresponding to the second eigenvalue is a | -//| complex conjugate to the first vector. | -//| Arrays whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm has not converged. | -//| Note 1: | -//| Some users may ask the following question: what if WI[N-1]>0?| -//| WI[N] must contain an eigenvalue which is complex conjugate | -//| to the N-th eigenvalue, but the array has only size N? | -//| The answer is as follows: such a situation cannot occur | -//| because the algorithm finds a pairs of eigenvalues, | -//| therefore, if WI[i]>0, I is strictly less than N-1. | -//| Note 2: | -//| The algorithm performance depends on the value of the | -//| internal parameter NS of the InternalSchurDecomposition | -//| subroutine which defines the number of shifts in the QR | -//| algorithm (similarly to the block width in block-matrix | -//| algorithms of linear algebra). If you require maximum | -//| performance on your machine, it is recommended to adjust | -//| this parameter manually. | -//| See also the InternalTREVC subroutine. | -//| The algorithm is based on the LAPACK 3.0 library. | -//+------------------------------------------------------------------+ -static bool CAlglib::RMatrixEVD(CMatrixDouble &a,const int n,const int vneeded, - double &wr[],double &wi[],CMatrixDouble &vl, - CMatrixDouble &vr) - { - bool result=CEigenVDetect::RMatrixEVD(a,n,vneeded,wr,wi,vl,vr); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Generation of a random uniformly distributed (Haar) orthogonal | -//| matrix | -//| INPUT PARAMETERS: | -//| N - matrix size, N>=1 | -//| OUTPUT PARAMETERS: | -//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRndOrthogonal(const int n,CMatrixDouble &a) - { -//--- function call - CMatGen::RMatrixRndOrthogonal(n,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN matrix with given condition number and | -//| norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRndCond(const int n,const double c, - CMatrixDouble &a) - { -//--- function call - CMatGen::RMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of a random Haar distributed orthogonal complex matrix| -//| INPUT PARAMETERS: | -//| N - matrix size, N>=1 | -//| OUTPUT PARAMETERS: | -//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRndOrthogonal(const int n,CMatrixComplex &a) - { -//--- function call - CMatGen::CMatrixRndOrthogonal(n,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN complex matrix with given condition | -//| number C and norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRndCond(const int n,const double c, - CMatrixComplex &a) - { -//--- function call - CMatGen::CMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN symmetric matrix with given condition | -//| number and norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::SMatrixRndCond(const int n,const double c, - CMatrixDouble &a) - { -//--- function call - CMatGen::SMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN symmetric positive definite matrix with | -//| given condition number and norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random SPD matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixRndCond(const int n,const double c, - CMatrixDouble &a) - { -//--- function call - CMatGen::SPDMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN Hermitian matrix with given condition | -//| number and norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::HMatrixRndCond(const int n,const double c, - CMatrixComplex &a) - { -//--- function call - CMatGen::HMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Generation of random NxN Hermitian positive definite matrix with | -//| given condition number and norm2(A)=1 | -//| INPUT PARAMETERS: | -//| N - matrix size | -//| C - condition number (in 2-norm) | -//| OUTPUT PARAMETERS: | -//| A - random HPD matrix with norm2(A)=1 and cond(A)=C | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixRndCond(const int n,const double c, - CMatrixComplex &a) - { -//--- function call - CMatGen::HPDMatrixRndCond(n,c,a); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication of MxN matrix by NxN random Haar distributed | -//| orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..M-1, 0..N-1] | -//| M, N- matrix size | -//| OUTPUT PARAMETERS: | -//| A - A*Q, where Q is random NxN orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRndOrthogonalFromTheRight(CMatrixDouble &a, - const int m,const int n) - { -//--- function call - CMatGen::RMatrixRndOrthogonalFromTheRight(a,m,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication of MxN matrix by MxM random Haar distributed | -//| orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..M-1, 0..N-1] | -//| M, N- matrix size | -//| OUTPUT PARAMETERS: | -//| A - Q*A, where Q is random MxM orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixRndOrthogonalFromTheLeft(CMatrixDouble &a, - const int m,const int n) - { -//--- function call - CMatGen::RMatrixRndOrthogonalFromTheLeft(a,m,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication of MxN complex matrix by NxN random Haar | -//| distributed complex orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..M-1, 0..N-1] | -//| M, N- matrix size | -//| OUTPUT PARAMETERS: | -//| A - A*Q, where Q is random NxN orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRndOrthogonalFromTheRight(CMatrixComplex &a, - const int m,const int n) - { -//--- function call - CMatGen::CMatrixRndOrthogonalFromTheRight(a,m,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Multiplication of MxN complex matrix by MxM random Haar | -//| distributed complex orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..M-1, 0..N-1] | -//| M, N- matrix size | -//| OUTPUT PARAMETERS: | -//| A - Q*A, where Q is random MxM orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixRndOrthogonalFromTheLeft(CMatrixComplex &a, - const int m,const int n) - { -//--- function call - CMatGen::CMatrixRndOrthogonalFromTheLeft(a,m,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Symmetric multiplication of NxN matrix by random Haar | -//| distributed orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - matrix size | -//| OUTPUT PARAMETERS: | -//| A - Q'*A*Q, where Q is random NxN orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::SMatrixRndMultiply(CMatrixDouble &a,const int n) - { -//--- function call - CMatGen::SMatrixRndMultiply(a,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Hermitian multiplication of NxN matrix by random Haar distributed| -//| complex orthogonal matrix | -//| INPUT PARAMETERS: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - matrix size | -//| OUTPUT PARAMETERS: | -//| A - Q^H*A*Q, where Q is random NxN orthogonal matrix | -//+------------------------------------------------------------------+ -static void CAlglib::HMatrixRndMultiply(CMatrixComplex &a,const int n) - { -//--- function call - CMatGen::HMatrixRndMultiply(a,n); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LU decomposition of a general real matrix with row pivoting | -//| A is represented as A = P*L*U, where: | -//| * L is lower unitriangular matrix | -//| * U is upper triangular matrix | -//| * P = P0*P1*...*PK, K=min(M,N)-1, | -//| Pi - permutation matrix for I and Pivots[I] | -//| This is cache-oblivous implementation of LU decomposition. | -//| It is optimized for square matrices. As for rectangular matrices:| -//| * best case - M>>N | -//| * worst case - N>>M, small M, large N, matrix does not fit in CPU| -//| cache | -//| INPUT PARAMETERS: | -//| A - array[0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| OUTPUT PARAMETERS: | -//| A - matrices L and U in compact form: | -//| * L is stored under main diagonal | -//| * U is stored on and above main diagonal | -//| Pivots - permutation matrix in compact form. | -//| array[0..Min(M-1,N-1)]. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLU(CMatrixDouble &a,const int m,const int n, - int &pivots[]) - { -//--- function call - CTrFac::RMatrixLU(a,m,n,pivots); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LU decomposition of a general complex matrix with row pivoting | -//| A is represented as A = P*L*U, where: | -//| * L is lower unitriangular matrix | -//| * U is upper triangular matrix | -//| * P = P0*P1*...*PK, K=min(M,N)-1, | -//| Pi - permutation matrix for I and Pivots[I] | -//| This is cache-oblivous implementation of LU decomposition. It is | -//| optimized for square matrices. As for rectangular matrices: | -//| * best case - M>>N | -//| * worst case - N>>M, small M, large N, matrix does not fit in CPU| -//| cache | -//| INPUT PARAMETERS: | -//| A - array[0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| OUTPUT PARAMETERS: | -//| A - matrices L and U in compact form: | -//| * L is stored under main diagonal | -//| * U is stored on and above main diagonal | -//| Pivots - permutation matrix in compact form. | -//| array[0..Min(M-1,N-1)]. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLU(CMatrixComplex &a,const int m,const int n, - int &pivots[]) - { -//--- function call - CTrFac::CMatrixLU(a,m,n,pivots); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Cache-oblivious Cholesky decomposition | -//| The algorithm computes Cholesky decomposition of a Hermitian | -//| positive - definite matrix. The result of an algorithm is a | -//| representation of A as A=U'*U or A=L*L' (here X' detones | -//| conj(X^T)). | -//| INPUT PARAMETERS: | -//| A - upper or lower triangle of a factorized matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - if IsUpper=True, then A contains an upper | -//| triangle of a symmetric matrix, otherwise A | -//| contains a lower one. | -//| OUTPUT PARAMETERS: | -//| A - the result of factorization. If IsUpper=True, | -//| then the upper triangle contains matrix U, so | -//| that A = U'*U, and the elements below the main | -//| diagonal are not modified. Similarly, if | -//| IsUpper = False. | -//| RESULT: | -//| If the matrix is positive-definite, the function returns | -//| True. Otherwise, the function returns False. Contents of A is| -//| not determined in such case. | -//+------------------------------------------------------------------+ -static bool CAlglib::HPDMatrixCholesky(CMatrixComplex &a,const int n, - const bool isupper) - { -//--- return result - return(CTrFac::HPDMatrixCholesky(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Cache-oblivious Cholesky decomposition | -//| The algorithm computes Cholesky decomposition of a symmetric | -//| positive - definite matrix. The result of an algorithm is a | -//| representation of A as A=U^T*U or A=L*L^T | -//| INPUT PARAMETERS: | -//| A - upper or lower triangle of a factorized matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - if IsUpper=True, then A contains an upper | -//| triangle of a symmetric matrix, otherwise A | -//| contains a lower one. | -//| OUTPUT PARAMETERS: | -//| A - the result of factorization. If IsUpper=True, | -//| then the upper triangle contains matrix U, so | -//| that A = U^T*U, and the elements below the main | -//| diagonal are not modified. Similarly, if | -//| IsUpper = False. | -//| RESULT: | -//| If the matrix is positive-definite, the function returns | -//| True. Otherwise, the function returns False. Contents of A is| -//| not determined in such case. | -//+------------------------------------------------------------------+ -static bool CAlglib::SPDMatrixCholesky(CMatrixDouble &a,const int n, - const bool isupper) - { -//--- return result - return(CTrFac::SPDMatrixCholesky(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Estimate of a matrix condition number (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixRCond1(CMatrixDouble &a,const int n) - { -//--- return result - return(CRCond::RMatrixRCond1(a,n)); - } -//+------------------------------------------------------------------+ -//| Estimate of a matrix condition number (infinity-norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixRCondInf(CMatrixDouble &a,const int n) - { -//--- return result - return(CRCond::RMatrixRCondInf(a,n)); - } -//+------------------------------------------------------------------+ -//| Condition number estimate of a symmetric positive definite | -//| matrix. | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| It should be noted that 1-norm and inf-norm of condition numbers | -//| of symmetric matrices are equal, so the algorithm doesn't take | -//| into account the differences between these types of norms. | -//| Input parameters: | -//| A - symmetric positive definite matrix which is given| -//| by its upper or lower triangle depending on the | -//| value of IsUpper. Array with elements | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. | -//| Result: | -//| 1/LowerBound(cond(A)), if matrix A is positive definite, | -//| -1, if matrix A is not positive definite, and its condition | -//| number could not be found by this algorithm. | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixRCond(CMatrixDouble &a,const int n, - const bool isupper) - { -//--- return result - return(CRCond::SPDMatrixRCond(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Triangular matrix: estimate of a condition number (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array[0..N-1, 0..N-1]. | -//| N - size of A. | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - True, if the matrix has a unit diagonal. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixTrRCond1(CMatrixDouble &a,const int n, - const bool isupper,const bool isunit) - { -//--- return result - return(CRCond::RMatrixTrRCond1(a,n,isupper,isunit)); - } -//+-------------------------------------------------------------------+ -//| Triangular matrix: estimate of a matrix condition number | -//| (infinity-norm). | -//| The algorithm calculates a lower bound of the condition number. In| -//| this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - True, if the matrix has a unit diagonal. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+-------------------------------------------------------------------+ -static double CAlglib::RMatrixTrRCondInf(CMatrixDouble &a,const int n, - const bool isupper,const bool isunit) - { -//--- return result - return(CRCond::RMatrixTrRCondInf(a,n,isupper,isunit)); - } -//+------------------------------------------------------------------+ -//| Condition number estimate of a Hermitian positive definite | -//| matrix. | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| It should be noted that 1-norm and inf-norm of condition numbers | -//| of symmetric matrices are equal, so the algorithm doesn't take | -//| into account the differences between these types of norms. | -//| Input parameters: | -//| A - Hermitian positive definite matrix which is given| -//| by its upper or lower triangle depending on the | -//| value of IsUpper. Array with elements | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. | -//| Result: | -//| 1/LowerBound(cond(A)), if matrix A is positive definite, | -//| -1, if matrix A is not positive definite, and its condition | -//| number could not be found by this algorithm. | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::HPDMatrixRCond(CMatrixComplex &a,const int n, - const bool isupper) - { -//--- return result - return(CRCond::HPDMatrixRCond(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Estimate of a matrix condition number (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixRCond1(CMatrixComplex &a,const int n) - { -//--- return result - return(CRCond::CMatrixRCond1(a,n)); - } -//+------------------------------------------------------------------+ -//| Estimate of a matrix condition number (infinity-norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixRCondInf(CMatrixComplex &a,const int n) - { -//--- return result - return(CRCond::CMatrixRCondInf(a,n)); - } -//+------------------------------------------------------------------+ -//| Estimate of the condition number of a matrix given by its LU | -//| decomposition (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| LUA - LU decomposition of a matrix in compact form.| -//| Output of the RMatrixLU subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixLURCond1(CMatrixDouble &lua,const int n) - { -//--- return result - return(CRCond::RMatrixLURCond1(lua,n)); - } -//+------------------------------------------------------------------+ -//| Estimate of the condition number of a matrix given by its LU | -//| decomposition (infinity norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| LUA - LU decomposition of a matrix in compact form. | -//| Output of the RMatrixLU subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixLURCondInf(CMatrixDouble &lua,const int n) - { -//--- return result - return(CRCond::RMatrixLURCondInf(lua,n)); - } -//+------------------------------------------------------------------+ -//| Condition number estimate of a symmetric positive definite matrix| -//| given by Cholesky decomposition. | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| It should be noted that 1-norm and inf-norm condition numbers of | -//| symmetric matrices are equal, so the algorithm doesn't take into | -//| account the differences between these types of norms. | -//| Input parameters: | -//| CD - Cholesky decomposition of matrix A, | -//| output of SMatrixCholesky subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixCholeskyRCond(CMatrixDouble &a,const int n, - const bool isupper) - { -//--- return result - return(CRCond::SPDMatrixCholeskyRCond(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Condition number estimate of a Hermitian positive definite matrix| -//| given by Cholesky decomposition. | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| It should be noted that 1-norm and inf-norm condition numbers of | -//| symmetric matrices are equal, so the algorithm doesn't take into | -//| account the differences between these types of norms. | -//| Input parameters: | -//| CD - Cholesky decomposition of matrix A, | -//| output of SMatrixCholesky subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::HPDMatrixCholeskyRCond(CMatrixComplex &a,const int n, - const bool isupper) - { -//--- return result - return(CRCond::HPDMatrixCholeskyRCond(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Estimate of the condition number of a matrix given by its LU | -//| decomposition (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| LUA - LU decomposition of a matrix in compact form.| -//| Output of the CMatrixLU subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixLURCond1(CMatrixComplex &lua,const int n) - { -//--- return result - return(CRCond::CMatrixLURCond1(lua,n)); - } -//+------------------------------------------------------------------+ -//| Estimate of the condition number of a matrix given by its LU | -//| decomposition (infinity norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| LUA - LU decomposition of a matrix in compact form. | -//| Output of the CMatrixLU subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixLURCondInf(CMatrixComplex &lua,const int n) - { -//--- return result - return(CRCond::CMatrixLURCondInf(lua,n)); - } -//+------------------------------------------------------------------+ -//| Triangular matrix: estimate of a condition number (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array[0..N-1, 0..N-1]. | -//| N - size of A. | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - True, if the matrix has a unit diagonal. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixTrRCond1(CMatrixComplex &a,const int n, - const bool isupper,const bool isunit) - { -//--- return result - return(CRCond::CMatrixTrRCond1(a,n,isupper,isunit)); - } -//+------------------------------------------------------------------+ -//| Triangular matrix: estimate of a matrix condition number | -//| (infinity-norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - True, if the matrix has a unit diagonal. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CAlglib::CMatrixTrRCondInf(CMatrixComplex &a,const int n, - const bool isupper,const bool isunit) - { -//--- return result - return(CRCond::CMatrixTrRCondInf(a,n,isupper,isunit)); - } -//+------------------------------------------------------------------+ -//| Inversion of a matrix given by its LU decomposition. | -//| INPUT PARAMETERS: | -//| A - LU decomposition of the matrix | -//| (output of RMatrixLU subroutine). | -//| Pivots - table of permutations | -//| (the output of RMatrixLU subroutine). | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -3 A is singular, or VERY close to singular.| -//| it is filled by zeros in such cases. | -//| * 1 task is solved (but matrix A may be | -//| ill-conditioned, check R1/RInf parameters| -//| for condition numbers). | -//| Rep - solver report, see below for more info | -//| A - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. | -//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLUInverse(CMatrixDouble &a,int &pivots[], - const int n,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::RMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a matrix given by its LU decomposition. | -//| INPUT PARAMETERS: | -//| A - LU decomposition of the matrix | -//| (output of RMatrixLU subroutine). | -//| Pivots - table of permutations | -//| (the output of RMatrixLU subroutine). | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -3 A is singular, or VERY close to singular.| -//| it is filled by zeros in such cases. | -//| * 1 task is solved (but matrix A may be | -//| ill-conditioned, check R1/RInf parameters| -//| for condition numbers). | -//| Rep - solver report, see below for more info | -//| A - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. | -//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLUInverse(CMatrixDouble &a,int &pivots[], - int &info,CMatInvReportShell &rep) - { -//--- create a variable - int n; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a)) || (CAp::Cols(a)!=CAp::Len(pivots))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); -//--- function call - CMatInv::RMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//| Result: | -//| True, if the matrix is not singular. | -//| False, if the matrix is singular. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInverse(CMatrixDouble &a,const int n,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::RMatrixInverse(a,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//| Result: | -//| True, if the matrix is not singular. | -//| False, if the matrix is singular. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInverse(CMatrixDouble &a,int &info, - CMatInvReportShell &rep) - { -//--- create a variable - int n; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); -//--- function call - CMatInv::RMatrixInverse(a,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a matrix given by its LU decomposition. | -//| INPUT PARAMETERS: | -//| A - LU decomposition of the matrix | -//| (output of CMatrixLU subroutine). | -//| Pivots - table of permutations | -//| (the output of CMatrixLU subroutine). | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| OUTPUT PARAMETERS: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLUInverse(CMatrixComplex &a,int &pivots[], - const int n,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::CMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a matrix given by its LU decomposition. | -//| INPUT PARAMETERS: | -//| A - LU decomposition of the matrix | -//| (output of CMatrixLU subroutine). | -//| Pivots - table of permutations | -//| (the output of CMatrixLU subroutine). | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| OUTPUT PARAMETERS: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLUInverse(CMatrixComplex &a,int &pivots[], - int &info,CMatInvReportShell &rep) - { -//--- create a variable - int n; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a)) || (CAp::Cols(a)!=CAp::Len(pivots))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); -//--- function call - CMatInv::CMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixInverse(CMatrixComplex &a,const int n,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::CMatrixInverse(a,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixInverse(CMatrixComplex &a,int &info, - CMatInvReportShell &rep) - { -//--- create a variable - int n; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); -//--- function call - CMatInv::CMatrixInverse(a,n,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a symmetric positive definite matrix which is given | -//| by Cholesky decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition of the matrix to be | -//| inverted: A=U?*U or A = L*L'. | -//| Output of SPDMatrixCholesky subroutine. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, lower half is used. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixCholeskyInverse(CMatrixDouble &a,const int n, - const bool isupper,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::SPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a symmetric positive definite matrix which is given | -//| by Cholesky decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition of the matrix to be | -//| inverted: A=U?*U or A = L*L'. | -//| Output of SPDMatrixCholesky subroutine. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, lower half is used. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixCholeskyInverse(CMatrixDouble &a,int &info, - CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isupper; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); -//--- initialization - isupper=false; -//--- function call - CMatInv::SPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a symmetric positive definite matrix. | -//| Given an upper or lower triangle of a symmetric positive definite| -//| matrix, the algorithm generates matrix A^-1 and saves the upper | -//| or lower triangle depending on the input. | -//| Input parameters: | -//| A - matrix to be inverted (upper or lower triangle). | -//| Array with elements [0..N-1,0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixInverse(CMatrixDouble &a,const int n, - const bool isupper,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::SPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a symmetric positive definite matrix. | -//| Given an upper or lower triangle of a symmetric positive definite| -//| matrix, the algorithm generates matrix A^-1 and saves the upper | -//| or lower triangle depending on the input. | -//| Input parameters: | -//| A - matrix to be inverted (upper or lower triangle). | -//| Array with elements [0..N-1,0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixInverse(CMatrixDouble &a,int &info, - CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isupper; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- check - if(!CAp::IsSymmetric(a)) - { - Print(__FUNCTION__+": 'a' parameter is not symmetric matrix"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); - isupper=false; -//--- function call - CMatInv::SPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- check - if(!CAp::ForceSymmetric(a)) - { - Print(__FUNCTION__+": Internal error while forcing symmetricity of 'a' parameter"); - CAp::exception_happened=true; - return; - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a Hermitian positive definite matrix which is given | -//| by Cholesky decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition of the matrix to be | -//| inverted: A=U?*U or A = L*L'. | -//| Output of HPDMatrixCholesky subroutine. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, lower half is used. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixCholeskyInverse(CMatrixComplex &a,const int n, - const bool isupper,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::HPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a Hermitian positive definite matrix which is given | -//| by Cholesky decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition of the matrix to be | -//| inverted: A=U?*U or A = L*L'. | -//| Output of HPDMatrixCholesky subroutine. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, lower half is used. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixCholeskyInverse(CMatrixComplex &a,int &info, - CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isupper; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); - isupper=false; -//--- function call - CMatInv::HPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a Hermitian positive definite matrix. | -//| Given an upper or lower triangle of a Hermitian positive definite| -//| matrix, the algorithm generates matrix A^-1 and saves the upper | -//| or lower triangle depending on the input. | -//| Input parameters: | -//| A - matrix to be inverted (upper or lower triangle). | -//| Array with elements [0..N-1,0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixInverse(CMatrixComplex &a,const int n, - const bool isupper,int &info, - CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::HPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inversion of a Hermitian positive definite matrix. | -//| Given an upper or lower triangle of a Hermitian positive definite| -//| matrix, the algorithm generates matrix A^-1 and saves the upper | -//| or lower triangle depending on the input. | -//| Input parameters: | -//| A - matrix to be inverted (upper or lower triangle). | -//| Array with elements [0..N-1,0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - storage type (optional): | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixInverse(CMatrixComplex &a,int &info, - CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isupper; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- check - if(!CAp::IsHermitian(a)) - { - Print(__FUNCTION__+": 'a' parameter is not Hermitian matrix"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); - isupper=false; -//--- function call - CMatInv::HPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj()); -//--- check - if(!CAp::ForceHermitian(a)) - { - Print(__FUNCTION__+": Internal error while forcing Hermitian properties of 'a' parameter"); - CAp::exception_happened=true; - return; - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Triangular matrix inverse (real) | -//| The subroutine inverts the following types of matrices: | -//| * upper triangular | -//| * upper triangular with unit diagonal | -//| * lower triangular | -//| * lower triangular with unit diagonal | -//| In case of an upper (lower) triangular matrix, the inverse matrix| -//| will also be upper (lower) triangular, and after the end of the | -//| algorithm, the inverse matrix replaces the source matrix. The | -//| elements below (above) the main diagonal are not changed by the | -//| algorithm. | -//| If the matrix has a unit diagonal, the inverse matrix also has a | -//| unit diagonal, and the diagonal elements are not passed to the | -//| algorithm. | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - diagonal type (optional): | -//| * if True, matrix has unit diagonal (a[i,i] are | -//| NOT used) | -//| * if False, matrix diagonal is arbitrary | -//| * if not given, False is assumed | -//| Output parameters: | -//| Info - same as for RMatrixLUInverse | -//| Rep - same as for RMatrixLUInverse | -//| A - same as for RMatrixLUInverse. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixTrInverse(CMatrixDouble &a,const int n, - const bool isupper,const bool isunit, - int &info,CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::RMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Triangular matrix inverse (real) | -//| The subroutine inverts the following types of matrices: | -//| * upper triangular | -//| * upper triangular with unit diagonal | -//| * lower triangular | -//| * lower triangular with unit diagonal | -//| In case of an upper (lower) triangular matrix, the inverse matrix| -//| will also be upper (lower) triangular, and after the end of the | -//| algorithm, the inverse matrix replaces the source matrix. The | -//| elements below (above) the main diagonal are not changed by the | -//| algorithm. | -//| If the matrix has a unit diagonal, the inverse matrix also has a | -//| unit diagonal, and the diagonal elements are not passed to the | -//| algorithm. | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - diagonal type (optional): | -//| * if True, matrix has unit diagonal (a[i,i] are | -//| NOT used) | -//| * if False, matrix diagonal is arbitrary | -//| * if not given, False is assumed | -//| Output parameters: | -//| Info - same as for RMatrixLUInverse | -//| Rep - same as for RMatrixLUInverse | -//| A - same as for RMatrixLUInverse. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixTrInverse(CMatrixDouble &a,const bool isupper, - int &info,CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isunit; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); - isunit=false; -//--- function call - CMatInv::RMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Triangular matrix inverse (complex) | -//| The subroutine inverts the following types of matrices: | -//| * upper triangular | -//| * upper triangular with unit diagonal | -//| * lower triangular | -//| * lower triangular with unit diagonal | -//| In case of an upper (lower) triangular matrix, the inverse matrix| -//| will also be upper (lower) triangular, and after the end of the | -//| algorithm, the inverse matrix replaces the source matrix. The | -//| elements below (above) the main diagonal are not changed by the | -//| algorithm. | -//| If the matrix has a unit diagonal, the inverse matrix also has a | -//| unit diagonal, and the diagonal elements are not passed to the | -//| algorithm. | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - diagonal type (optional): | -//| * if True, matrix has unit diagonal (a[i,i] are | -//| NOT used) | -//| * if False, matrix diagonal is arbitrary | -//| * if not given, False is assumed | -//| Output parameters: | -//| Info - same as for RMatrixLUInverse | -//| Rep - same as for RMatrixLUInverse | -//| A - same as for RMatrixLUInverse. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixTrInverse(CMatrixComplex &a,const int n, - const bool isupper,const bool isunit, - int &info,CMatInvReportShell &rep) - { -//--- initialization - info=0; -//--- function call - CMatInv::CMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Triangular matrix inverse (complex) | -//| The subroutine inverts the following types of matrices: | -//| * upper triangular | -//| * upper triangular with unit diagonal | -//| * lower triangular | -//| * lower triangular with unit diagonal | -//| In case of an upper (lower) triangular matrix, the inverse matrix| -//| will also be upper (lower) triangular, and after the end of the | -//| algorithm, the inverse matrix replaces the source matrix. The | -//| elements below (above) the main diagonal are not changed by the | -//| algorithm. | -//| If the matrix has a unit diagonal, the inverse matrix also has a | -//| unit diagonal, and the diagonal elements are not passed to the | -//| algorithm. | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1]. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - diagonal type (optional): | -//| * if True, matrix has unit diagonal (a[i,i] are | -//| NOT used) | -//| * if False, matrix diagonal is arbitrary | -//| * if not given, False is assumed | -//| Output parameters: | -//| Info - same as for RMatrixLUInverse | -//| Rep - same as for RMatrixLUInverse | -//| A - same as for RMatrixLUInverse. | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixTrInverse(CMatrixComplex &a,const bool isupper, - int &info,CMatInvReportShell &rep) - { -//--- create variables - int n; - bool isunit; -//--- check - if((CAp::Cols(a)!=CAp::Rows(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - info=0; - n=CAp::Cols(a); - isunit=false; -//--- function call - CMatInv::CMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Singular value decomposition of a bidiagonal matrix (extended | -//| algorithm) | -//| The algorithm performs the singular value decomposition of a | -//| bidiagonal matrix B (upper or lower) representing it as | -//| B = Q*S*P^T, where Q and P - orthogonal matrices, S - diagonal | -//| matrix with non-negative elements on the main diagonal, in | -//| descending order. | -//| The algorithm finds singular values. In addition, the algorithm | -//| can calculate matrices Q and P (more precisely, not the matrices,| -//| but their product with given matrices U and VT - U*Q and | -//| (P^T)*VT)). Of course, matrices U and VT can be of any type, | -//| including identity. Furthermore, the algorithm can calculate Q'*C| -//| (this product is calculated more effectively than U*Q, because | -//| this calculation operates with rows instead of matrix columns). | -//| The feature of the algorithm is its ability to find all singular | -//| values including those which are arbitrarily close to 0 with | -//| relative accuracy close to machine precision. If the parameter | -//| IsFractionalAccuracyRequired is set to True, all singular values | -//| will have high relative accuracy close to machine precision. If | -//| the parameter is set to False, only the biggest singular value | -//| will have relative accuracy close to machine precision. The | -//| absolute error of other singular values is equal to the absolute | -//| error of the biggest singular value. | -//| Input parameters: | -//| D - main diagonal of matrix B. | -//| Array whose index ranges within [0..N-1]. | -//| E - superdiagonal (or subdiagonal) of matrix B. | -//| Array whose index ranges within [0..N-2]. | -//| N - size of matrix B. | -//| IsUpper - True, if the matrix is upper bidiagonal. | -//| IsFractionalAccuracyRequired - | -//| accuracy to search singular values with. | -//| U - matrix to be multiplied by Q. | -//| Array whose indexes range within | -//| [0..NRU-1, 0..N-1]. | -//| The matrix can be bigger, in that case only the | -//| submatrix [0..NRU-1, 0..N-1] will be multiplied | -//| by Q. | -//| NRU - number of rows in matrix U. | -//| C - matrix to be multiplied by Q'. | -//| Array whose indexes range within | -//| [0..N-1, 0..NCC-1]. | -//| The matrix can be bigger, in that case only the | -//| submatrix [0..N-1, 0..NCC-1] will be multiplied | -//| by Q'. | -//| NCC - number of columns in matrix C. | -//| VT - matrix to be multiplied by P^T. | -//| Array whose indexes range within | -//| [0..N-1, 0..NCVT-1]. | -//| The matrix can be bigger, in that case only the | -//| submatrix [0..N-1, 0..NCVT-1] will be multiplied | -//| by P^T. | -//| NCVT - number of columns in matrix VT. | -//| Output parameters: | -//| D - singular values of matrix B in descending order. | -//| U - if NRU>0, contains matrix U*Q. | -//| VT - if NCVT>0, contains matrix (P^T)*VT. | -//| C - if NCC>0, contains matrix Q'*C. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged (rare case). | -//| Additional information: | -//| The type of convergence is controlled by the internal | -//| parameter TOL. If the parameter is greater than 0, the | -//| singular values will have relative accuracy TOL. If TOL<0, | -//| the singular values will have absolute accuracy | -//| ABS(TOL)*norm(B). By default, |TOL| falls within the range of| -//| 10*Epsilon and 100*Epsilon, where Epsilon is the machine | -//| precision. It is not recommended to use TOL less than | -//| 10*Epsilon since this will considerably slow down the | -//| algorithm and may not lead to error decreasing. | -//| History: | -//| * 31 March, 2007. | -//| changed MAXITR from 6 to 12. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1999. | -//+------------------------------------------------------------------+ -static bool CAlglib::RMatrixBdSVD(double &d[],double &e[],const int n, - const bool isupper, - bool isfractionalaccuracyrequired, - CMatrixDouble &u,const int nru, - CMatrixDouble &c,const int ncc, - CMatrixDouble &vt,const int ncvt) - { -//--- return result - return(CBdSingValueDecompose::RMatrixBdSVD(d,e,n,isupper,isfractionalaccuracyrequired,u,nru,c,ncc,vt,ncvt)); - } -//+------------------------------------------------------------------+ -//| Singular value decomposition of a rectangular matrix. | -//| The algorithm calculates the singular value decomposition of a | -//| matrix of size MxN: A = U * S * V^T | -//| The algorithm finds the singular values and, optionally, matrices| -//| U and V^T. The algorithm can find both first min(M,N) columns of | -//| matrix U and rows of matrix V^T (singular vectors), and matrices | -//| U and V^T wholly (of sizes MxM and NxN respectively). | -//| Take into account that the subroutine does not return matrix V | -//| but V^T. | -//| Input parameters: | -//| A - matrix to be decomposed. | -//| Array whose indexes range within | -//| [0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| UNeeded - 0, 1 or 2. See the description of the | -//| parameter U. | -//| VTNeeded - 0, 1 or 2. See the description of the | -//| parameter VT. | -//| AdditionalMemory - | -//| If the parameter: | -//| * equals 0, the algorithm doesn?t use | -//| additional memory (lower requirements, | -//| lower performance). | -//| * equals 1, the algorithm uses additional | -//| memory of size min(M,N)*min(M,N) of real | -//| numbers. It often speeds up the algorithm.| -//| * equals 2, the algorithm uses additional | -//| memory of size M*min(M,N) of real numbers.| -//| It allows to get a maximum performance. | -//| The recommended value of the parameter is 2. | -//| Output parameters: | -//| W - contains singular values in descending order.| -//| U - if UNeeded=0, U isn't changed, the left | -//| singular vectors are not calculated. | -//| if Uneeded=1, U contains left singular | -//| vectors (first min(M,N) columns of matrix U).| -//| Array whose indexes range within | -//| [0..M-1, 0..Min(M,N)-1]. if UNeeded=2, U | -//| contains matrix U wholly. Array whose indexes| -//| range within [0..M-1, 0..M-1]. | -//| VT - if VTNeeded=0, VT isn?t changed, the right | -//| singular vectors are not calculated. | -//| if VTNeeded=1, VT contains right singular | -//| vectors (first min(M,N) rows of matrix V^T). | -//| Array whose indexes range within | -//| [0..min(M,N)-1, 0..N-1]. if VTNeeded=2, VT | -//| contains matrix V^T wholly. Array whose | -//| indexes range within [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static bool CAlglib::RMatrixSVD(CMatrixDouble &a,const int m,const int n, - const int uneeded,const int vtneeded, - const int additionalmemory,double &w[], - CMatrixDouble &u,CMatrixDouble &vt) - { -//--- return result - return(CSingValueDecompose::RMatrixSVD(a,m,n,uneeded,vtneeded,additionalmemory,w,u,vt)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by its LU | -//| decomposition. | -//| Input parameters: | -//| A - LU decomposition of the matrix (output of | -//| RMatrixLU subroutine). | -//| Pivots - table of permutations which were made during | -//| the LU decomposition. | -//| Output of RMatrixLU subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: matrix determinant. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixLUDet(CMatrixDouble &a,int &pivots[],const int n) - { -//--- return result - return(CMatDet::RMatrixLUDet(a,pivots,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by its LU | -//| decomposition. | -//| Input parameters: | -//| A - LU decomposition of the matrix (output of | -//| RMatrixLU subroutine). | -//| Pivots - table of permutations which were made during | -//| the LU decomposition. | -//| Output of RMatrixLU subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: matrix determinant. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixLUDet(CMatrixDouble &a,int &pivots[]) - { -//--- create a variable - int n; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a)) || (CAp::Rows(a)!=CAp::Len(pivots))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); -//--- return result - return(CMatDet::RMatrixLUDet(a,pivots,n)); - } -//+------------------------------------------------------------------+ -//| Calculation of the determinant of a general matrix | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: determinant of matrix A. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixDet(CMatrixDouble &a,const int n) - { -//--- return result - return(CMatDet::RMatrixDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Calculation of the determinant of a general matrix | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: determinant of matrix A. | -//+------------------------------------------------------------------+ -static double CAlglib::RMatrixDet(CMatrixDouble &a) - { -//--- create a variable - int n; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); -//--- return result - return(CMatDet::RMatrixDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by its LU | -//| decomposition. | -//| Input parameters: | -//| A - LU decomposition of the matrix (output of | -//| RMatrixLU subroutine). | -//| Pivots - table of permutations which were made during | -//| the LU decomposition. | -//| Output of RMatrixLU subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: matrix determinant. | -//+------------------------------------------------------------------+ -static al_complex CAlglib::CMatrixLUDet(CMatrixComplex &a,int &pivots[], - const int n) - { -//--- return result - return(CMatDet::CMatrixLUDet(a,pivots,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by its LU | -//| decomposition. | -//| Input parameters: | -//| A - LU decomposition of the matrix (output of | -//| RMatrixLU subroutine). | -//| Pivots - table of permutations which were made during | -//| the LU decomposition. | -//| Output of RMatrixLU subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: matrix determinant. | -//+------------------------------------------------------------------+ -static al_complex CAlglib::CMatrixLUDet(CMatrixComplex &a,int &pivots[]) - { -//--- create a variable - int n; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a)) || (CAp::Rows(a)!=CAp::Len(pivots))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); -//--- return result - return(CMatDet::CMatrixLUDet(a,pivots,n)); - } -//+------------------------------------------------------------------+ -//| Calculation of the determinant of a general matrix | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: determinant of matrix A. | -//+------------------------------------------------------------------+ -static al_complex CAlglib::CMatrixDet(CMatrixComplex &a,const int n) - { -//--- return result - return(CMatDet::CMatrixDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Calculation of the determinant of a general matrix | -//| Input parameters: | -//| A - matrix, array[0..N-1, 0..N-1] | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| Result: determinant of matrix A. | -//+------------------------------------------------------------------+ -static al_complex CAlglib::CMatrixDet(CMatrixComplex &a) - { -//--- create a variable - int n; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); -//--- return result - return(CMatDet::CMatrixDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by the Cholesky | -//| decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition, | -//| output of SMatrixCholesky subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| As the determinant is equal to the product of squares of diagonal| -//| elements, it?s not necessary to specify which triangle - lower | -//| or upper - the matrix is stored in. | -//| Result: | -//| matrix determinant. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixCholeskyDet(CMatrixDouble &a,const int n) - { -//--- return result - return(CMatDet::SPDMatrixCholeskyDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the matrix given by the Cholesky | -//| decomposition. | -//| Input parameters: | -//| A - Cholesky decomposition, | -//| output of SMatrixCholesky subroutine. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| As the determinant is equal to the product of squares of diagonal| -//| elements, it?s not necessary to specify which triangle - lower | -//| or upper - the matrix is stored in. | -//| Result: | -//| matrix determinant. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixCholeskyDet(CMatrixDouble &a) - { -//--- create a variable - int n; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); -//--- return result - return(CMatDet::SPDMatrixCholeskyDet(a,n)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the symmetric positive definite | -//| matrix. | -//| Input parameters: | -//| A - matrix. Array with elements [0..N-1, 0..N-1]. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| IsUpper - (optional) storage type: | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Result: | -//| determinant of matrix A. | -//| If matrix A is not positive definite, exception is thrown. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixDet(CMatrixDouble &a,const int n, - const bool isupper) - { -//--- return result - return(CMatDet::SPDMatrixDet(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Determinant calculation of the symmetric positive definite | -//| matrix. | -//| Input parameters: | -//| A - matrix. Array with elements [0..N-1, 0..N-1]. | -//| N - (optional) size of matrix A: | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, automatically determined from | -//| matrix size (A must be square matrix) | -//| IsUpper - (optional) storage type: | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used/changed by function | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used/changed by function | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//| Result: | -//| determinant of matrix A. | -//| If matrix A is not positive definite, exception is thrown. | -//+------------------------------------------------------------------+ -static double CAlglib::SPDMatrixDet(CMatrixDouble &a) - { -//--- create a variable - int n; - bool isupper; -//--- check - if((CAp::Rows(a)!=CAp::Cols(a))) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- check - if(!CAp::IsSymmetric(a)) - { - Print(__FUNCTION__+": 'a' parameter is not symmetric matrix"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- initialization - n=CAp::Rows(a); - isupper=false; -//--- return result - return(CMatDet::SPDMatrixDet(a,n,isupper)); - } -//+------------------------------------------------------------------+ -//| Algorithm for solving the following generalized symmetric | -//| positive-definite eigenproblem: | -//| A*x = lambda*B*x (1) or | -//| A*B*x = lambda*x (2) or | -//| B*A*x = lambda*x (3). | -//| where A is a symmetric matrix, B - symmetric positive-definite | -//| matrix. The problem is solved by reducing it to an ordinary | -//| symmetric eigenvalue problem. | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper | -//| or lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrices A and B. | -//| IsUpperA - storage format of matrix A. | -//| B - symmetric positive-definite matrix which is | -//| given by its upper or lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| IsUpperB - storage format of matrix B. | -//| ZNeeded - if ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| ProblemType - if ProblemType is equal to: | -//| * 1, the following problem is solved: | -//| A*x = lambda*B*x; | -//| * 2, the following problem is solved: | -//| A*B*x = lambda*x; | -//| * 3, the following problem is solved: | -//| B*A*x = lambda*x. | -//| Output parameters: | -//| D - eigenvalues in ascending order. | -//| Array whose index ranges within [0..N-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| The eigenvectors are stored in matrix | -//| columns. It should be noted that the | -//| eigenvectors in such problems do not form an | -//| orthogonal system. | -//| Result: | -//| True, if the problem was solved successfully. | -//| False, if the error occurred during the Cholesky | -//| decomposition of matrix B (the matrix isn?t | -//| positive-definite) or during the work of the iterative | -//| algorithm for solving the symmetric eigenproblem. | -//| See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixGEVD(CMatrixDouble &a,const int n,const bool isuppera, - CMatrixDouble &b,const bool isupperb, - const int zneeded,const int problemtype, - double &d[],CMatrixDouble &z) - { -//--- return result - return(CSpdGEVD::SMatrixGEVD(a,n,isuppera,b,isupperb,zneeded,problemtype,d,z)); - } -//+------------------------------------------------------------------+ -//| Algorithm for reduction of the following generalized symmetric | -//| positive- definite eigenvalue problem: | -//| A*x = lambda*B*x (1) or | -//| A*B*x = lambda*x (2) or | -//| B*A*x = lambda*x (3) | -//| to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues | -//| of this and the given problems are the same, and the eigenvectors| -//| of the given problem could be obtained by multiplying the | -//| obtained eigenvectors by the transformation matrix x = R*y). | -//| Here A is a symmetric matrix, B - symmetric positive-definite | -//| matrix. | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper | -//| or lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrices A and B. | -//| IsUpperA - storage format of matrix A. | -//| B - symmetric positive-definite matrix which is | -//| given by its upper or lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| IsUpperB - storage format of matrix B. | -//| ProblemType - if ProblemType is equal to: | -//| * 1, the following problem is solved: | -//| A*x = lambda*B*x; | -//| * 2, the following problem is solved: | -//| A*B*x = lambda*x; | -//| * 3, the following problem is solved: | -//| B*A*x = lambda*x. | -//| Output parameters: | -//| A - symmetric matrix which is given by its upper | -//| or lower triangle depending on IsUpperA. | -//| Contains matrix C. Array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| R - upper triangular or low triangular | -//| transformation matrix which is used to obtain| -//| the eigenvectors of a given problem as the | -//| product of eigenvectors of C (from the right)| -//| and matrix R (from the left). If the matrix | -//| is upper triangular, the elements below the | -//| main diagonal are equal to 0 (and vice versa)| -//| Thus, we can perform the multiplication | -//| without taking into account the internal | -//| structure (which is an easier though less | -//| effective way). Array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| IsUpperR - type of matrix R (upper or lower triangular).| -//| Result: | -//| True, if the problem was reduced successfully. | -//| False, if the error occurred during the Cholesky | -//| decomposition of matrix B (the matrix is not | -//| positive-definite). | -//+------------------------------------------------------------------+ -static bool CAlglib::SMatrixGEVDReduce(CMatrixDouble &a,const int n, - const bool isuppera,CMatrixDouble &b, - const bool isupperb,const int problemtype, - CMatrixDouble &r,bool &isupperr) - { -//--- initialization - isupperr=false; -//--- return result - return(CSpdGEVD::SMatrixGEVDReduce(a,n,isuppera,b,isupperb,problemtype,r,isupperr)); - } -//+------------------------------------------------------------------+ -//| Inverse matrix update by the Sherman-Morrison formula | -//| The algorithm updates matrix A^-1 when adding a number to an | -//| element of matrix A. | -//| Input parameters: | -//| InvA - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| UpdRow - row where the element to be updated is stored. | -//| UpdColumn - column where the element to be updated is stored.| -//| UpdVal - a number to be added to the element. | -//| Output parameters: | -//| InvA - inverse of modified matrix A. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInvUpdateSimple(CMatrixDouble &inva,const int n, - const int updrow,const int updcolumn, - const double updval) - { -//--- get result - CInverseUpdate::RMatrixInvUpdateSimple(inva,n,updrow,updcolumn,updval); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inverse matrix update by the Sherman-Morrison formula | -//| The algorithm updates matrix A^-1 when adding a vector to a row | -//| of matrix A. | -//| Input parameters: | -//| InvA - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| UpdRow - the row of A whose vector V was added. | -//| 0 <= Row <= N-1 | -//| V - the vector to be added to a row. | -//| Array whose index ranges within [0..N-1]. | -//| Output parameters: | -//| InvA - inverse of modified matrix A. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInvUpdateRow(CMatrixDouble &inva,const int n, - const int updrow,double &v[]) - { -//--- get result - CInverseUpdate::RMatrixInvUpdateRow(inva,n,updrow,v); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inverse matrix update by the Sherman-Morrison formula | -//| The algorithm updates matrix A^-1 when adding a vector to a | -//| column of matrix A. | -//| Input parameters: | -//| InvA - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| UpdColumn - the column of A whose vector U was added. | -//| 0 <= UpdColumn <= N-1 | -//| U - the vector to be added to a column. | -//| Array whose index ranges within [0..N-1]. | -//| Output parameters: | -//| InvA - inverse of modified matrix A. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInvUpdateColumn(CMatrixDouble &inva,const int n, - const int updcolumn,double &u[]) - { -//--- get result - CInverseUpdate::RMatrixInvUpdateColumn(inva,n,updcolumn,u); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Inverse matrix update by the Sherman-Morrison formula | -//| The algorithm computes the inverse of matrix A+u*v? by using the | -//| given matrix A^-1 and the vectors u and v. | -//| Input parameters: | -//| InvA - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| U - the vector modifying the matrix. | -//| Array whose index ranges within [0..N-1]. | -//| V - the vector modifying the matrix. | -//| Array whose index ranges within [0..N-1]. | -//| Output parameters: | -//| InvA - inverse of matrix A + u*v'. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixInvUpdateUV(CMatrixDouble &inva,const int n, - double &u[],double &v[]) - { -//--- get result - CInverseUpdate::RMatrixInvUpdateUV(inva,n,u,v); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Subroutine performing the Schur decomposition of a general matrix| -//| by using the QR algorithm with multiple shifts. | -//| The source matrix A is represented as S'*A*S = T, where S is an | -//| orthogonal matrix (Schur vectors), T - upper quasi-triangular | -//| matrix (with blocks of sizes 1x1 and 2x2 on the main diagonal). | -//| Input parameters: | -//| A - matrix to be decomposed. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//| N - size of A, N>=0. | -//| Output parameters: | -//| A - contains matrix T. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//| S - contains Schur vectors. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//| Note 1: | -//| The block structure of matrix T can be easily recognized: | -//| since all the elements below the blocks are zeros, the | -//| elements a[i+1,i] which are equal to 0 show the block border.| -//| Note 2: | -//| The algorithm performance depends on the value of the | -//| internal parameter NS of the InternalSchurDecomposition | -//| subroutine which defines the number of shifts in the QR | -//| algorithm (similarly to the block width in block-matrix | -//| algorithms in linear algebra). If you require maximum | -//| performance on your machine, it is recommended to adjust | -//| this parameter manually. | -//| Result: | -//| True, | -//| if the algorithm has converged and parameters A and S | -//| contain the result. | -//| False, | -//| if the algorithm has not converged. | -//| Algorithm implemented on the basis of the DHSEQR subroutine | -//| (LAPACK 3.0 library). | -//+------------------------------------------------------------------+ -static bool CAlglib::RMatrixSchur(CMatrixDouble &a,const int n,CMatrixDouble &s) - { -//--- return result - return(CSchur::RMatrixSchur(a,n,s)); - } -//+------------------------------------------------------------------+ -//| NONLINEAR CONJUGATE GRADIENT METHOD | -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments by using | -//| one of the nonlinear conjugate gradient methods. | -//| These CG methods are globally convergent (even on non-convex | -//| functions) as long as grad(f) is Lipschitz continuous in a some | -//| neighborhood of the L = { x : f(x)<=f(x0) }. | -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function value F and its gradient G (simultaneously) at given | -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with MinCGCreate() call | -//| 2. User tunes solver parameters with MinCGSetCond(), | -//| MinCGSetStpMax() and other functions | -//| 3. User calls MinCGOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 4. User calls MinCGResults() to get solution | -//| 5. Optionally, user may call MinCGRestartFrom() to solve another | -//| problem with same N but another starting point and/or another | -//| function. MinCGRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGCreate(const int n,double &x[],CMinCGStateShell &state) - { -//--- function call - CMinCG::MinCGCreate(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| NONLINEAR CONJUGATE GRADIENT METHOD | -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments by using | -//| one of the nonlinear conjugate gradient methods. | -//| These CG methods are globally convergent (even on non-convex | -//| functions) as long as grad(f) is Lipschitz continuous in a some | -//| neighborhood of the L = { x : f(x)<=f(x0) }. | -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function value F and its gradient G (simultaneously) at given | -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with MinCGCreate() call | -//| 2. User tunes solver parameters with MinCGSetCond(), | -//| MinCGSetStpMax() and other functions | -//| 3. User calls MinCGOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 4. User calls MinCGResults() to get solution | -//| 5. Optionally, user may call MinCGRestartFrom() to solve another | -//| problem with same N but another starting point and/or another | -//| function. MinCGRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGCreate(double &x[],CMinCGStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinCG::MinCGCreate(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinCGCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinCGCreate() in | -//| order to get more information about creation of CG optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to | -//| DiffStep*S[I] where S[] is scaling vector which can be set by | -//| MinCGSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. L-BFGS needs | -//| exact gradient values. Imprecise gradient may slow down | -//| convergence, especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping | -//| on small- dimensional problems only, and to implement | -//| analytical gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGCreateF(const int n,double &x[],double diffstep, - CMinCGStateShell &state) - { -//--- function call - CMinCG::MinCGCreateF(n,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinCGCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinCGCreate() in | -//| order to get more information about creation of CG optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to | -//| DiffStep*S[I] where S[] is scaling vector which can be set by | -//| MinCGSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. L-BFGS needs | -//| exact gradient values. Imprecise gradient may slow down | -//| convergence, especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping | -//| on small- dimensional problems only, and to implement | -//| analytical gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGCreateF(double &x[],double diffstep, - CMinCGStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinCG::MinCGCreateF(n,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for CG optimization | -//| algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by MinCGSetScale()| -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetCond(CMinCGStateShell &state,double epsg, - double epsf,double epsx,int maxits) - { -//--- function call - CMinCG::MinCGSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for CG optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of CG | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the CG too) scaling is NOT a form of | -//| preconditioning. It just affects stopping conditions. You should | -//| set preconditioner by separate call to one of the | -//| MinCGSetPrec...() functions. | -//| There is special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should understand| -//| that scaling is not the same thing as preconditioning - these are| -//| two different, although related forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetScale(CMinCGStateShell &state,double &s[]) - { -//--- function call - CMinCG::MinCGSetScale(state.GetInnerObj(),s); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinCGOptimize(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetXRep(CMinCGStateShell &state,bool needxrep) - { -//--- function call - CMinCG::MinCGSetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets CG algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| CGType - algorithm type: | -//| * -1 automatic selection of the best | -//| algorithm | -//| * 0 DY (Dai and Yuan) algorithm | -//| * 1 Hybrid DY-HS algorithm | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetCGType(CMinCGStateShell &state,int cgtype) - { -//--- function call - CMinCG::MinCGSetCGType(state.GetInnerObj(),cgtype); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetStpMax(CMinCGStateShell &state,double stpmax) - { -//--- function call - CMinCG::MinCGSetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function allows to suggest initial step length to the CG | -//| algorithm. | -//| Suggested step length is used as starting point for the line | -//| search. It can be useful when you have badly scaled problem, i.e.| -//| when ||grad|| (which is used as initial estimate for the first | -//| step) is many orders of magnitude different from the desired | -//| step. | -//| Line search may fail on such problems without good estimate of | -//| initial step length. Imagine, for example, problem with | -//| ||grad||=10^50 and desired step equal to 0.1 Line search | -//| function will use 10^50 as initial step, then it will decrease | -//| step length by 2 (up to 20 attempts) and will get 10^44, which is| -//| still too large. | -//| This function allows us to tell than line search should be | -//| started from some moderate step length, like 1.0, so algorithm | -//| will be able to detect desired step length in a several searches.| -//| Default behavior (when no step is suggested) is to use | -//| preconditioner, if it is available, to generate initial estimate | -//| of step length. | -//| This function influences only first iteration of algorithm. It | -//| should be called between MinCGCreate/MinCGRestartFrom() call and | -//| MinCGOptimize call. Suggested step is ignored if you have | -//| preconditioner. | -//| INPUT PARAMETERS: | -//| State - structure used to store algorithm state. | -//| Stp - initial estimate of the step length. | -//| Can be zero (no estimate). | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSuggestStep(CMinCGStateShell &state,double stp) - { -//--- function call - CMinCG::MinCGSuggestStep(state.GetInnerObj(),stp); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: preconditioning is turned | -//| off. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetPrecDefault(CMinCGStateShell &state) - { -//--- function call - CMinCG::MinCGSetPrecDefault(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: diagonal of approximate | -//| Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| D - diagonal of the approximate Hessian, | -//| array[0..N-1], (if larger, only leading N | -//| elements are used). | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//| NOTE 2: D[i] should be positive. Exception will be thrown | -//| otherwise. | -//| NOTE 3: you should pass diagonal of approximate Hessian - NOT | -//| ITS INVERSE. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetPrecDiag(CMinCGStateShell &state,double &d[]) - { -//--- function call - CMinCG::MinCGSetPrecDiag(state.GetInnerObj(),d); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, | -//| with H[i] = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinCGSetScale() call (before or after MinCGSetPrecScale() call). | -//| Without knowledge of the scale of your variables scale-based | -//| preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGSetPrecScale(CMinCGStateShell &state) - { -//--- function call - CMinCG::MinCGSetPrecScale(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::MinCGIteration(CMinCGStateShell &state) - { -//--- return result - return(CMinCG::MinCGIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which| -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinCGCreate() for analytical gradient or | -//| MinCGCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinCGOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinCGOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinCGOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinCGOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinCGCreateF() | work FAIL | -//| MinCGCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinCGOptimize() version. Attemps to use | -//| such combination (for example, to create optimizer with | -//| MinCGCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGOptimize(CMinCGStateShell &state,CNDimensional_Func &func, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinCGIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which| -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinCGCreate() for analytical gradient or | -//| MinCGCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinCGOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinCGOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinCGOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinCGOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinCGCreateF() | work FAIL | -//| MinCGCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinCGOptimize() version. Attemps to use | -//| such combination (for example, to create optimizer with | -//| MinCGCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGOptimize(CMinCGStateShell &state,CNDimensional_Grad &grad, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinCGIteration(state)) - { - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| Conjugate gradient results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * 1 relative function improvement is no | -//| more than EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient norm is no more than EpsG | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible, we return best X found | -//| so far | -//| * 8 terminated by user | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGResults(CMinCGStateShell &state,double &x[], - CMinCGReportShell &rep) - { -//--- function call - CMinCG::MinCGResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Conjugate gradient results | -//| Buffered implementation of MinCGResults(), which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer.It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGResultsBuf(CMinCGStateShell &state,double &x[], - CMinCGReportShell &rep) - { -//--- function call - CMinCG::MinCGResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts CG algorithm from new point. All | -//| optimization parameters are left unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure used to store algorithm state. | -//| X - new starting point. | -//+------------------------------------------------------------------+ -static void CAlglib::MinCGRestartFrom(CMinCGStateShell &state,double &x[]) - { -//--- function call - CMinCG::MinCGRestartFrom(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| BOUND CONSTRAINED OPTIMIZATION | -//| WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS| -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments subject to | -//| any combination of: | -//| * bound constraints | -//| * linear inequality constraints | -//| * linear equality constraints | -//| REQUIREMENTS: | -//| * user must provide function value and gradient | -//| * starting point X0 must be feasible or | -//| not too far away from the feasible set | -//| * grad(f) must be Lipschitz continuous on a level set: | -//| L = { x : f(x)<=f(x0) } | -//| * function must be defined everywhere on the feasible set F | -//| USAGE: | -//| Constrained optimization if far more complex than the | -//| unconstrained one. Here we give very brief outline of the BLEIC | -//| optimizer. We strongly recommend you to read examples in the | -//| ALGLIB Reference Manual and to read ALGLIB User Guide on | -//| optimization, which is available at | -//| http://www.alglib.net/optimization/ | -//| 1. User initializes algorithm state with MinBLEICCreate() call | -//| 2. USer adds boundary and/or linear constraints by calling | -//| MinBLEICSetBC() and MinBLEICSetLC() functions. | -//| 3. User sets stopping conditions for underlying unconstrained | -//| solver with MinBLEICSetInnerCond() call. | -//| This function controls accuracy of underlying optimization | -//| algorithm. | -//| 4. User sets stopping conditions for outer iteration by calling | -//| MinBLEICSetOuterCond() function. | -//| This function controls handling of boundary and inequality | -//| constraints. | -//| 5. Additionally, user may set limit on number of internal | -//| iterations by MinBLEICSetMaxIts() call. | -//| This function allows to prevent algorithm from looping | -//| forever. | -//| 6. User calls MinBLEICOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function | -//| which calculates F/G. | -//| 7. User calls MinBLEICResults() to get solution | -//| 8. Optionally user may call MinBLEICRestartFrom() to solve | -//| another problem with same N but another starting point. | -//| MinBLEICRestartFrom() allows to reuse already initialized | -//| structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size ofX | -//| X - starting point, array[N]: | -//| * it is better to set X to a feasible point | -//| * but X can be infeasible, in which case | -//| algorithm will try to find feasible point | -//| first, using X as initial approximation. | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICCreate(const int n,double &x[],CMinBLEICStateShell &state) - { -//--- function call - CMinBLEIC::MinBLEICCreate(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| BOUND CONSTRAINED OPTIMIZATION | -//| WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS| -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments subject to | -//| any combination of: | -//| * bound constraints | -//| * linear inequality constraints | -//| * linear equality constraints | -//| REQUIREMENTS: | -//| * user must provide function value and gradient | -//| * starting point X0 must be feasible or | -//| not too far away from the feasible set | -//| * grad(f) must be Lipschitz continuous on a level set: | -//| L = { x : f(x)<=f(x0) } | -//| * function must be defined everywhere on the feasible set F | -//| USAGE: | -//| Constrained optimization if far more complex than the | -//| unconstrained one. Here we give very brief outline of the BLEIC | -//| optimizer. We strongly recommend you to read examples in the | -//| ALGLIB Reference Manual and to read ALGLIB User Guide on | -//| optimization, which is available at | -//| http://www.alglib.net/optimization/ | -//| 1. User initializes algorithm state with MinBLEICCreate() call | -//| 2. USer adds boundary and/or linear constraints by calling | -//| MinBLEICSetBC() and MinBLEICSetLC() functions. | -//| 3. User sets stopping conditions for underlying unconstrained | -//| solver with MinBLEICSetInnerCond() call. | -//| This function controls accuracy of underlying optimization | -//| algorithm. | -//| 4. User sets stopping conditions for outer iteration by calling | -//| MinBLEICSetOuterCond() function. | -//| This function controls handling of boundary and inequality | -//| constraints. | -//| 5. Additionally, user may set limit on number of internal | -//| iterations by MinBLEICSetMaxIts() call. | -//| This function allows to prevent algorithm from looping | -//| forever. | -//| 6. User calls MinBLEICOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function | -//| which calculates F/G. | -//| 7. User calls MinBLEICResults() to get solution | -//| 8. Optionally user may call MinBLEICRestartFrom() to solve | -//| another problem with same N but another starting point. | -//| MinBLEICRestartFrom() allows to reuse already initialized | -//| structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size ofX | -//| X - starting point, array[N]: | -//| * it is better to set X to a feasible point | -//| * but X can be infeasible, in which case | -//| algorithm will try to find feasible point | -//| first, using X as initial approximation. | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICCreate(double &x[],CMinBLEICStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinBLEIC::MinBLEICCreate(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinBLEICCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinBLEICCreate() | -//| in order to get more information about creation of BLEIC | -//| optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinBLEICSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. CG needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small - dimensional problems only, and to implement analytical| -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICCreateF(const int n,double &x[],double diffstep, - CMinBLEICStateShell &state) - { -//--- function call - CMinBLEIC::MinBLEICCreateF(n,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinBLEICCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinBLEICCreate() | -//| in order to get more information about creation of BLEIC | -//| optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinBLEICSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. CG needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small - dimensional problems only, and to implement analytical| -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICCreateF(double &x[],double diffstep, - CMinBLEICStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinBLEIC::MinBLEICCreateF(n,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets boundary constraints for BLEIC optimizer. | -//| Boundary constraints are inactive by default (after initial | -//| creation). They are preserved after algorithm restart with | -//| MinBLEICRestartFrom(). | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| BndL - lower bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very small number or -INF. | -//| BndU - upper bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very large number or +INF. | -//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case | -//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. | -//| NOTE 2: this solver has following useful properties: | -//| * bound constraints are always satisfied exactly | -//| * function is evaluated only INSIDE area specified by bound | -//| constraints, even when numerical differentiation is used | -//| (algorithm adjusts nodes according to boundary constraints) | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetBC(CMinBLEICStateShell &state,double &bndl[], - double &bndu[]) - { -//--- function call - CMinBLEIC::MinBLEICSetBC(state.GetInnerObj(),bndl,bndu); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets linear constraints for BLEIC optimizer. | -//| Linear constraints are inactive by default (after initial | -//| creation). They are preserved after algorithm restart with | -//| MinBLEICRestartFrom(). | -//| INPUT PARAMETERS: | -//| State - structure previously allocated with | -//| MinBLEICCreate call. | -//| C - linear constraints, array[K,N+1]. | -//| Each row of C represents one constraint, either | -//| equality or inequality (see below): | -//| * first N elements correspond to coefficients, | -//| * last element corresponds to the right part. | -//| All elements of C (including right part) must be | -//| finite. | -//| CT - type of constraints, array[K]: | -//| * if CT[i]>0, then I-th constraint is | -//| C[i,*]*x >= C[i,n+1] | -//| * if CT[i]=0, then I-th constraint is | -//| C[i,*]*x = C[i,n+1] | -//| * if CT[i]<0, then I-th constraint is | -//| C[i,*]*x <= C[i,n+1] | -//| K - number of equality/inequality constraints, K>=0: | -//| * if given, only leading K elements of C/CT are | -//| used | -//| * if not given, automatically determined from | -//| sizes of C/CT | -//| NOTE 1: linear (non-bound) constraints are satisfied only | -//| approximately: | -//| * there always exists some minor violation (about Epsilon in | -//| magnitude) due to rounding errors | -//| * numerical differentiation, if used, may lead to function | -//| evaluations outside of the feasible area, because algorithm | -//| does NOT change numerical differentiation formula according to | -//| linear constraints. | -//| If you want constraints to be satisfied exactly, try to | -//| reformulate your problem in such manner that all constraints will| -//| become boundary ones (this kind of constraints is always | -//| satisfied exactly, both in the final solution and in all | -//| intermediate points). | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c, - int &ct[],const int k) - { -//--- function call - CMinBLEIC::MinBLEICSetLC(state.GetInnerObj(),c,ct,k); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets linear constraints for BLEIC optimizer. | -//| Linear constraints are inactive by default (after initial | -//| creation). They are preserved after algorithm restart with | -//| MinBLEICRestartFrom(). | -//| INPUT PARAMETERS: | -//| State - structure previously allocated with | -//| MinBLEICCreate call. | -//| C - linear constraints, array[K,N+1]. | -//| Each row of C represents one constraint, either | -//| equality or inequality (see below): | -//| * first N elements correspond to coefficients, | -//| * last element corresponds to the right part. | -//| All elements of C (including right part) must be | -//| finite. | -//| CT - type of constraints, array[K]: | -//| * if CT[i]>0, then I-th constraint is | -//| C[i,*]*x >= C[i,n+1] | -//| * if CT[i]=0, then I-th constraint is | -//| C[i,*]*x = C[i,n+1] | -//| * if CT[i]<0, then I-th constraint is | -//| C[i,*]*x <= C[i,n+1] | -//| K - number of equality/inequality constraints, K>=0: | -//| * if given, only leading K elements of C/CT are | -//| used | -//| * if not given, automatically determined from | -//| sizes of C/CT | -//| NOTE 1: linear (non-bound) constraints are satisfied only | -//| approximately: | -//| * there always exists some minor violation (about Epsilon in | -//| magnitude) due to rounding errors | -//| * numerical differentiation, if used, may lead to function | -//| evaluations outside of the feasible area, because algorithm | -//| does NOT change numerical differentiation formula according to | -//| linear constraints. | -//| If you want constraints to be satisfied exactly, try to | -//| reformulate your problem in such manner that all constraints will| -//| become boundary ones (this kind of constraints is always | -//| satisfied exactly, both in the final solution and in all | -//| intermediate points). | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c, - int &ct[]) - { -//--- create a variable - int k; -//--- check - if(CAp::Rows(c)!=CAp::Len(ct)) - { - Print(__FUNCTION__+": looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - k=CAp::Rows(c); -//--- function call - CMinBLEIC::MinBLEICSetLC(state.GetInnerObj(),c,ct,k); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for the underlying | -//| nonlinear CG optimizer. It controls overall accuracy of solution.| -//| These conditions should be strict enough in order for algorithm | -//| to converge. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by | -//| MinBLEICSetScale() | -//| Passing EpsG=0, EpsF=0 and EpsX=0 (simultaneously) will lead to | -//| automatic stopping criterion selection. | -//| These conditions are used to terminate inner iterations. However,| -//| you need to tune termination conditions for outer iterations too.| -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetInnerCond(CMinBLEICStateShell &state, - const double epsg, - const double epsf, - const double epsx) - { -//--- function call - CMinBLEIC::MinBLEICSetInnerCond(state.GetInnerObj(),epsg,epsf,epsx); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for outer iteration of | -//| BLEIC algo. | -//| These conditions control accuracy of constraint handling and | -//| amount of infeasibility allowed in the solution. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsX - >0, stopping condition on outer iteration step | -//| length | -//| EpsI - >0, stopping condition on infeasibility | -//| Both EpsX and EpsI must be non-zero. | -//| MEANING OF EpsX | -//| EpsX is a stopping condition for outer iterations. Algorithm will| -//| stop when solution of the current modified subproblem will be | -//| within EpsX (using 2-norm) of the previous solution. | -//| MEANING OF EpsI | -//| EpsI controls feasibility properties - algorithm won't stop until| -//| all inequality constraints will be satisfied with error (distance| -//| from current point to the feasible area) at most EpsI. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetOuterCond(CMinBLEICStateShell &state, - const double epsx,const double epsi) - { -//--- function call - CMinBLEIC::MinBLEICSetOuterCond(state.GetInnerObj(),epsx,epsi); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for BLEIC optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of the | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the BLEIC too) scaling is NOT a form | -//| of preconditioning. It just affects stopping conditions. You | -//| should set preconditioner by separate call to one of the | -//| MinBLEICSetPrec...() functions. | -//| There is a special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should understand| -//| that scaling is not the same thing as preconditioning - these are| -//| two different, although related forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetScale(CMinBLEICStateShell &state,double &s[]) - { -//--- function call - CMinBLEIC::MinBLEICSetScale(state.GetInnerObj(),s); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: preconditioning is turned | -//| off. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetPrecDefault(CMinBLEICStateShell &state) - { -//--- function call - CMinBLEIC::MinBLEICSetPrecDefault(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: diagonal of approximate | -//| Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| D - diagonal of the approximate Hessian, | -//| array[0..N-1], (if larger, only leading N | -//| elements are used). | -//| NOTE 1: D[i] should be positive. Exception will be thrown | -//| otherwise. | -//| NOTE 2: you should pass diagonal of approximate Hessian - NOT | -//| ITS INVERSE. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetPrecDiag(CMinBLEICStateShell &state, - double &d[]) - { -//--- function call - CMinBLEIC::MinBLEICSetPrecDiag(state.GetInnerObj(),d); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, with H[i] = | -//| = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinBLEICSetScale() call (before or after MinBLEICSetPrecScale() | -//| call). Without knowledge of the scale of your variables | -//| scale-based preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetPrecScale(CMinBLEICStateShell &state) - { -//--- function call - CMinBLEIC::MinBLEICSetPrecScale(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function allows to stop algorithm after specified number of | -//| inner iterations. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| MaxIts - maximum number of inner iterations. | -//| If MaxIts=0, the number of iterations is | -//| unlimited. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetMaxIts(CMinBLEICStateShell &state, - const int maxits) - { -//--- function call - CMinBLEIC::MinBLEICSetMaxIts(state.GetInnerObj(),maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinBLEICOptimize(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetXRep(CMinBLEICStateShell &state,bool needxrep) - { -//--- function call - CMinBLEIC::MinBLEICSetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| IMPORTANT: this feature is hard to combine with preconditioning. | -//| You can't set upper limit on step length, when you solve | -//| optimization problem with linear (non-boundary) constraints AND | -//| preconditioner turned on. | -//| When non-boundary constraints are present, you have to either a) | -//| use preconditioner, or b) use upper limit on step length. YOU | -//| CAN'T USE BOTH! In this case algorithm will terminate with | -//| appropriate error code. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which lead to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetStpMax(CMinBLEICStateShell &state,double stpmax) - { -//--- function call - CMinBLEIC::MinBLEICSetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::MinBLEICIteration(CMinBLEICStateShell &state) - { -//--- return result - return(CMinBLEIC::MinBLEICIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which | -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinBLEICCreate() for analytical gradient or | -//| MinBLEICCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinBLEICOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinBLEICOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinBLEICOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinBLEICOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinBLEICCreateF() | work FAIL | -//| MinBLEICCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinBLEICOptimize() version. Attemps to | -//| use such combination (for example, to create optimizer with | -//| MinBLEICCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Func &func, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinBLEICIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which | -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinBLEICCreate() for analytical gradient or | -//| MinBLEICCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinBLEICOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinBLEICOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinBLEICOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinBLEICOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinBLEICCreateF() | work FAIL | -//| MinBLEICCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinBLEICOptimize() version. Attemps to | -//| use such combination (for example, to create optimizer with | -//| MinBLEICCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Grad &grad, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinBLEICIteration(state)) - { - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| BLEIC results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report. You should check Rep. | -//| TerminationType in order to distinguish | -//| successful termination from unsuccessful one. | -//| More information about fields of this structure | -//| can be found in the comments on MinBLEICReport | -//| datatype. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICResults(CMinBLEICStateShell &state,double &x[], - CMinBLEICReportShell &rep) - { -//--- function call - CMinBLEIC::MinBLEICResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| BLEIC results | -//| Buffered implementation of MinBLEICResults() which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICResultsBuf(CMinBLEICStateShell &state,double &x[], - CMinBLEICReportShell &rep) - { -//--- function call - CMinBLEIC::MinBLEICResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts algorithm from new point. | -//| All optimization parameters (including constraints) are left | -//| unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure previously allocated with | -//| MinBLEICCreate call. | -//| X - new starting point. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICRestartFrom(CMinBLEICStateShell &state, - double &x[]) - { -//--- function call - CMinBLEIC::MinBLEICRestartFrom(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION | -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments by using a | -//| quasi - Newton method (LBFGS scheme) which is optimized to use a | -//| minimum amount of memory. | -//| The subroutine generates the approximation of an inverse Hessian | -//| matrix by using information about the last M steps of the | -//| algorithm (instead of N). It lessens a required amount of memory | -//| from a value of order N^2 to a value of order 2*N*M. | -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function value F and its gradient G (simultaneously) at given | -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with MinLBFGSCreate() call | -//| 2. User tunes solver parameters with MinLBFGSSetCond() | -//| MinLBFGSSetStpMax() and other functions | -//| 3. User calls MinLBFGSOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 4. User calls MinLBFGSResults() to get solution | -//| 5. Optionally user may call MinLBFGSRestartFrom() to solve | -//| another problem with same N/M but another starting point | -//| and/or another function. MinLBFGSRestartFrom() allows to reuse| -//| already initialized structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension. N>0 | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause | -//| a fall in the performance. M<=N. | -//| X - initial solution approximation, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLBFGSSetCond() | -//| function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLBFGSSetStpMax() function to | -//| bound algorithm's steps. However, L-BFGS rarely needs such a | -//| tuning. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSCreate(const int n,const int m,double &x[], - CMinLBFGSStateShell &state) - { -//--- function call - CMinLBFGS::MinLBFGSCreate(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION | -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments by using a | -//| quasi - Newton method (LBFGS scheme) which is optimized to use a | -//| minimum amount of memory. | -//| The subroutine generates the approximation of an inverse Hessian | -//| matrix by using information about the last M steps of the | -//| algorithm (instead of N). It lessens a required amount of memory | -//| from a value of order N^2 to a value of order 2*N*M. | -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function value F and its gradient G (simultaneously) at given | -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with MinLBFGSCreate() call | -//| 2. User tunes solver parameters with MinLBFGSSetCond() | -//| MinLBFGSSetStpMax() and other functions | -//| 3. User calls MinLBFGSOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 4. User calls MinLBFGSResults() to get solution | -//| 5. Optionally user may call MinLBFGSRestartFrom() to solve | -//| another problem with same N/M but another starting point | -//| and/or another function. MinLBFGSRestartFrom() allows to reuse| -//| already initialized structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension. N>0 | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause | -//| a fall in the performance. M<=N. | -//| X - initial solution approximation, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLBFGSSetCond() | -//| function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLBFGSSetStpMax() function to | -//| bound algorithm's steps. However, L-BFGS rarely needs such a | -//| tuning. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSCreate(const int m,double &x[],CMinLBFGSStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLBFGS::MinLBFGSCreate(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinLBFGSCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinLBFGSCreate() | -//| in order to get more information about creation of LBFGS | -//| optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause a| -//| fall in the performance. M<=N. | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinLBFGSSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. LBFGS needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small- dimensional problems only, and to implement analytical | -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSCreateF(const int n,const int m,double &x[], - const double diffstep,CMinLBFGSStateShell &state) - { -//--- function call - CMinLBFGS::MinLBFGSCreateF(n,m,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| The subroutine is finite difference variant of MinLBFGSCreate(). | -//| It uses finite differences in order to differentiate target | -//| function. | -//| Description below contains information which is specific to this | -//| function only. We recommend to read comments on MinLBFGSCreate() | -//| in order to get more information about creation of LBFGS | -//| optimizer. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause a| -//| fall in the performance. M<=N. | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinLBFGSSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. LBFGS needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small- dimensional problems only, and to implement analytical | -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSCreateF(const int m,double &x[],const double diffstep, - CMinLBFGSStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLBFGS::MinLBFGSCreateF(n,m,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for L-BFGS optimization | -//| algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by | -//| MinLBFGSSetScale() | -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetCond(CMinLBFGSStateShell &state,const double epsg, - const double epsf,const double epsx, - const int maxits) - { -//--- function call - CMinLBFGS::MinLBFGSSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinLBFGSOptimize(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetXRep(CMinLBFGSStateShell &state,const bool needxrep) - { -//--- function call - CMinLBFGS::MinLBFGSSetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0 | -//| (default), if you don't want to limit step | -//| length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetStpMax(CMinLBFGSStateShell &state,const double stpmax) - { -//--- function call - CMinLBFGS::MinLBFGSSetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for LBFGS optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of the | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the LBFGS too) scaling is NOT a form | -//| of preconditioning. It just affects stopping conditions. You | -//| should set preconditioner by separate call to one of the | -//| MinLBFGSSetPrec...() functions. | -//| There is special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should | -//| understand that scaling is not the same thing as | -//| preconditioning - these are two different, although related | -//| forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetScale(CMinLBFGSStateShell &state,double &s[]) - { -//--- function call - CMinLBFGS::MinLBFGSSetScale(state.GetInnerObj(),s); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: default preconditioner | -//| (simple scaling, same for all elements of X) is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetPrecDefault(CMinLBFGSStateShell &state) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecDefault(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: Cholesky factorization of | -//| approximate Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| P - triangular preconditioner, Cholesky factorization| -//| of the approximate Hessian. array[0..N-1,0..N-1],| -//| (if larger, only leading N elements are used). | -//| IsUpper - whether upper or lower triangle of P is given | -//| (other triangle is not referenced) | -//| After call to this function preconditioner is changed to P (P is | -//| copied into the internal buffer). | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//| NOTE 2: P should be nonsingular. Exception will be thrown | -//| otherwise. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetPrecCholesky(CMinLBFGSStateShell &state, - CMatrixDouble &p,const bool isupper) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecCholesky(state.GetInnerObj(),p,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: diagonal of approximate | -//| Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| D - diagonal of the approximate Hessian, | -//| array[0..N-1], (if larger, only leading N | -//| elements are used). | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//| NOTE 2: D[i] should be positive. Exception will be thrown | -//| otherwise. | -//| NOTE 3: you should pass diagonal of approximate Hessian - NOT | -//| ITS INVERSE. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetPrecDiag(CMinLBFGSStateShell &state,double &d[]) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecDiag(state.GetInnerObj(),d); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, with H[i] = | -//| = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinLBFGSSetScale() call (before or after MinLBFGSSetPrecScale() | -//| call). Without knowledge of the scale of your variables | -//| scale-based preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetPrecScale(CMinLBFGSStateShell &state) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecScale(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::MinLBFGSIteration(CMinLBFGSStateShell &state) - { -//--- return result - return(CMinLBFGS::MinLBFGSIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which | -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinLBFGSCreate() for analytical gradient or | -//| MinLBFGSCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinLBFGSOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinLBFGSOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinLBFGSOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinLBFGSOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinLBFGSCreateF() | work FAIL | -//| MinLBFGSCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinLBFGSOptimize() version. Attemps to | -//| use such combination (for example, to create optimizer with | -//| MinLBFGSCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Func &func, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLBFGSIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which | -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinLBFGSCreate() for analytical gradient or | -//| MinLBFGSCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinLBFGSOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinLBFGSOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinLBFGSOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinLBFGSOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinLBFGSCreateF() | work FAIL | -//| MinLBFGSCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinLBFGSOptimize() version. Attemps to | -//| use such combination (for example, to create optimizer with | -//| MinLBFGSCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Grad &grad, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLBFGSIteration(state)) - { - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| L-BFGS algorithm results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * -2 rounding errors prevent further | -//| improvement. X contains best point | -//| found. | -//| * -1 incorrect parameters were specified | -//| * 1 relative function improvement is no | -//| more than EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient norm is no more than EpsG | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSResults(CMinLBFGSStateShell &state,double &x[], - CMinLBFGSReportShell &rep) - { -//--- function call - CMinLBFGS::MinLBFGSResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| L-BFGS algorithm results | -//| Buffered implementation of MinLBFGSResults which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSresultsbuf(CMinLBFGSStateShell &state,double &x[], - CMinLBFGSReportShell &rep) - { -//--- function call - CMinLBFGS::MinLBFGSresultsbuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts LBFGS algorithm from new point. All | -//| optimization parameters are left unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure used to store algorithm state | -//| X - new starting point. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSRestartFrom(CMinLBFGSStateShell &state,double &x[]) - { -//--- function call - CMinLBFGS::MinLBFGSRestartFrom(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| CONSTRAINED QUADRATIC PROGRAMMING | -//| The subroutine creates QP optimizer. After initial creation, it | -//| contains default optimization problem with zero quadratic and | -//| linear terms and no constraints. You should set quadratic/linear | -//| terms with calls to functions provided by MinQP subpackage. | -//| INPUT PARAMETERS: | -//| N - problem size | -//| OUTPUT PARAMETERS: | -//| State - optimizer with zero quadratic/linear terms | -//| and no constraints | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPCreate(const int n,CMinQPStateShell &state) - { -//--- function call - CMinQP::MinQPCreate(n,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets linear term for QP solver. | -//| By default, linear term is zero. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| B - linear term, array[N]. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetLinearTerm(CMinQPStateShell &state,double &b[]) - { -//--- function call - CMinQP::MinQPSetLinearTerm(state.GetInnerObj(),b); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets quadratic term for QP solver. | -//| By default quadratic term is zero. | -//| IMPORTANT: this solver minimizes following function: | -//| f(x) = 0.5*x'*A*x + b'*x. | -//| Note that quadratic term has 0.5 before it. So if you want to | -//| minimize | -//| f(x) = x^2 + x | -//| you should rewrite your problem as follows: | -//| f(x) = 0.5*(2*x^2) + x | -//| and your matrix A will be equal to [[2.0]], not to [[1.0]] | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| A - matrix, array[N,N] | -//| IsUpper - (optional) storage type: | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a, - const bool isupper) - { -//--- function call - CMinQP::MinQPSetQuadraticTerm(state.GetInnerObj(),a,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets quadratic term for QP solver. | -//| By default quadratic term is zero. | -//| IMPORTANT: this solver minimizes following function: | -//| f(x) = 0.5*x'*A*x + b'*x. | -//| Note that quadratic term has 0.5 before it. So if you want to | -//| minimize | -//| f(x) = x^2 + x | -//| you should rewrite your problem as follows: | -//| f(x) = 0.5*(2*x^2) + x | -//| and your matrix A will be equal to [[2.0]], not to [[1.0]] | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| A - matrix, array[N,N] | -//| IsUpper - (optional) storage type: | -//| * if True, symmetric matrix A is given by its | -//| upper triangle, and the lower triangle isn?t | -//| used | -//| * if False, symmetric matrix A is given by its | -//| lower triangle, and the upper triangle isn?t | -//| used | -//| * if not given, both lower and upper triangles | -//| must be filled. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a) - { -//--- create a variable - bool isupper; -//--- check - if(!CAp::IsSymmetric(a)) - { - Print(__FUNCTION__+": 'a' parameter is not symmetric matrix"); - CAp::exception_happened=true; - return; - } -//--- initialization - isupper=false; -//--- function call - CMinQP::MinQPSetQuadraticTerm(state.GetInnerObj(),a,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets starting point for QP solver. It is useful to | -//| have good initial approximation to the solution, because it will | -//| increase speed of convergence and identification of active | -//| constraints. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| X - starting point, array[N]. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetStartingPoint(CMinQPStateShell &state,double &x[]) - { -//--- function call - CMinQP::MinQPSetStartingPoint(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets origin for QP solver. By default, following | -//| QP program is solved: | -//| min(0.5*x'*A*x+b'*x) | -//| This function allows to solve different problem: | -//| min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| XOrigin - origin, array[N]. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetOrigin(CMinQPStateShell &state,double &xorigin[]) - { -//--- function call - CMinQP::MinQPSetOrigin(state.GetInnerObj(),xorigin); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function tells solver to use Cholesky-based algorithm. | -//| Cholesky-based algorithm can be used when: | -//| * problem is convex | -//| * there is no constraints or only boundary constraints are | -//| present | -//| This algorithm has O(N^3) complexity for unconstrained problem | -//| and is up to several times slower on bound constrained problems | -//| (these additional iterations are needed to identify active | -//| constraints). | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetAlgoCholesky(CMinQPStateShell &state) - { -//--- function call - CMinQP::MinQPSetAlgoCholesky(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets boundary constraints for QP solver | -//| Boundary constraints are inactive by default (after initial | -//| creation). After being set, they are preserved until explicitly | -//| turned off with another SetBC() call. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| BndL - lower bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very small number or -INF (latter is | -//| recommended because it will allow solver to use | -//| better algorithm). | -//| BndU - upper bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very large number or +INF (latter is | -//| recommended because it will allow solver to use | -//| better algorithm). | -//| NOTE: it is possible to specify BndL[i]=BndU[i]. In this case | -//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPSetBC(CMinQPStateShell &state,double &bndl[], - double &bndu[]) - { -//--- function call - CMinQP::MinQPSetBC(state.GetInnerObj(),bndl,bndu); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function solves quadratic programming problem. | -//| You should call it after setting solver options with | -//| MinQPSet...() calls. | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| You should use MinQPResults() function to access results after | -//| calls to this function. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPOptimize(CMinQPStateShell &state) - { -//--- function call - CMinQP::MinQPOptimize(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| QP solver results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report. You should check Rep. | -//| TerminationType, which contains completion code, | -//| and you may check another fields which contain | -//| another information about algorithm functioning. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPResults(CMinQPStateShell &state,double &x[], - CMinQPReportShell &rep) - { -//--- function call - CMinQP::MinQPResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| QP results | -//| Buffered implementation of MinQPResults() which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::MinQPResultsBuf(CMinQPStateShell &state,double &x[], - CMinQPReportShell &rep) - { -//--- function call - CMinQP::MinQPResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR | -//| NON-LINEAR LEAST SQUARES OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of function which is | -//| represented as sum of squares: | -//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + | -//| + f[m-1]^2(x[0],...,x[n-1]) | -//| using value of function vector f[] and Jacobian of f[]. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function vector f[] at given point X | -//| * function vector f[] and Jacobian of f[] (simultaneously) at | -//| given point | -//| There are several overloaded versions of MinLMOptimize() | -//| function which correspond to different LM-like optimization | -//| algorithms provided by this unit. You should choose version which| -//| accepts fvec() and jac() callbacks. First one is used to | -//| calculate f[] at given point, second one calculates f[] and | -//| Jacobian df[i]/dx[j]. | -//| You can try to initialize MinLMState structure with VJ function | -//| and then use incorrect version of MinLMOptimize() (for example,| -//| version which works with general form function and does not | -//| provide Jacobian), but it will lead to exception being thrown | -//| after first attempt to calculate Jacobian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateVJ() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N/M but another starting point and/or | -//| another function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateVJ(const int n,const int m,double &x[], - CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateVJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR | -//| NON-LINEAR LEAST SQUARES OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of function which is | -//| represented as sum of squares: | -//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + | -//| + f[m-1]^2(x[0],...,x[n-1]) | -//| using value of function vector f[] and Jacobian of f[]. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function vector f[] at given point X | -//| * function vector f[] and Jacobian of f[] (simultaneously) at | -//| given point | -//| There are several overloaded versions of MinLMOptimize() | -//| function which correspond to different LM-like optimization | -//| algorithms provided by this unit. You should choose version which| -//| accepts fvec() and jac() callbacks. First one is used to | -//| calculate f[] at given point, second one calculates f[] and | -//| Jacobian df[i]/dx[j]. | -//| You can try to initialize MinLMState structure with VJ function | -//| and then use incorrect version of MinLMOptimize() (for example,| -//| version which works with general form function and does not | -//| provide Jacobian), but it will lead to exception being thrown | -//| after first attempt to calculate Jacobian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateVJ() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N/M but another starting point and/or | -//| another function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateVJ(const int m,double &x[],CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateVJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR | -//| NON-LINEAR LEAST SQUARES OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of function which is | -//| represented as sum of squares: | -//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + | -//| + f[m-1]^2(x[0],...,x[n-1]) | -//| using value of function vector f[] only. Finite differences are | -//| used to calculate Jacobian. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function vector f[] at given point X | -//| There are several overloaded versions of MinLMOptimize() function| -//| which correspond to different LM-like optimization algorithms | -//| provided by this unit. You should choose version which accepts | -//| fvec() callback. | -//| You can try to initialize MinLMState structure with VJ function | -//| and then use incorrect version of MinLMOptimize() (for example, | -//| version which works with general form function and does not | -//| accept function vector), but it will lead to exception being | -//| thrown after first attempt to calculate Jacobian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateV() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N/M but another starting point and/or | -//| another function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| See also MinLMIteration, MinLMResults. | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateV(const int n,const int m,double &x[], - double diffstep,CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateV(n,m,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR | -//| NON-LINEAR LEAST SQUARES OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of function which is | -//| represented as sum of squares: | -//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + | -//| + f[m-1]^2(x[0],...,x[n-1]) | -//| using value of function vector f[] only. Finite differences are | -//| used to calculate Jacobian. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function vector f[] at given point X | -//| There are several overloaded versions of MinLMOptimize() function| -//| which correspond to different LM-like optimization algorithms | -//| provided by this unit. You should choose version which accepts | -//| fvec() callback. | -//| You can try to initialize MinLMState structure with VJ function | -//| and then use incorrect version of MinLMOptimize() (for example, | -//| version which works with general form function and does not | -//| accept function vector), but it will lead to exception being | -//| thrown after first attempt to calculate Jacobian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateV() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N/M but another starting point and/or | -//| another function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| See also MinLMIteration, MinLMResults. | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateV(const int m,double &x[],const double diffstep, - CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateV(n,m,x,diffstep,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of general form (not | -//| "sum-of-squares") function | -//| F = F(x[0], ..., x[n-1]) | -//| using its gradient and Hessian. Levenberg-Marquardt modification | -//| with L-BFGS pre-optimization and internal pre-conditioned L-BFGS | -//| optimization after each Levenberg-Marquardt step is used. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function value F at given point X | -//| * F and gradient G (simultaneously) at given point X | -//| * F, G and Hessian H (simultaneously) at given point X | -//| There are several overloaded versions of MinLMOptimize() | -//| function which correspond to different LM-like optimization | -//| algorithms provided by this unit. You should choose version which| -//| accepts func(), grad() and hess() function pointers. First | -//| pointer is used to calculate F at given point, second one | -//| calculates F(x) and grad F(x), third one calculates F(x), grad | -//| F(x), hess F(x). | -//| You can try to initialize MinLMState structure with FGH-function | -//| and then use incorrect version of MinLMOptimize() (for example, | -//| version which does not provide Hessian matrix), but it will lead | -//| to exception being thrown after first attempt to calculate | -//| Hessian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateFGH() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and pointers (delegates, etc.) to callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N but another starting point and/or another | -//| function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFGH(const int n,double &x[],CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateFGH(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of general form (not | -//| "sum-of-squares") function | -//| F = F(x[0], ..., x[n-1]) | -//| using its gradient and Hessian. Levenberg-Marquardt modification | -//| with L-BFGS pre-optimization and internal pre-conditioned L-BFGS | -//| optimization after each Levenberg-Marquardt step is used. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function value F at given point X | -//| * F and gradient G (simultaneously) at given point X | -//| * F, G and Hessian H (simultaneously) at given point X | -//| There are several overloaded versions of MinLMOptimize() | -//| function which correspond to different LM-like optimization | -//| algorithms provided by this unit. You should choose version which| -//| accepts func(), grad() and hess() function pointers. First | -//| pointer is used to calculate F at given point, second one | -//| calculates F(x) and grad F(x), third one calculates F(x), grad | -//| F(x), hess F(x). | -//| You can try to initialize MinLMState structure with FGH-function | -//| and then use incorrect version of MinLMOptimize() (for example, | -//| version which does not provide Hessian matrix), but it will lead | -//| to exception being thrown after first attempt to calculate | -//| Hessian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateFGH() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and pointers (delegates, etc.) to callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N but another starting point and/or another | -//| function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFGH(double &x[],CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateFGH(n,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for Levenberg-Marquardt | -//| optimization algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the | -//| condition |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by MinLMSetScale()| -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. Only | -//| Levenberg-Marquardt iterations are counted | -//| (L-BFGS/CG iterations are NOT counted because | -//| their cost is very low compared to that of LM). | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetCond(CMinLMStateShell &state,const double epsg, - const double epsf,const double epsx, - const int maxits) - { -//--- function call - CMinLM::MinLMSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinLMOptimize(). Both Levenberg-Marquardt | -//| and internal L-BFGS iterations are reported. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetXRep(CMinLMStateShell &state,const bool needxrep) - { -//--- function call - CMinLM::MinLMSetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//| NOTE: non-zero StpMax leads to moderate performance degradation | -//| because intermediate step of preconditioned L-BFGS optimization | -//| is incompatible with limits on step size. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetStpMax(CMinLMStateShell &state,const double stpmax) - { -//--- function call - CMinLM::MinLMSetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for LM optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Generally, scale is NOT considered to be a form of | -//| preconditioner. But LM optimizer is unique in that it uses | -//| scaling matrix both in the stopping condition tests and as | -//| Marquardt damping factor. | -//| Proper scaling is very important for the algorithm performance. | -//| It is less important for the quality of results, but still has | -//| some influence (it is easier to converge when variables are | -//| properly scaled, so premature stopping is possible when very | -//| badly scalled variables are combined with relaxed stopping | -//| conditions). | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetScale(CMinLMStateShell &state,double &s[]) - { -//--- function call - CMinLM::MinLMSetScale(state.GetInnerObj(),s); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets boundary constraints for LM optimizer | -//| Boundary constraints are inactive by default (after initial | -//| creation). They are preserved until explicitly turned off with | -//| another SetBC() call. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| BndL - lower bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very small number or -INF (latter is | -//| recommended because it will allow solver to use | -//| better algorithm). | -//| BndU - upper bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very large number or +INF (latter is | -//| recommended because it will allow solver to use | -//| better algorithm). | -//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case | -//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. | -//| NOTE 2: this solver has following useful properties: | -//| * bound constraints are always satisfied exactly | -//| * function is evaluated only INSIDE area specified by bound | -//| constraints or at its boundary | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetBC(CMinLMStateShell &state,double &bndl[], - double &bndu[]) - { -//--- function call - CMinLM::MinLMSetBC(state.GetInnerObj(),bndl,bndu); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function is used to change acceleration settings | -//| You can choose between three acceleration strategies: | -//| * AccType=0, no acceleration. | -//| * AccType=1, secant updates are used to update quadratic model | -//| after each iteration. After fixed number of iterations (or | -//| after model breakdown) we recalculate quadratic model using | -//| analytic Jacobian or finite differences. Number of secant-based| -//| iterations depends on optimization settings: about 3 | -//| iterations - when we have analytic Jacobian, up to 2*N | -//| iterations - when we use finite differences to calculate | -//| Jacobian. | -//| AccType=1 is recommended when Jacobian calculation cost is | -//| prohibitive high (several Mx1 function vector calculations | -//| followed by several NxN Cholesky factorizations are faster than | -//| calculation of one M*N Jacobian). It should also be used when we| -//| have no Jacobian, because finite difference approximation takes | -//| too much time to compute. | -//| Table below list optimization protocols (XYZ protocol corresponds| -//| to MinLMCreateXYZ) and acceleration types they support (and use | -//| by default). | -//| ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: | -//| protocol 0 1 comment | -//| V + + | -//| VJ + + | -//| FGH + | -//| DAFAULT VALUES: | -//| protocol 0 1 comment | -//| V x without acceleration it is so slooooooooow | -//| VJ x | -//| FGH x | -//| NOTE: this function should be called before optimization. | -//| Attempt to call it during algorithm iterations may result in | -//| unexpected behavior. | -//| NOTE: attempt to call this function with unsupported | -//| protocol/acceleration combination will result in exception being | -//| thrown. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMSetAccType(CMinLMStateShell &state,const int acctype) - { -//--- function call - CMinLM::MinLMSetAccType(state.GetInnerObj(),acctype); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::MinLMIteration(CMinLMStateShell &state) - { -//--- return result - return(CMinLM::MinLMIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| hess - callback which calculates function (or merit | -//| function) value func, gradient grad and Hessian | -//| hess at given point x | -//| fvec - callback which calculates function vector fi[] | -//| at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLMIteration(state)) - { - if(state.GetNeedFI()) - { - fvec.FVec(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| hess - callback which calculates function (or merit | -//| function) value func, gradient grad and Hessian | -//| hess at given point x | -//| fvec - callback which calculates function vector fi[] | -//| at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec, - CNDimensional_Jac &jac,CNDimensional_Rep &rep, - bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLMIteration(state)) - { - //--- check - if(state.GetNeedFI()) - { - fvec.FVec(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFIJ()) - { - jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| hess - callback which calculates function (or merit | -//| function) value func, gradient grad and Hessian | -//| hess at given point x | -//| fvec - callback which calculates function vector fi[] | -//| at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func, - CNDimensional_Grad &grad,CNDimensional_Hess &hess, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLMIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFGH()) - { - hess.Hess(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,state.GetInnerObj().m_h,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| hess - callback which calculates function (or merit | -//| function) value func, gradient grad and Hessian | -//| hess at given point x | -//| fvec - callback which calculates function vector fi[] | -//| at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func, - CNDimensional_Jac &jac,CNDimensional_Rep &rep, - bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLMIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFIJ()) - { - jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| hess - callback which calculates function (or merit | -//| function) value func, gradient grad and Hessian | -//| hess at given point x | -//| fvec - callback which calculates function vector fi[] | -//| at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func, - CNDimensional_Grad &grad,CNDimensional_Jac &jac, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinLMIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFIJ()) - { - jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| Levenberg-Marquardt algorithm results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report; | -//| see comments for this structure for more info. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMResults(CMinLMStateShell &state,double &x[], - CMinLMReportShell &rep) - { -//--- function call - CMinLM::MinLMResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Levenberg-Marquardt algorithm results | -//| Buffered implementation of MinLMResults(), which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMResultsBuf(CMinLMStateShell &state,double &x[], - CMinLMReportShell &rep) - { -//--- function call - CMinLM::MinLMResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts LM algorithm from new point. All | -//| optimization parameters are left unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure used for reverse communication | -//| previously allocated with MinLMCreateXXX call. | -//| X - new starting point. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMRestartFrom(CMinLMStateShell &state,double &x[]) - { -//--- function call - CMinLM::MinLMRestartFrom(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function. | -//| Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateVGJ(const int n,const int m,double &x[], - CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateVGJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function. | -//| Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateVGJ(const int m,double &x[],CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateVGJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function. | -//| Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFGJ(const int n,const int m,double &x[], - CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateFGJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function. | -//| Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFGJ(const int m,double &x[],CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateFGJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function is considered obsolete since ALGLIB 3.1.0 and is | -//| present for backward compatibility only. We recommend to use | -//| MinLMCreateVJ, which provides similar, but more consistent and | -//| feature-rich interface. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFJ(const int n,const int m,double &x[], - CMinLMStateShell &state) - { -//--- function call - CMinLM::MinLMCreateFJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function is considered obsolete since ALGLIB 3.1.0 and is | -//| present for backward compatibility only. We recommend to use | -//| MinLMCreateVJ, which provides similar, but more consistent and | -//| feature-rich interface. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLMCreateFJ(const int m,double &x[],CMinLMStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CMinLM::MinLMCreateFJ(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete function, use MinLBFGSSetPrecDefault() instead. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetDefaultPreconditioner(CMinLBFGSStateShell &state) - { -//--- function call - CMinComp::MinLBFGSSetDefaultPreconditioner(state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete function, use MinLBFGSSetCholeskyPreconditioner() | -//| instead. | -//+------------------------------------------------------------------+ -static void CAlglib::MinLBFGSSetCholeskyPreconditioner(CMinLBFGSStateShell &state, - CMatrixDouble &p,bool isupper) - { -//--- function call - CMinComp::MinLBFGSSetCholeskyPreconditioner(state.GetInnerObj(),p,isupper); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function which was used by previous version of | -//| the BLEIC optimizer. It does nothing in the current version of | -//| BLEIC. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetBarrierWidth(CMinBLEICStateShell &state, - const double mu) - { -//--- function call - CMinComp::MinBLEICSetBarrierWidth(state.GetInnerObj(),mu); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This is obsolete function which was used by previous version of | -//| the BLEIC optimizer. It does nothing in the current version of | -//| BLEIC. | -//+------------------------------------------------------------------+ -static void CAlglib::MinBLEICSetBarrierDecay(CMinBLEICStateShell &state, - const double mudecay) - { -//--- function call - CMinComp::MinBLEICSetBarrierDecay(state.GetInnerObj(),mudecay); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASACreate(const int n,double &x[],double &bndl[], - double &bndu[],CMinASAStateShell &state) - { -//--- function call - CMinComp::MinASACreate(n,x,bndl,bndu,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASACreate(double &x[],double &bndl[],double &bndu[], - CMinASAStateShell &state) - { -//--- create a variable - int n; -//--- check - if((CAp::Len(x)!=CAp::Len(bndl)) || (CAp::Len(x)!=CAp::Len(bndu))) - { - Print("Error while calling 'minasacreate': looks like one of arguments has wrong size"); - CAp::exception_happened=true; - return; - } -//--- initialization - n=CAp::Len(x); -//--- function call - CMinComp::MinASACreate(n,x,bndl,bndu,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASASetCond(CMinASAStateShell &state,const double epsg, - const double epsf,const double epsx,const int maxits) - { -//--- function call - CMinComp::MinASASetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASASetXRep(CMinASAStateShell &state,const bool needxrep) - { -//--- function call - CMinComp::MinASASetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASASetAlgorithm(CMinASAStateShell &state,const int algotype) - { -//--- function call - CMinComp::MinASASetAlgorithm(state.GetInnerObj(),algotype); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASASetStpMax(CMinASAStateShell &state,const double stpmax) - { -//--- function call - CMinComp::MinASASetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::MinASAIteration(CMinASAStateShell &state) - { -//--- return result - return(CMinComp::MinASAIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear optimizer | -//| These functions accept following parameters: | -//| grad - callback which calculates function (or merit | -//| function) value func and gradient grad at given | -//| point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//+------------------------------------------------------------------+ -static void CAlglib::MinASAOptimize(CMinASAStateShell &state,CNDimensional_Grad &grad, - CNDimensional_Rep &rep,bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::MinASAIteration(state)) - { - //--- check - if(state.GetNeedFG()) - { - grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'minasaoptimize' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASAResults(CMinASAStateShell &state,double &x[], - CMinASAReportShell &rep) - { -//--- function call - CMinComp::MinASAResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASAResultsBuf(CMinASAStateShell &state,double &x[], - CMinASAReportShell &rep) - { -//--- function call - CMinComp::MinASAResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CAlglib::MinASARestartFrom(CMinASAStateShell &state,double &x[], - double &bndl[],double &bndu[]) - { -//--- function call - CMinComp::MinASARestartFrom(state.GetInnerObj(),x,bndl,bndu); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*x=b, where A is NxN | -//| non-denegerate real matrix, x and b are vectors. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - return code: | -//| * -3 A is singular, or VERY close to singular.| -//| X is filled by zeros in such cases. | -//| * -1 N<=0 was passed | -//| * 1 task is solved (but matrix A may be | -//| ill-conditioned, check R1/RInf parameters| -//| for condition numbers). | -//| Rep - solver report, see below for more info | -//| X - array[0..N-1], it contains: | -//| * solution of A*x=b if A is non-singular | -//| (well-conditioned or ill-conditioned, but not | -//| very close to singular) | -//| * zeros, if A is singular or VERY close to | -//| singular (in this case Info=-3). | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. | -//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixSolve(CMatrixDouble &a,const int n,double &b[], - int &info,CDenseSolverReportShell &rep, - double &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixSolve(a,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixSolve() but solves task with multiple right | -//| parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * optional iterative refinement | -//| * O(N^3+M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| RFS - iterative refinement switch: | -//| * True - refinement is used. | -//| Less performance, more precision. | -//| * False - refinement is not used. | -//| More performance, less precision. | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixSolveM(CMatrixDouble &a,const int n,CMatrixDouble &b, - const int m,const bool rfs,int &info, - CDenseSolverReportShell &rep,CMatrixDouble &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixSolveM(a,n,b,m,rfs,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*X=B, where A is NxN | -//| non-denegerate real matrix given by its LU decomposition, X and | -//| B are NxM real matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use RMatrixSolve or | -//| RMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLUSolve(CMatrixDouble &lua,int &p[],const int n, - double &b[],int &info, - CDenseSolverReportShell &rep,double &x[]) - {//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixLUSolve(lua,p,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixLUSolve() but solves task with multiple right | -//| parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use RMatrixSolve or | -//| RMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixLUSolveM(CMatrixDouble &lua,int &p[],const int n, - CMatrixDouble &b,const int m,int &info, - CDenseSolverReportShell &rep,CMatrixDouble &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixLUSolveM(lua,p,n,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND | -//| ITS LU DECOMPOSITION ARE KNOWN. You can use it if for some | -//| reasons you have both A and its LU decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua, - int &p[],const int n,double &b[], - int &info,CDenseSolverReportShell &rep, - double &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixMixedSolve(a,lua,p,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixMixedSolve() but solves task with multiple | -//| right parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua, - int &p[],const int n,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReportShell &rep, - CMatrixDouble &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixMixedSolveM(a,lua,p,n,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for complex matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3+M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| RFS - iterative refinement switch: | -//| * True - refinement is used. | -//| Less performance, more precision. | -//| * False - refinement is not used. | -//| More performance, less precision. | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixSolveM(CMatrixComplex &a,const int n,CMatrixComplex &b, - const int m,const bool rfs,int &info, - CDenseSolverReportShell &rep, - CMatrixComplex &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixSolveM(a,n,b,m,rfs,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for complex matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixSolve(CMatrixComplex &a,const int n,al_complex &b[], - int &info,CDenseSolverReportShell &rep, - al_complex &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixSolve(a,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use CMatrixSolve or | -//| CMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLUSolveM(CMatrixComplex &lua,int &p[],const int n, - CMatrixComplex &b,const int m,int &info, - CDenseSolverReportShell &rep,CMatrixComplex &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixLUSolveM(lua,p,n,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for complex matrices.| -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use CMatrixSolve or | -//| CMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixLUSolve(CMatrixComplex &lua,int &p[],const int n, - al_complex &b[],int &info,CDenseSolverReportShell &rep, - al_complex &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixLUSolve(lua,p,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixMixedSolveM(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua, - int &p[],const int n,CMatrixComplex &b, - const int m,int &info, - CDenseSolverReportShell &rep, - CMatrixComplex &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixMixedSolveM(a,lua,p,n,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixMixedSolve(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CAlglib::CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua, - int &p[],const int n,al_complex &b[], - int &info,CDenseSolverReportShell &rep, - al_complex &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::CMatrixMixedSolve(a,lua,p,n,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for symmetric positive| -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3+M*N^2) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve. | -//| Returns -3 for non-SPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixSolveM(CMatrixDouble &a,const int n,const bool isupper, - CMatrixDouble &b,const int m,int &info, - CDenseSolverReportShell &rep,CMatrixDouble &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::SPDMatrixSolveM(a,n,isupper,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for SPD matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Returns -3 for non-SPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixSolve(CMatrixDouble &a,const int n,const bool isupper, - double &b[],int &info,CDenseSolverReportShell &rep, - double &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::SPDMatrixSolve(a,n,isupper,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for SPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of CHA | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n, - const bool isupper,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReportShell &rep, - CMatrixDouble &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::SPDMatrixCholeskySolveM(cha,n,isupper,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for SPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of A | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n, - const bool isupper,double &b[], - int &info,CDenseSolverReportShell &rep, - double &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::SPDMatrixCholeskySolve(cha,n,isupper,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for Hermitian positive| -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3+M*N^2) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve. | -//| Returns -3 for non-HPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixSolveM(CMatrixComplex &a,const int n,const bool isupper, - CMatrixComplex &b,const int m,int &info, - CDenseSolverReportShell &rep,CMatrixComplex &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::HPDMatrixSolveM(a,n,isupper,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for Hermitian positive | -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Returns -3 for non-HPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixSolve(CMatrixComplex &a,const int n, - const bool isupper,al_complex &b[], - int &info,CDenseSolverReportShell &rep, - al_complex &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::HPDMatrixSolve(a,n,isupper,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| HPDMatrixCholesky result | -//| N - size of CHA | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixCholeskySolveM(CMatrixComplex &cha,const int n, - const bool isupper,CMatrixComplex &b, - const int m,int &info, - CDenseSolverReportShell &rep, - CMatrixComplex &x) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::HPDMatrixCholeskySolveM(cha,n,isupper,b,m,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for HPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of A | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CAlglib::HPDMatrixCholeskySolve(CMatrixComplex &cha,const int n, - const bool isupper,al_complex &b[], - int &info,CDenseSolverReportShell &rep, - al_complex &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::HPDMatrixCholeskySolve(cha,n,isupper,b,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine finds solution of the linear system A*X=B with | -//| non-square, possibly degenerate A. System is solved in the least | -//| squares sense, and general least squares solution X = X0 + CX*y | -//| which minimizes |A*X-B| is returned. If A is non-degenerate, | -//| solution in the usual sense is returned | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..NRows-1,0..NCols-1], system matrix | -//| NRows - vertical size of A | -//| NCols - horizontal size of A | -//| B - array[0..NCols-1], right part | -//| Threshold- a number in [0,1]. Singular values beyond | -//| Threshold are considered zero. Set it to 0.0, | -//| if you don't understand what it means, so the | -//| solver will choose good value on its own. | -//| OUTPUT PARAMETERS | -//| Info - return code: | -//| * -4 SVD subroutine failed | -//| * -1 if NRows<=0 or NCols<=0 or Threshold<0 | -//| was passed | -//| * 1 if task is solved | -//| Rep - solver report, see below for more info | -//| X - array[0..N-1,0..M-1], it contains: | -//| * solution of A*X=B if A is non-singular | -//| (well-conditioned or ill-conditioned, but not | -//| very close to singular) | -//| * zeros, if A is singular or VERY close to | -//| singular (in this case Info=-3). | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R2 reciprocal of condition number: 1/cond(A), 2-norm. | -//| * N = NCols | -//| * K dim(Null(A)) | -//| * CX array[0..N-1,0..K-1], kernel of A. | -//| Columns of CX store such vectors that A*CX[i]=0. | -//+------------------------------------------------------------------+ -static void CAlglib::RMatrixSolveLS(CMatrixDouble &a,const int nrows, - const int ncols,double &b[], - const double threshold,int &info, - CDenseSolverLSReportShell &rep, - double &x[]) - { -//--- initialization - info=0; -//--- function call - CDenseSolver::RMatrixSolveLS(a,nrows,ncols,b,threshold,info,rep.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER | -//| DESCRIPTION: | -//| This algorithm solves system of nonlinear equations | -//| F[0](x[0], ..., x[n-1]) = 0 | -//| F[1](x[0], ..., x[n-1]) = 0 | -//| ... | -//| F[M-1](x[0], ..., x[n-1]) = 0 | -//| with M/N do not necessarily coincide. Algorithm converges | -//| quadratically under following conditions: | -//| * the solution set XS is nonempty | -//| * for some xs in XS there exist such neighbourhood N(xs) | -//| that: | -//| * vector function F(x) and its Jacobian J(x) are | -//| continuously differentiable on N | -//| * ||F(x)|| provides local error bound on N, i.e. there | -//| exists such c1, that ||F(x)||>c1*distance(x,XS) | -//| Note that these conditions are much more weaker than usual | -//| non-singularity conditions. For example, algorithm will converge | -//| for any affine function F (whether its Jacobian singular or not).| -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function vector F[] and Jacobian matrix at given point X | -//| * value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given| -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with NLEQCreateLM() call | -//| 2. User tunes solver parameters with NLEQSetCond(), | -//| NLEQSetStpMax() and other functions | -//| 3. User calls NLEQSolve() function which takes algorithm state | -//| and pointers (delegates, etc.) to callback functions which | -//| calculate merit function value and Jacobian. | -//| 4. User calls NLEQResults() to get solution | -//| 5. Optionally, user may call NLEQRestartFrom() to solve another | -//| problem with same parameters (N/M) but another starting point | -//| and/or another function vector. NLEQRestartFrom() allows to | -//| reuse already initialized structure. | -//| INPUT PARAMETERS: | -//| N - space dimension, N>1: | -//| * if provided, only leading N elements of X are | -//| used | -//| * if not provided, determined automatically from | -//| size of X | -//| M - system size | -//| X - starting point | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with NLEQSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use NLEQSetStpMax() function to bound| -//| algorithm's steps. | -//| 3. this algorithm is a slightly modified implementation of the | -//| method described in 'Levenberg-Marquardt method for | -//| constrained nonlinear equations with strong local convergence | -//| properties' by Christian Kanzow Nobuo Yamashita and Masao | -//| Fukushima and further developed in 'On the convergence of a | -//| New Levenberg-Marquardt Method' by Jin-yan Fan and Ya-Xiang | -//| Yuan. | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqCreateLM(const int n,const int m,double &x[], - CNlEqStateShell &state) - { -//--- function call - CNlEq::NlEqCreateLM(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER | -//| DESCRIPTION: | -//| This algorithm solves system of nonlinear equations | -//| F[0](x[0], ..., x[n-1]) = 0 | -//| F[1](x[0], ..., x[n-1]) = 0 | -//| ... | -//| F[M-1](x[0], ..., x[n-1]) = 0 | -//| with M/N do not necessarily coincide. Algorithm converges | -//| quadratically under following conditions: | -//| * the solution set XS is nonempty | -//| * for some xs in XS there exist such neighbourhood N(xs) | -//| that: | -//| * vector function F(x) and its Jacobian J(x) are | -//| continuously differentiable on N | -//| * ||F(x)|| provides local error bound on N, i.e. there | -//| exists such c1, that ||F(x)||>c1*distance(x,XS) | -//| Note that these conditions are much more weaker than usual | -//| non-singularity conditions. For example, algorithm will converge | -//| for any affine function F (whether its Jacobian singular or not).| -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function vector F[] and Jacobian matrix at given point X | -//| * value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given| -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with NLEQCreateLM() call | -//| 2. User tunes solver parameters with NLEQSetCond(), | -//| NLEQSetStpMax() and other functions | -//| 3. User calls NLEQSolve() function which takes algorithm state | -//| and pointers (delegates, etc.) to callback functions which | -//| calculate merit function value and Jacobian. | -//| 4. User calls NLEQResults() to get solution | -//| 5. Optionally, user may call NLEQRestartFrom() to solve another | -//| problem with same parameters (N/M) but another starting point | -//| and/or another function vector. NLEQRestartFrom() allows to | -//| reuse already initialized structure. | -//| INPUT PARAMETERS: | -//| N - space dimension, N>1: | -//| * if provided, only leading N elements of X are | -//| used | -//| * if not provided, determined automatically from | -//| size of X | -//| M - system size | -//| X - starting point | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with NLEQSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use NLEQSetStpMax() function to bound| -//| algorithm's steps. | -//| 3. this algorithm is a slightly modified implementation of the | -//| method described in 'Levenberg-Marquardt method for | -//| constrained nonlinear equations with strong local convergence | -//| properties' by Christian Kanzow Nobuo Yamashita and Masao | -//| Fukushima and further developed in 'On the convergence of a | -//| New Levenberg-Marquardt Method' by Jin-yan Fan and Ya-Xiang | -//| Yuan. | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqCreateLM(const int m,double &x[],CNlEqStateShell &state) - { -//--- create a variable - int n; -//--- initialization - n=CAp::Len(x); -//--- function call - CNlEq::NlEqCreateLM(n,m,x,state.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for the nonlinear solver | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsF - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition ||F||<=EpsF is satisfied | -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsF=0 and MaxIts=0 simultaneously will lead to | -//| automatic stopping criterion selection (small EpsF). | -//| NOTES: | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqSetCond(CNlEqStateShell &state,const double epsf, - const int maxits) - { -//--- function call - CNlEq::NlEqSetCond(state.GetInnerObj(),epsf,maxits); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to NLEQSolve(). | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqSetXRep(CNlEqStateShell &state,const bool needxrep) - { -//--- function call - CNlEq::NlEqSetXRep(state.GetInnerObj(),needxrep); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when target function contains exp() or other | -//| fast growing functions, and algorithm makes too large steps which| -//| lead to overflow. This function allows us to reject steps that | -//| are too large (and therefore expose us to the possible overflow) | -//| without actually calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqSetStpMax(CNlEqStateShell &state,const double stpmax) - { -//--- function call - CNlEq::NlEqSetStpMax(state.GetInnerObj(),stpmax); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This function provides reverse communication interface | -//| Reverse communication interface is not documented or recommended | -//| to use. | -//| See below for functions which provide better documented API | -//+------------------------------------------------------------------+ -static bool CAlglib::NlEqIteration(CNlEqStateShell &state) - { -//--- return result - return(CNlEq::NlEqIteration(state.GetInnerObj())); - } -//+------------------------------------------------------------------+ -//| This family of functions is used to launcn iterations of | -//| nonlinear solver | -//| These functions accept following parameters: | -//| func - callback which calculates function (or merit | -//| function) value func at given point x | -//| jac - callback which calculates function vector fi[] | -//| and Jacobian jac at given point x | -//| rep - optional callback which is called after each | -//| iteration can be null | -//| obj - optional object which is passed to | -//| func/grad/hess/jac/rep can be null | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqSolve(CNlEqStateShell &state,CNDimensional_Func &func, - CNDimensional_Jac &jac,CNDimensional_Rep &rep, - bool rep_status,CObject &obj) - { -//--- cycle - while(CAlglib::NlEqIteration(state)) - { - //--- check - if(state.GetNeedF()) - { - func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetNeedFIJ()) - { - jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj); - //--- next iteration - continue; - } - //--- check - if(state.GetInnerObj().m_xupdated) - { - //--- check - if(rep_status) - rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj); - //--- next iteration - continue; - } - Print("ALGLIB: error in 'nleqsolve' (some derivatives were not provided?)"); - CAp::exception_happened=true; - return; - } - } -//+------------------------------------------------------------------+ -//| NLEQ solver results | -//| INPUT PARAMETERS: | -//| State - algorithm state. | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * -4 ERROR: algorithm has converged to the| -//| stationary point Xf which is local | -//| minimum of f=F[0]^2+...+F[m-1]^2, | -//| but is not solution of nonlinear | -//| system. | -//| * 1 sqrt(f)<=EpsF. | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//| * ActiveConstraints contains number of active | -//| constraints | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqResults(CNlEqStateShell &state,double &x[], - CNlEqReportShell &rep) - { -//--- function call - CNlEq::NlEqResults(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| NLEQ solver results | -//| Buffered implementation of NLEQResults(), which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqResultsBuf(CNlEqStateShell &state,double &x[], - CNlEqReportShell &rep) - { -//--- function call - CNlEq::NlEqResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj()); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts CG algorithm from new point. All | -//| optimization parameters are left unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure used for reverse communication | -//| previously allocated with MinCGCreate call. | -//| X - new starting point. | -//| BndL - new lower bounds | -//| BndU - new upper bounds | -//+------------------------------------------------------------------+ -static void CAlglib::NlEqRestartFrom(CNlEqStateShell &state,double &x[]) - { -//--- function call - CNlEq::NlEqRestartFrom(state.GetInnerObj(),x); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Gamma function | -//| Input parameters: | -//| X - argument | -//| Domain: | -//| 0 < X < 171.6 | -//| -170 < X < 0, X is not an integer. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -170,-33 20000 2.3e-15 3.3e-16 | -//| IEEE -33, 33 20000 9.4e-16 2.2e-16 | -//| IEEE 33, 171.6 20000 2.3e-15 3.2e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::GammaFunction(const double x) - { -//--- return result - return(CGammaFunc::GammaFunc(x)); - } -//+------------------------------------------------------------------+ -//| Natural logarithm of gamma function | -//| Input parameters: | -//| X - argument | -//| Result: | -//| logarithm of the absolute value of the Gamma(X). | -//| Output parameters: | -//| SgnGam - sign(Gamma(X)) | -//| Domain: | -//| 0 < X < 2.55e305 | -//| -2.55e305 < X < 0, X is not an integer. | -//| ACCURACY: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 3 28000 5.4e-16 1.1e-16 | -//| IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 | -//| The error criterion was relative when the function magnitude | -//| was greater than one but absolute when it was less than one. | -//| The following test used the relative error criterion, though | -//| at certain points the relative error could be much higher than | -//| indicated. | -//| IEEE -200, -4 10000 4.8e-16 1.3e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::LnGamma(const double x,double &sgngam) - { -//--- initialization - sgngam=0; -//--- return result - return(CGammaFunc::LnGamma(x,sgngam)); - } -//+------------------------------------------------------------------+ -//| Error function | -//| The integral is | -//| x | -//| - | -//| 2 | | 2 | -//| erf(x) = -------- | exp( - t ) dt. | -//| sqrt(pi) | | | -//| - | -//| 0 | -//| For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise | -//| erf(x) = 1 - erfc(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 3.7e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::ErrorFunction(const double x) - { -//--- return result - return(CNormalDistr::ErrorFunction(x)); - } -//+------------------------------------------------------------------+ -//| Complementary error function | -//| 1 - erf(x) = | -//| inf. | -//| - | -//| 2 | | 2 | -//| erfc(x) = -------- | exp( - t ) dt | -//| sqrt(pi) | | | -//| - | -//| x | -//| For small x, erfc(x) = 1 - erf(x); otherwise rational | -//| approximations are computed. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,26.6417 30000 5.7e-14 1.5e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::ErrorFunctionC(const double x) - { -//--- return result - return(CNormalDistr::ErrorFunctionC(x)); - } -//+------------------------------------------------------------------+ -//| Normal distribution function | -//| Returns the area under the Gaussian probability density | -//| function, integrated from minus infinity to x: | -//| x | -//| - | -//| 1 | | 2 | -//| ndtr(x) = --------- | exp( - t /2 ) dt | -//| sqrt(2pi) | | | -//| - | -//| -inf. | -//| = ( 1 + erf(z) ) / 2 | -//| = erfc(z) / 2 | -//| where z = x/sqrt(2). Computation is via the functions | -//| erf and erfc. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -13,0 30000 3.4e-14 6.7e-15 | -//+------------------------------------------------------------------+ -static double CAlglib::NormalDistribution(const double x) - { -//--- return result - return(CNormalDistr::NormalDistribution(x)); - } -//+------------------------------------------------------------------+ -//| Inverse of the error function | -//+------------------------------------------------------------------+ -static double CAlglib::InvErF(double e) - { -//--- return result - return(CNormalDistr::InvErF(e)); - } -//+------------------------------------------------------------------+ -//| Inverse of Normal distribution function | -//| Returns the argument, x, for which the area under the | -//| Gaussian probability density function (integrated from | -//| minus infinity to x) is equal to y. | -//| For small arguments 0 < y < exp(-2), the program computes | -//| z = sqrt( -2.0 * log(y) ); then the approximation is | -//| x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). | -//| There are two rational functions P/Q, one for 0 < y < exp(-32) | -//| and the other for y up to exp(-2). For larger arguments, | -//| w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0.125, 1 20000 7.2e-16 1.3e-16 | -//| IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 | -//+------------------------------------------------------------------+ -static double CAlglib::InvNormalDistribution(const double y0) - { -//--- return result - return(CNormalDistr::InvNormalDistribution(y0)); - } -//+------------------------------------------------------------------+ -//| Incomplete gamma integral | -//| The function is defined by | -//| x | -//| - | -//| 1 | | -t a-1 | -//| igam(a,x) = ----- | e t dt. | -//| - | | | -//| | (a) - | -//| 0 | -//| In this implementation both arguments must be positive. | -//| The integral is evaluated by either a power series or | -//| continued fraction expansion, depending on the relative | -//| values of a and x. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 200000 3.6e-14 2.9e-15 | -//| IEEE 0,100 300000 9.9e-14 1.5e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::IncompleteGamma(const double a,const double x) - { -//--- return result - return(CIncGammaF::IncompleteGamma(a,x)); - } -//+------------------------------------------------------------------+ -//| Complemented incomplete gamma integral | -//| The function is defined by | -//| igamc(a,x) = 1 - igam(a,x) | -//| inf. | -//| - | -//| 1 | | -t a-1 | -//| = ----- | e t dt. | -//| - | | | -//| | (a) - | -//| x | -//| In this implementation both arguments must be positive. | -//| The integral is evaluated by either a power series or | -//| continued fraction expansion, depending on the relative | -//| values of a and x. | -//| ACCURACY: | -//| Tested at random a, x. | -//| a x Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15| -//| IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15| -//+------------------------------------------------------------------+ -static double CAlglib::IncompleteGammaC(const double a,const double x) - { -//--- return result - return(CIncGammaF::IncompleteGammaC(a,x)); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented imcomplete gamma integral | -//| Given p, the function finds x such that | -//| igamc( a, x ) = p. | -//| Starting with the approximate value | -//| 3 | -//| x = a t | -//| where | -//| t = 1 - d - ndtri(p) sqrt(d) | -//| and | -//| d = 1/9a, | -//| the routine performs up to 10 Newton iterations to find the | -//| root of igamc(a,x) - p = 0. | -//| ACCURACY: | -//| Tested at random a, p in the intervals indicated. | -//| a p Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15| -//| IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15| -//| IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14| -//+------------------------------------------------------------------+ -static double CAlglib::InvIncompleteGammaC(const double a,const double y0) - { -//--- return result - return(CIncGammaF::InvIncompleteGammaC(a,y0)); - } -//+------------------------------------------------------------------+ -//| Airy function | -//| Solution of the differential equation | -//| y"(x) = xy. | -//| The function returns the two independent solutions Ai, Bi | -//| and their first derivatives Ai'(x), Bi'(x). | -//| Evaluation is by power series summation for small x, | -//| by rational minimax approximations for large x. | -//| ACCURACY: | -//| Error criterion is absolute when function <= 1, relative | -//| when function > 1, except * denotes relative error criterion. | -//| For large negative x, the absolute error increases as x^1.5. | -//| For large positive x, the relative error increases as x^1.5. | -//| Arithmetic domain function # trials peak rms | -//| IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 | -//| IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15*| -//| IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 | -//| IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15*| -//| IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 | -//| IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 | -//+------------------------------------------------------------------+ -static void CAlglib::Airy(const double x,double &ai,double &aip,double &bi, - double &bip) - { -//--- create variables - ai=0; - aip=0; - bi=0; - bip=0; -//--- function call - CAiryF::Airy(x,ai,aip,bi,bip); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Bessel function of order zero | -//| Returns Bessel function of order zero of the argument. | -//| The domain is divided into the intervals [0, 5] and | -//| (5, infinity). In the first interval the following rational | -//| approximation is used: | -//| 2 2 | -//| (w - r ) (w - r ) P (w) / Q (w) | -//| 1 2 3 8 | -//| 2 | -//| where w = x and the two r's are zeros of the function. | -//| In the second interval, the Hankel asymptotic expansion | -//| is employed with two rational functions of degree 6/6 | -//| and 7/7. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 60000 4.2e-16 1.1e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselJ0(const double x) - { -//--- return result - return(CBessel::BesselJ0(x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of order one | -//| Returns Bessel function of order one of the argument. | -//| The domain is divided into the intervals [0, 8] and | -//| (8, infinity). In the first interval a 24 term Chebyshev | -//| expansion is used. In the second, the asymptotic | -//| trigonometric representation is employed using two | -//| rational functions of degree 5/5. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 2.6e-16 1.1e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselJ1(const double x) - { -//--- return result - return(CBessel::BesselJ1(x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of integer order | -//| Returns Bessel function of order n, where n is a | -//| (possibly negative) integer. | -//| The ratio of jn(x) to j0(x) is computed by backward | -//| recurrence. First the ratio jn/jn-1 is found by a | -//| continued fraction expansion. Then the recurrence | -//| relating successive orders is applied until j0 or j1 is | -//| reached. | -//| If n = 0 or 1 the routine for j0 or j1 is called | -//| directly. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic range # trials peak rms | -//| IEEE 0, 30 5000 4.4e-16 7.9e-17 | -//| Not suitable for large n or x. Use jv() (fractional order) | -//| instead. | -//+------------------------------------------------------------------+ -static double CAlglib::BesselJN(const int n,const double x) - { -//--- return result - return(CBessel::BesselJN(n,x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of the second kind, order zero | -//| Returns Bessel function of the second kind, of order | -//| zero, of the argument. | -//| The domain is divided into the intervals [0, 5] and | -//| (5, infinity). In the first interval a rational approximation | -//| R(x) is employed to compute | -//| y0(x) = R(x) + 2 * log(x) * j0(x) / PI. | -//| Thus a call to j0() is required. | -//| In the second interval, the Hankel asymptotic expansion | -//| is employed with two rational functions of degree 6/6 | -//| and 7/7. | -//| ACCURACY: | -//| Absolute error, when y0(x) < 1; else relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.3e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselY0(const double x) - { -//--- return result - return(CBessel::BesselY0(x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of second kind of order one | -//| Returns Bessel function of the second kind of order one | -//| of the argument. | -//| The domain is divided into the intervals [0, 8] and | -//| (8, infinity). In the first interval a 25 term Chebyshev | -//| expansion is used, and a call to j1() is required. | -//| In the second, the asymptotic trigonometric representation | -//| is employed using two rational functions of degree 5/5. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.0e-15 1.3e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselY1(const double x) - { -//--- return result - return(CBessel::BesselY1(x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of second kind of integer order | -//| Returns Bessel function of order n, where n is a | -//| (possibly negative) integer. | -//| The function is evaluated by forward recurrence on | -//| n, starting with values computed by the routines | -//| y0() and y1(). | -//| If n = 0 or 1 the routine for y0 or y1 is called | -//| directly. | -//| ACCURACY: | -//| Absolute error, except relative | -//| when y > 1: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 3.4e-15 4.3e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselYN(const int n,const double x) - { -//--- return result - return(CBessel::BesselYN(n,x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function of order zero | -//| Returns modified Bessel function of order zero of the | -//| argument. | -//| The function is defined as i0(x) = j0( ix ). | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 5.8e-16 1.4e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselI0(const double x) - { -//--- return result - return(CBessel::BesselI0(x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function of order one | -//| Returns modified Bessel function of order one of the | -//| argument. | -//| The function is defined as i1(x) = -i j1( ix ). | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.9e-15 2.1e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselI1(const double x) - { -//--- return result - return(CBessel::BesselI1(x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, order zero | -//| Returns modified Bessel function of the second kind | -//| of order zero of the argument. | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Tested at 2000 random points between 0 and 8. Peak absolute | -//| error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.2e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselK0(const double x) - { -//--- return result - return(CBessel::BesselK0(x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, order one | -//| Computes the modified Bessel function of the second kind | -//| of order one of the argument. | -//| The range is partitioned into the two intervals [0,2] and | -//| (2, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.2e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BesselK1(const double x) - { -//--- return result - return(CBessel::BesselK1(x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, integer order | -//| Returns modified Bessel function of the second kind | -//| of order n of the argument. | -//| The range is partitioned into the two intervals [0,9.55] and | -//| (9.55, infinity). An ascending power series is used in the | -//| low range, and an asymptotic expansion in the high range. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 90000 1.8e-8 3.0e-10 | -//| Error is high only near the crossover point x = 9.55 | -//| between the two expansions used. | -//+------------------------------------------------------------------+ -static double CAlglib::BesselKN(const int nn,const double x) - { -//--- return result - return(CBessel::BesselKN(nn,x)); - } -//+------------------------------------------------------------------+ -//| Beta function | -//| - - | -//| | (a) | (b) | -//| beta( a, b ) = -----------. | -//| - | -//| | (a+b) | -//| For large arguments the logarithm of the function is | -//| evaluated using lgam(), then exponentiated. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 8.1e-14 1.1e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::Beta(const double a,const double b) - { -//--- return result - return(CBetaF::Beta(a,b)); - } -//+------------------------------------------------------------------+ -//| Incomplete beta integral | -//| Returns incomplete beta integral of the arguments, evaluated | -//| from zero to x. The function is defined as | -//| x | -//| - - | -//| | (a+b) | | a-1 b-1 | -//| ----------- | t (1-t) dt. | -//| - - | | | -//| | (a) | (b) - | -//| 0 | -//| The domain of definition is 0 <= x <= 1. In this | -//| implementation a and b are restricted to positive values. | -//| The integral from x to 1 may be obtained by the symmetry | -//| relation | -//| 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). | -//| The integral is evaluated by a continued fraction expansion | -//| or, when b*x is small, by a power series. | -//| ACCURACY: | -//| Tested at uniformly distributed random points (a,b,x) with a and | -//| b in "domain" and x between 0 and 1. | -//| Relative error | -//| arithmetic domain # trials peak rms | -//| IEEE 0,5 10000 6.9e-15 4.5e-16 | -//| IEEE 0,85 250000 2.2e-13 1.7e-14 | -//| IEEE 0,1000 30000 5.3e-12 6.3e-13 | -//| IEEE 0,10000 250000 9.3e-11 7.1e-12 | -//| IEEE 0,100000 10000 8.7e-10 4.8e-11 | -//| Outputs smaller than the IEEE gradual underflow threshold | -//| were excluded from these statistics. | -//+------------------------------------------------------------------+ -static double CAlglib::IncompleteBeta(const double a,const double b,const double x) - { -//--- return result - return(CIncBetaF::IncompleteBeta(a,b,x)); - } -//+------------------------------------------------------------------+ -//| Inverse of imcomplete beta integral | -//| Given y, the function finds x such that | -//| incbet( a, b, x ) = y . | -//| The routine performs interval halving or Newton iterations to | -//| find the root of incbet(a,b,x) - y = 0. | -//| ACCURACY: | -//| Relative error: | -//| x a,b | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 | -//| IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 | -//| IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 | -//| With a and b constrained to half-integer or integer values: | -//| IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 | -//| IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 | -//| With a = .5, b constrained to half-integer or integer values: | -//| IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 | -//+------------------------------------------------------------------+ -static double CAlglib::InvIncompleteBeta(const double a,const double b,double y) - { -//--- return result - return(CIncBetaF::InvIncompleteBeta(a,b,y)); - } -//+------------------------------------------------------------------+ -//| Binomial distribution | -//| Returns the sum of the terms 0 through k of the Binomial | -//| probability density: | -//| k | -//| -- ( n ) j n-j | -//| > ( ) p (1-p) | -//| -- ( j ) | -//| j=0 | -//| The terms are not summed directly; instead the incomplete | -//| beta integral is employed, according to the formula | -//| y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). | -//| The arguments must be positive, with p ranging from 0 to 1. | -//| ACCURACY: | -//| Tested at random points (a,b,p), with p between 0 and 1. | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 4.3e-15 2.6e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::BinomialDistribution(const int k,const int n,const double p) - { -//--- return result - return(CBinomialDistr::BinomialDistribution(k,n,p)); - } -//+------------------------------------------------------------------+ -//| Complemented binomial distribution | -//| Returns the sum of the terms k+1 through n of the Binomial | -//| probability density: | -//| n | -//| -- ( n ) j n-j | -//| > ( ) p (1-p) | -//| -- ( j ) | -//| j=k+1 | -//| The terms are not summed directly; instead the incomplete | -//| beta integral is employed, according to the formula | -//| y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). | -//| The arguments must be positive, with p ranging from 0 to 1. | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 6.7e-15 8.2e-16 | -//| For p between 0 and .001: | -//| IEEE 0,100 100000 1.5e-13 2.7e-15 | -//+------------------------------------------------------------------+ -static double CAlglib::BinomialComplDistribution(const int k,const int n,const double p) - { -//--- return result - return(CBinomialDistr::BinomialComplDistribution(k,n,p)); - } -//+------------------------------------------------------------------+ -//| Inverse binomial distribution | -//| Finds the event probability p such that the sum of the | -//| terms 0 through k of the Binomial probability density | -//| is equal to the given cumulative probability y. | -//| This is accomplished using the inverse beta integral | -//| function and the relation | -//| 1 - p = incbi( n-k, k+1, y ). | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 2.3e-14 6.4e-16 | -//| IEEE 0,10000 100000 6.6e-12 1.2e-13 | -//| For p between 10^-6 and 0.001: | -//| IEEE 0,100 100000 2.0e-12 1.3e-14 | -//| IEEE 0,10000 100000 1.5e-12 3.2e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::InvBinomialDistribution(const int k,const int n,const double y) - { -//--- return result - return(CBinomialDistr::InvBinomialDistribution(k,n,y)); - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Chebyshev polynomials of the | -//| first and second kinds. | -//| Parameters: | -//| r - polynomial kind, either 1 or 2. | -//| n - degree, n>=0 | -//| x - argument, -1 <= x <= 1 | -//| Result: | -//| the value of the Chebyshev polynomial at x | -//+------------------------------------------------------------------+ -static double CAlglib::ChebyshevCalculate(int r,const int n,const double x) - { -//--- return result - return(CChebyshev::ChebyshevCalculate(r,n,x)); - } -//+------------------------------------------------------------------+ -//| Summation of Chebyshev polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) | -//| or | -//| c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) | -//| depending on the R. | -//| Parameters: | -//| r - polynomial kind, either 1 or 2. | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Chebyshev polynomial at x | -//+------------------------------------------------------------------+ -static double CAlglib::ChebyshevSum(double &c[],const int r,const int n,const double x) - { -//--- return result - return(CChebyshev::ChebyshevSum(c,r,n,x)); - } -//+------------------------------------------------------------------+ -//| Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CAlglib::ChebyshevCoefficients(const int n,double &c[]) - { -//--- function call - CChebyshev::ChebyshevCoefficients(n,c); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Conversion of a series of Chebyshev polynomials to a power | -//| series. | -//| Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as | -//| B[0] + B[1]*X + ... + B[N]*X^N. | -//| Input parameters: | -//| A - Chebyshev series coefficients | -//| N - degree, N>=0 | -//| Output parameters | -//| B - power series coefficients | -//+------------------------------------------------------------------+ -static void CAlglib::FromChebyshev(double &a[],const int n,double &b[]) - { -//--- function call - CChebyshev::FromChebyshev(a,n,b); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Chi-square distribution | -//| Returns the area under the left hand tail (from 0 to x) | -//| of the Chi square probability density function with | -//| v degrees of freedom. | -//| x | -//| - | -//| 1 | | v/2-1 -t/2 | -//| P( x | v ) = ----------- | t e dt | -//| v/2 - | | | -//| 2 | (v/2) - | -//| 0 | -//| where x is the Chi-square variable. | -//| The incomplete gamma integral is used, according to the | -//| formula | -//| y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::ChiSquareDistribution(const double v,const double x) - { -//--- return result - return(CChiSquareDistr::ChiSquareDistribution(v,x)); - } -//+------------------------------------------------------------------+ -//| Complemented Chi-square distribution | -//| Returns the area under the right hand tail (from x to | -//| infinity) of the Chi square probability density function | -//| with v degrees of freedom: | -//| inf. | -//| - | -//| 1 | | v/2-1 -t/2 | -//| P( x | v ) = ----------- | t e dt | -//| v/2 - | | | -//| 2 | (v/2) - | -//| x | -//| where x is the Chi-square variable. | -//| The incomplete gamma integral is used, according to the | -//| formula | -//| y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::ChiSquareComplDistribution(const double v,const double x) - { -//--- return result - return(CChiSquareDistr::ChiSquareComplDistribution(v,x)); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented Chi-square distribution | -//| Finds the Chi-square argument x such that the integral | -//| from x to infinity of the Chi-square density is equal | -//| to the given cumulative probability y. | -//| This is accomplished using the inverse gamma integral | -//| function and the relation | -//| x/2 = igami( df/2, y ); | -//| ACCURACY: | -//| See inverse incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::InvChiSquareDistribution(const double v,const double y) - { -//--- return result - return(CChiSquareDistr::InvChiSquareDistribution(v,y)); - } -//+------------------------------------------------------------------+ -//| Dawson's Integral | -//| Approximates the integral | -//| x | -//| - | -//| 2 | | 2 | -//| dawsn(x) = exp( -x ) | exp( t ) dt | -//| | | | -//| - | -//| 0 | -//| Three different rational approximations are employed, for | -//| the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,10 10000 6.9e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::DawsonIntegral(const double x) - { -//--- return result - return(CDawson::DawsonIntegral(x)); - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the first kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | | -//| | dt | -//| K(m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| using the approximation | -//| P(x) - log x Q(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 2.5e-16 6.8e-17 | -//+------------------------------------------------------------------+ -static double CAlglib::EllipticIntegralK(const double m) - { -//--- return result - return(CElliptic::EllipticIntegralK(m)); - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the first kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | | -//| | dt | -//| K(m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| where m = 1 - m1, using the approximation | -//| P(x) - log x Q(x). | -//| The argument m1 is used rather than m so that the logarithmic | -//| singularity at m = 1 will be shifted to the origin; this | -//| preserves maximum accuracy. | -//| K(0) = pi/2. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 2.5e-16 6.8e-17 | -//+------------------------------------------------------------------+ -static double CAlglib::EllipticIntegralKhighPrecision(const double m1) - { -//--- return result - return(CElliptic::EllipticIntegralKhighPrecision(m1)); - } -//+------------------------------------------------------------------+ -//| Incomplete elliptic integral of the first kind F(phi|m) | -//| Approximates the integral | -//| phi | -//| - | -//| | | | -//| | dt | -//| F(phi_\m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| of amplitude phi and modulus m, using the arithmetic - | -//| geometric mean algorithm. | -//| ACCURACY: | -//| Tested at random points with m in [0, 1] and phi as indicated. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -10,10 200000 7.4e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::IncompleteEllipticIntegralK(const double phi,const double m) - { -//--- return result - return(CElliptic::IncompleteEllipticIntegralK(phi,m)); - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the second kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | 2 | -//| E(m) = | sqrt( 1 - m sin t ) dt | -//| | | | -//| - | -//| 0 | -//| using the approximation | -//| P(x) - x log x Q(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 1 10000 2.1e-16 7.3e-17 | -//+------------------------------------------------------------------+ -static double CAlglib::EllipticIntegralE(const double m) - { -//--- return result - return(CElliptic::EllipticIntegralE(m)); - } -//+------------------------------------------------------------------+ -//| Incomplete elliptic integral of the second kind | -//| Approximates the integral | -//| phi | -//| - | -//| | | | -//| | 2 | -//| E(phi_\m) = | sqrt( 1 - m sin t ) dt | -//| | | -//| | | | -//| - | -//| 0 | -//| of amplitude phi and modulus m, using the arithmetic - | -//| geometric mean algorithm. | -//| ACCURACY: | -//| Tested at random arguments with phi in [-10, 10] and m in | -//| [0, 1]. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -10,10 150000 3.3e-15 1.4e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::IncompleteEllipticIntegralE(const double phi,const double m) - { -//--- return result - return(CElliptic::IncompleteEllipticIntegralE(phi,m)); - } -//+------------------------------------------------------------------+ -//| Exponential integral Ei(x) | -//| x | -//| - t | -//| | | e | -//| Ei(x) = -|- --- dt . | -//| | | t | -//| - | -//| -inf | -//| Not defined for x <= 0. | -//| See also expn.c. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,100 50000 8.6e-16 1.3e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::ExponentialIntegralEi(const double x) - { -//--- return result - return(CExpIntegrals::ExponentialIntegralEi(x)); - } -//+------------------------------------------------------------------+ -//| Exponential integral En(x) | -//| Evaluates the exponential integral | -//| inf. | -//| - | -//| | | -xt | -//| | e | -//| E (x) = | ---- dt. | -//| n | n | -//| | | t | -//| - | -//| 1 | -//| Both n and x must be nonnegative. | -//| The routine employs either a power series, a continued | -//| fraction, or an asymptotic formula depending on the | -//| relative values of n and x. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 10000 1.7e-15 3.6e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::ExponentialIntegralEn(const double x,const int n) - { -//--- return result - return(CExpIntegrals::ExponentialIntegralEn(x,n)); - } -//+------------------------------------------------------------------+ -//| F distribution | -//| Returns the area from zero to x under the F density | -//| function (also known as Snedcor's density or the | -//| variance ratio density). This is the density | -//| of x = (u1/df1)/(u2/df2), where u1 and u2 are random | -//| variables having Chi square distributions with df1 | -//| and df2 degrees of freedom, respectively. | -//| The incomplete beta integral is used, according to the | -//| formula | -//| P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). | -//| The arguments a and b are greater than zero, and x is | -//| nonnegative. | -//| ACCURACY: | -//| Tested at random points (a,b,x). | -//| x a,b Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 | -//| IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 | -//| IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 | -//| IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 | -//+------------------------------------------------------------------+ -static double CAlglib::FDistribution(const int a,const int b,const double x) - { -//--- return result - return(CFDistr::FDistribution(a,b,x)); - } -//+------------------------------------------------------------------+ -//| Complemented F distribution | -//| Returns the area from x to infinity under the F density | -//| function (also known as Snedcor's density or the | -//| variance ratio density). | -//| inf. | -//| - | -//| 1 | | a-1 b-1 | -//| 1-P(x) = ------ | t (1-t) dt | -//| B(a,b) | | | -//| - | -//| x | -//| The incomplete beta integral is used, according to the | -//| formula | -//| P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). | -//| ACCURACY: | -//| Tested at random points (a,b,x) in the indicated intervals. | -//| x a,b Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 | -//| IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 | -//| IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 | -//| IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 | -//+------------------------------------------------------------------+ -static double CAlglib::FComplDistribution(const int a,const int b,const double x) - { -//--- return result - return(CFDistr::FComplDistribution(a,b,x)); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented F distribution | -//| Finds the F density argument x such that the integral | -//| from x to infinity of the F density is equal to the | -//| given probability p. | -//| This is accomplished using the inverse beta integral | -//| function and the relations | -//| z = incbi( df2/2, df1/2, p ) | -//| x = df2 (1-z) / (df1 z). | -//| Note: the following relations hold for the inverse of | -//| the uncomplemented F distribution: | -//| z = incbi( df1/2, df2/2, p ) | -//| x = df2 z / (df1 (1-z)). | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between .001 and 1: | -//| IEEE 1,100 100000 8.3e-15 4.7e-16 | -//| IEEE 1,10000 100000 2.1e-11 1.4e-13 | -//| For p between 10^-6 and 10^-3: | -//| IEEE 1,100 50000 1.3e-12 8.4e-15 | -//| IEEE 1,10000 50000 3.0e-12 4.8e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::InvFDistribution(const int a,const int b,const double y) - { -//--- return result - return(CFDistr::InvFDistribution(a,b,y)); - } -//+------------------------------------------------------------------+ -//| Fresnel integral | -//| Evaluates the Fresnel integrals | -//| x | -//| - | -//| | | | -//| C(x) = | cos(pi/2 t**2) dt, | -//| | | | -//| - | -//| 0 | -//| x | -//| - | -//| | | | -//| S(x) = | sin(pi/2 t**2) dt. | -//| | | | -//| - | -//| 0 | -//| The integrals are evaluated by a power series for x < 1. | -//| For x >= 1 auxiliary functions f(x) and g(x) are employed | -//| such that | -//| C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) | -//| S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) | -//| ACCURACY: | -//| Relative error. | -//| Arithmetic function domain # trials peak rms | -//| IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16| -//| IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16| -//+------------------------------------------------------------------+ -static void CAlglib::FresnelIntegral(const double x,double &c,double &s) - { -//--- function call - CFresnel::FresnelIntegral(x,c,s); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Hermite polynomial. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Hermite polynomial Hn at x | -//+------------------------------------------------------------------+ -static double CAlglib::HermiteCalculate(const int n,const double x) - { -//--- return result - return(CHermite::HermiteCalculate(n,x)); - } -//+------------------------------------------------------------------+ -//| Summation of Hermite polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Hermite polynomial at x | -//+------------------------------------------------------------------+ -static double CAlglib::HermiteSum(double &c[],const int n,const double x) - { -//--- return result - return(CHermite::HermiteSum(c,n,x)); - } -//+------------------------------------------------------------------+ -//| Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CAlglib::HermiteCoefficients(const int n,double &c[]) - { -//--- function call - CHermite::HermiteCoefficients(n,c); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Jacobian Elliptic Functions | -//| Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), | -//| and dn(u|m) of parameter m between 0 and 1, and real | -//| argument u. | -//| These functions are periodic, with quarter-period on the | -//| real axis equal to the complete elliptic integral | -//| ellpk(1.0-m). | -//| Relation to incomplete elliptic integral: | -//| If u = ellik(phi,m), then sn(u|m) = sin(phi), | -//| and cn(u|m) = cos(phi). Phi is called the amplitude of u. | -//| Computation is by means of the arithmetic-geometric mean | -//| algorithm, except when m is within 1e-9 of 0 or 1. In the | -//| latter case with m close to 1, the approximation applies | -//| only for phi < pi/2. | -//| ACCURACY: | -//| Tested at random points with u between 0 and 10, m between | -//| 0 and 1. | -//| Absolute error (* = relative error): | -//| arithmetic function # trials peak rms | -//| IEEE phi 10000 9.2e-16* 1.4e-16* | -//| IEEE sn 50000 4.1e-15 4.6e-16 | -//| IEEE cn 40000 3.6e-15 4.4e-16 | -//| IEEE dn 10000 1.3e-12 1.8e-14 | -//| Peak error observed in consistency check using addition | -//| theorem for sn(u+v) was 4e-16 (absolute). Also tested by | -//| the above relation to the incomplete elliptic integral. | -//| Accuracy deteriorates when u is large. | -//+------------------------------------------------------------------+ -static void CAlglib::JacobianEllipticFunctions(const double u,const double m, - double &sn,double &cn, - double &dn,double &ph) - { -//--- create variables - sn=0; - cn=0; - dn=0; - ph=0; -//--- function call - CJacobianElliptic::JacobianEllipticFunctions(u,m,sn,cn,dn,ph); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Laguerre polynomial. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Laguerre polynomial Ln at x | -//+------------------------------------------------------------------+ -static double CAlglib::LaguerreCalculate(const int n,const double x) - { -//--- return result - return(CLaguerre::LaguerreCalculate(n,x)); - } -//+------------------------------------------------------------------+ -//| Summation of Laguerre polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + | -//| + c[N]*LN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Laguerre polynomial at x | -//+------------------------------------------------------------------+ -static double CAlglib::LaguerreSum(double &c[],const int n,const double x) - { -//--- return result - return(CLaguerre::LaguerreSum(c,n,x)); - } -//+------------------------------------------------------------------+ -//| Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CAlglib::LaguerreCoefficients(const int n,double &c[]) - { -//--- function call - CLaguerre::LaguerreCoefficients(n,c); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Legendre polynomial Pn. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Legendre polynomial Pn at x | -//+------------------------------------------------------------------+ -static double CAlglib::LegendreCalculate(const int n,const double x) - { -//--- return result - return(CLegendre::LegendreCalculate(n,x)); - } -//+------------------------------------------------------------------+ -//| Summation of Legendre polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Legendre polynomial at x | -//+------------------------------------------------------------------+ -static double CAlglib::LegendreSum(double &c[],const int n,const double x) - { -//--- return result - return(CLegendre::LegendreSum(c,n,x)); - } -//+------------------------------------------------------------------+ -//| Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CAlglib::LegendreCoefficients(const int n,double &c[]) - { -//--- function call - CLegendre::LegendreCoefficients(n,c); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Poisson distribution | -//| Returns the sum of the first k+1 terms of the Poisson | -//| distribution: | -//| k j | -//| -- -m m | -//| > e -- | -//| -- j! | -//| j=0 | -//| The terms are not summed directly; instead the incomplete | -//| gamma integral is employed, according to the relation | -//| y = pdtr( k, m ) = igamc( k+1, m ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::PoissonDistribution(const int k,const double m) - { -//--- return result - return(CPoissonDistr::PoissonDistribution(k,m)); - } -//+------------------------------------------------------------------+ -//| Complemented Poisson distribution | -//| Returns the sum of the terms k+1 to infinity of the Poisson | -//| distribution: | -//| inf. j | -//| -- -m m | -//| > e -- | -//| -- j! | -//| j=k+1 | -//| The terms are not summed directly; instead the incomplete | -//| gamma integral is employed, according to the formula | -//| y = pdtrc( k, m ) = igam( k+1, m ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::PoissonComplDistribution(const int k,const double m) - { -//--- return result - return(CPoissonDistr::PoissonComplDistribution(k,m)); - } -//+------------------------------------------------------------------+ -//| Inverse Poisson distribution | -//| Finds the Poisson variable x such that the integral | -//| from 0 to x of the Poisson density is equal to the | -//| given probability y. | -//| This is accomplished using the inverse gamma integral | -//| function and the relation | -//| m = igami( k+1, y ). | -//| ACCURACY: | -//| See inverse incomplete gamma function | -//+------------------------------------------------------------------+ -static double CAlglib::InvPoissonDistribution(const int k,const double y) - { -//--- return result - return(CPoissonDistr::InvPoissonDistribution(k,y)); - } -//+------------------------------------------------------------------+ -//| Psi (digamma) function | -//| d - | -//| psi(x) = -- ln | (x) | -//| dx | -//| is the logarithmic derivative of the gamma function. | -//| For integer x, | -//| n-1 | -//| - | -//| psi(n) = -EUL + > 1/k. | -//| - | -//| k=1 | -//| This formula is used for 0 < n <= 10. If x is negative, it | -//| is transformed to a positive argument by the reflection | -//| formula psi(1-x) = psi(x) + pi cot(pi x). | -//| For general positive x, the argument is made greater than 10 | -//| using the recurrence psi(x+1) = psi(x) + 1/x. | -//| Then the following asymptotic expansion is applied: | -//| inf. B | -//| - 2k | -//| psi(x) = log(x) - 1/2x - > ------- | -//| - 2k | -//| k=1 2k x | -//| where the B2k are Bernoulli numbers. | -//| ACCURACY: | -//| Relative error (except absolute when |psi| < 1): | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 1.3e-15 1.4e-16 | -//| IEEE -30,0 40000 1.5e-15 2.2e-16 | -//+------------------------------------------------------------------+ -static double CAlglib::Psi(const double x) - { -//--- return result - return(CPsiF::Psi(x)); - } -//+------------------------------------------------------------------+ -//| Student's t distribution | -//| Computes the integral from minus infinity to t of the Student | -//| t distribution with integer k > 0 degrees of freedom: | -//| t | -//| - | -//| | | | -//| - | 2 -(k+1)/2 | -//| | ( (k+1)/2 ) | ( x ) | -//| ---------------------- | ( 1 + --- ) dx | -//| - | ( k ) | -//| sqrt( k pi ) | ( k/2 ) | | -//| | | | -//| - | -//| -inf. | -//| Relation to incomplete beta integral: | -//| 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) | -//| where | -//| z = k/(k + t**2). | -//| For t < -2, this is the method of computation. For higher t, | -//| a direct method is derived from integration by parts. | -//| Since the function is symmetric about t=0, the area under the | -//| right tail of the density is found by calling the function | -//| with -t instead of t. | -//| ACCURACY: | -//| Tested at random 1 <= k <= 25. The "domain" refers to t. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -100,-2 50000 5.9e-15 1.4e-15 | -//| IEEE -2,100 500000 2.7e-15 4.9e-17 | -//+------------------------------------------------------------------+ -static double CAlglib::StudenttDistribution(const int k,const double t) - { -//--- return result - return(CStudenttDistr::StudenttDistribution(k,t)); - } -//+------------------------------------------------------------------+ -//| Functional inverse of Student's t distribution | -//| Given probability p, finds the argument t such that stdtr(k,t) | -//| is equal to p. | -//| ACCURACY: | -//| Tested at random 1 <= k <= 100. The "domain" refers to p: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE .001,.999 25000 5.7e-15 8.0e-16 | -//| IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 | -//+------------------------------------------------------------------+ -static double CAlglib::InvStudenttDistribution(const int k,const double p) - { -//--- return result - return(CStudenttDistr::InvStudenttDistribution(k,p)); - } -//+------------------------------------------------------------------+ -//| Sine and cosine integrals | -//| Evaluates the integrals | -//| x | -//| - | -//| | cos t - 1 | -//| Ci(x) = eul + ln x + | --------- dt, | -//| | t | -//| - | -//| 0 | -//| x | -//| - | -//| | sin t | -//| Si(x) = | ----- dt | -//| | t | -//| - | -//| 0 | -//| where eul = 0.57721566490153286061 is Euler's constant. | -//| The integrals are approximated by rational functions. | -//| For x > 8 auxiliary functions f(x) and g(x) are employed | -//| such that | -//| Ci(x) = f(x) sin(x) - g(x) cos(x) | -//| Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) | -//| ACCURACY: | -//| Test interval = [0,50]. | -//| Absolute error, except relative when > 1: | -//| arithmetic function # trials peak rms | -//| IEEE Si 30000 4.4e-16 7.3e-17 | -//| IEEE Ci 30000 6.9e-16 5.1e-17 | -//+------------------------------------------------------------------+ -static void CAlglib::SineCosineIntegrals(const double x,double &si,double &ci) - { -//--- initialization - si=0; - ci=0; -//--- function call - CTrigIntegrals::SineCosineIntegrals(x,si,ci); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Hyperbolic sine and cosine integrals | -//| Approximates the integrals | -//| x | -//| - | -//| | | cosh t - 1 | -//| Chi(x) = eul + ln x + | ----------- dt, | -//| | | t | -//| - | -//| 0 | -//| x | -//| - | -//| | | sinh t | -//| Shi(x) = | ------ dt | -//| | | t | -//| - | -//| 0 | -//| where eul = 0.57721566490153286061 is Euler's constant. | -//| The integrals are evaluated by power series for x < 8 | -//| and by Chebyshev expansions for x between 8 and 88. | -//| For large x, both functions approach exp(x)/2x. | -//| Arguments greater than 88 in magnitude return MAXNUM. | -//| ACCURACY: | -//| Test interval 0 to 88. | -//| Relative error: | -//| arithmetic function # trials peak rms | -//| IEEE Shi 30000 6.9e-16 1.6e-16 | -//| Absolute error, except relative when |Chi| > 1: | -//| IEEE Chi 30000 8.4e-16 1.4e-16 | -//+------------------------------------------------------------------+ -static void CAlglib::HyperbolicSineCosineIntegrals(const double x,double &shi,double &chi) - { -//--- initialization - shi=0; - chi=0; -//--- function call - CTrigIntegrals::HyperbolicSineCosineIntegrals(x,shi,chi); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Calculation of the distribution moments: mean, variance, | -//| skewness, kurtosis. | -//| INPUT PARAMETERS: | -//| X - sample | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from | -//| size of X | -//| OUTPUT PARAMETERS | -//| Mean - mean. | -//| Variance- variance. | -//| Skewness- skewness (if variance<>0; zero otherwise). | -//| Kurtosis- kurtosis (if variance<>0; zero otherwise). | -//+------------------------------------------------------------------+ -static void CAlglib::SampleMoments(const double &x[],const int n,double &mean, - double &variance,double &skewness, - double &kurtosis) - { -//--- initialization - mean=0; - variance=0; - skewness=0; - kurtosis=0; -//--- function call - CBaseStat::SampleMoments(x,n,mean,variance,skewness,kurtosis); - } -//+------------------------------------------------------------------+ -//| Calculation of the distribution moments: mean, variance, | -//| skewness, kurtosis. | -//| INPUT PARAMETERS: | -//| X - sample | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from | -//| size of X | -//| OUTPUT PARAMETERS | -//| Mean - mean. | -//| Variance- variance. | -//| Skewness- skewness (if variance<>0; zero otherwise). | -//| Kurtosis- kurtosis (if variance<>0; zero otherwise). | -//+------------------------------------------------------------------+ -static void CAlglib::SampleMoments(const double &x[],double &mean, - double &variance,double &skewness, - double &kurtosis) - { -//--- create a variable - int n; -//--- initialization - mean=0; - variance=0; - skewness=0; - kurtosis=0; -//--- get lenght - n=CAp::Len(x); -//--- function call - CBaseStat::SampleMoments(x,n,mean,variance,skewness,kurtosis); - } -//+------------------------------------------------------------------+ -//| ADev | -//| Input parameters: | -//| X - sample | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| ADev- ADev | -//+------------------------------------------------------------------+ -static void CAlglib::SampleAdev(const double &x[],const int n,double &adev) - { -//--- initialization - adev=0; -//--- function call - CBaseStat::SampleAdev(x,n,adev); - } -//+------------------------------------------------------------------+ -//| ADev | -//| Input parameters: | -//| X - sample | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| ADev- ADev | -//+------------------------------------------------------------------+ -static void CAlglib::SampleAdev(const double &x[],double &adev) - { -//--- create a variable - int n=CAp::Len(x); -//--- initialization - adev=0; -//--- function call - CBaseStat::SampleAdev(x,n,adev); - } -//+------------------------------------------------------------------+ -//| Median calculation. | -//| Input parameters: | -//| X - sample (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| Median | -//+------------------------------------------------------------------+ -static void CAlglib::SampleMedian(const double &x[],const int n,double &median) - { -//--- initialization - median=0; -//--- function call - CBaseStat::SampleMedian(x,n,median); - } -//+------------------------------------------------------------------+ -//| Median calculation. | -//| Input parameters: | -//| X - sample (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| Median | -//+------------------------------------------------------------------+ -static void CAlglib::SampleMedian(const double &x[],double &median) - { -//--- create a variable - int n=CAp::Len(x); -//--- initialization - median=0; -//--- function call - CBaseStat::SampleMedian(x,n,median); - } -//+------------------------------------------------------------------+ -//| Percentile calculation. | -//| Input parameters: | -//| X - sample (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| P - percentile (0<=P<=1) | -//| Output parameters: | -//| V - percentile | -//+------------------------------------------------------------------+ -static void CAlglib::SamplePercentile(const double &x[],const int n, - const double p,double &v) - { -//--- initialization - v=0; -//--- function call - CBaseStat::SamplePercentile(x,n,p,v); - } -//+------------------------------------------------------------------+ -//| Percentile calculation. | -//| Input parameters: | -//| X - sample (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| P - percentile (0<=P<=1) | -//| Output parameters: | -//| V - percentile | -//+------------------------------------------------------------------+ -static void CAlglib::SamplePercentile(const double &x[],const double p, - double &v) - { -//--- create a variable - int n=CAp::Len(x); -//--- initialization - v=0; -//--- function call - CBaseStat::SamplePercentile(x,n,p,v); - } -//+------------------------------------------------------------------+ -//| 2-sample covariance | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| covariance (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::Cov2(const double &x[],const double &y[],const int n) - { -//--- return result - return(CBaseStat::Cov2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| 2-sample covariance | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| covariance (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::Cov2(const double &x[],const double &y[]) - { -//--- check - if(CAp::Len(x)!=CAp::Len(y)) - { - Print(__FUNCTION__+": arrays size are not equal"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- create a variable - int n=CAp::Len(x); -//--- return result - return(CBaseStat::Cov2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment correlation coefficient | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Pearson product-moment correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::PearsonCorr2(const double &x[],const double &y[], - const int n) - { -//--- return result - return(CBaseStat::PearsonCorr2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment correlation coefficient | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Pearson product-moment correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::PearsonCorr2(const double &x[],const double &y[]) - { -//--- check - if(CAp::Len(x)!=CAp::Len(y)) - { - Print(__FUNCTION__+": arrays size are not equal"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- create a variable - int n=CAp::Len(x); -//--- return result - return(CBaseStat::PearsonCorr2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation coefficient | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Spearman's rank correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::SpearmanCorr2(const double &x[],const double &y[], - const int n) - { -//--- return result - return(CBaseStat::SpearmanCorr2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation coefficient | -//| Input parameters: | -//| X - sample 1 (array indexes: [0..N-1]) | -//| Y - sample 2 (array indexes: [0..N-1]) | -//| N - N>=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Spearman's rank correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CAlglib::SpearmanCorr2(const double &x[],const double &y[]) - { -//--- check - if(CAp::Len(x)!=CAp::Len(y)) - { - Print(__FUNCTION__+": arrays size are not equal"); - CAp::exception_happened=true; - return(EMPTY_VALUE); - } -//--- create a variable - int n=CAp::Len(x); -//--- return result - return(CBaseStat::SpearmanCorr2(x,y,n)); - } -//+------------------------------------------------------------------+ -//| Covariance matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], covariance matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::CovM(const CMatrixDouble &x,const int n,const int m, - CMatrixDouble &c) - { -//--- function call - CBaseStat::CovM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Covariance matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], covariance matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::CovM(const CMatrixDouble &x,CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m=CAp::Cols(x); -//--- function call - CBaseStat::CovM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::PearsonCorrM(const CMatrixDouble &x,const int n, - const int m,CMatrixDouble &c) - { -//--- function call - CBaseStat::PearsonCorrM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::PearsonCorrM(CMatrixDouble &x,CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m=CAp::Cols(x); -//--- function call - CBaseStat::PearsonCorrM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::SpearmanCorrM(const CMatrixDouble &x,const int n, - const int m,CMatrixDouble &c) - { -//--- function call - CBaseStat::SpearmanCorrM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::SpearmanCorrM(const CMatrixDouble &x,CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m=CAp::Cols(x); -//--- function call - CBaseStat::SpearmanCorrM(x,n,m,c); - } -//+------------------------------------------------------------------+ -//| Cross-covariance matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-covariance matrix (zero if N=0 or| -//| N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::CovM2(const CMatrixDouble &x,const CMatrixDouble &y, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- function call - CBaseStat::CovM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Cross-covariance matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-covariance matrix (zero if N=0 or| -//| N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::CovM2(const CMatrixDouble &x,const CMatrixDouble &y, - CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m1=CAp::Cols(x); - int m2=CAp::Cols(y); -//--- check - if(CAp::Rows(x)!=CAp::Rows(y)) - { - Print(__FUNCTION__+": rows size are not equal"); - CAp::exception_happened=true; - return; - } -//--- function call - CBaseStat::CovM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment cross-correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- function call - CBaseStat::PearsonCorrM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Pearson product-moment cross-correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y, - CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m1=CAp::Cols(x); - int m2=CAp::Cols(y); -//--- check - if(CAp::Rows(x)!=CAp::Rows(y)) - { - Print(__FUNCTION__+": rows size are not equal"); - CAp::exception_happened=true; - return; - } -//--- function call - CBaseStat::PearsonCorrM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Spearman's rank cross-correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- function call - CBaseStat::SpearmanCorrM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Spearman's rank cross-correlation matrix | -//| INPUT PARAMETERS: | -//| X - array[N,M1], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| Y - array[N,M2], sample matrix: | -//| * J-th column corresponds to J-th variable | -//| * I-th row corresponds to I-th observation | -//| N - N>=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static void CAlglib::SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y, - CMatrixDouble &c) - { -//--- create variables - int n=CAp::Rows(x); - int m1=CAp::Cols(x); - int m2=CAp::Cols(y); -//--- check - if(CAp::Rows(x)!=CAp::Rows(y)) - { - Print(__FUNCTION__+": rows size are not equal"); - CAp::exception_happened=true; - return; - } -//--- function call - CBaseStat::SpearmanCorrM2(x,y,n,m1,m2,c); - } -//+------------------------------------------------------------------+ -//| Pearson's correlation coefficient significance test | -//| This test checks hypotheses about whether X and Y are samples of| -//| two continuous distributions having zero correlation or whether | -//| their correlation is non-zero. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - X and Y have zero | -//| correlation) | -//| * left-tailed test (null hypothesis - the correlation | -//| coefficient is greater than or equal to 0) | -//| * right-tailed test (null hypothesis - the correlation | -//| coefficient is less than or equal to 0). | -//| Requirements: | -//| * the number of elements in each sample is not less than 5 | -//| * normality of distributions of X and Y. | -//| Input parameters: | -//| R - Pearson's correlation coefficient for X and Y | -//| N - number of elements in samples, N>=5. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::PearsonCorrelationSignificance(const double r,const int n, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CCorrTests::PearsonCorrSignific(r,n,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation coefficient significance test | -//| This test checks hypotheses about whether X and Y are samples of | -//| two continuous distributions having zero correlation or whether | -//| their correlation is non-zero. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - X and Y have zero | -//| correlation) | -//| * left-tailed test (null hypothesis - the correlation | -//| coefficient is greater than or equal to 0) | -//| * right-tailed test (null hypothesis - the correlation | -//| coefficient is less than or equal to 0). | -//| Requirements: | -//| * the number of elements in each sample is not less than 5. | -//| The test is non-parametric and doesn't require distributions X | -//| and Y to be normal. | -//| Input parameters: | -//| R - Spearman's rank correlation coefficient for X and Y | -//| N - number of elements in samples, N>=5. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::SpearmanRankCorrelationSignificance(const double r, - const int n, - double &bothTails, - double &leftTail, - double &rightTail) - { -//--- function call - CCorrTests::SpearmanRankCorrSignific(r,n,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Jarque-Bera test | -//| This test checks hypotheses about the fact that a given sample X | -//| is a sample of normal random variable. | -//| Requirements: | -//| * the number of elements in the sample is not less than 5. | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of the sample. N>=5 | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| Accuracy of the approximation used (5<=N<=1951): | -//| p-value relative error (5<=N<=1951) | -//| [1, 0.1] < 1% | -//| [0.1, 0.01] < 2% | -//| [0.01, 0.001] < 6% | -//| [0.001, 0] wasn't measured | -//| For N>1951 accuracy wasn't measured but it shouldn't be sharply | -//| different from table values. | -//+------------------------------------------------------------------+ -static void CAlglib::JarqueBeraTest(const double &x[],const int n,double &p) - { -//--- create a variable - p=0; -//--- function call - CJarqueBera::JarqueBeraTest(x,n,p); - } -//+------------------------------------------------------------------+ -//| Mann-Whitney U-test | -//| This test checks hypotheses about whether X and Y are samples of | -//| two continuous distributions of the same shape and same median or| -//| whether their medians are different. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - the medians are equal) | -//| * left-tailed test (null hypothesis - the median of the first| -//| sample is greater than or equal to the median of the second| -//| sample) | -//| * right-tailed test (null hypothesis - the median of the | -//| first sample is less than or equal to the median of the | -//| second sample). | -//| Requirements: | -//| * the samples are independent | -//| * X and Y are continuous distributions (or discrete | -//| distributions well- approximating continuous distributions)| -//| * distributions of X and Y have the same shape. The only | -//| possible difference is their position (i.e. the value of | -//| the median) | -//| * the number of elements in each sample is not less than 5 | -//| * the scale of measurement should be ordinal, interval or | -//| ratio (i.e. the test could not be applied to nominal | -//| variables). | -//| The test is non-parametric and doesn't require distributions to | -//| be normal. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - size of the sample. N>=5 | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - size of the sample. M>=5 | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| To calculate p-values, special approximation is used. This | -//| method lets us calculate p-values with satisfactory accuracy in | -//| interval [0.0001, 1]. There is no approximation outside the | -//| [0.0001, 1] interval. Therefore, if the significance level | -//| outlies this interval, the test returns 0.0001. | -//| Relative precision of approximation of p-value: | -//| N M Max.err. Rms.err. | -//| 5..10 N..10 1.4e-02 6.0e-04 | -//| 5..10 N..100 2.2e-02 5.3e-06 | -//| 10..15 N..15 1.0e-02 3.2e-04 | -//| 10..15 N..100 1.0e-02 2.2e-05 | -//| 15..100 N..100 6.1e-03 2.7e-06 | -//| For N,M>100 accuracy checks weren't put into practice, but taking| -//| into account characteristics of asymptotic approximation used, | -//| precision should not be sharply different from the values for | -//| interval [5, 100]. | -//+------------------------------------------------------------------+ -static void CAlglib::MannWhitneyUTest(const double &x[],const int n, - const double &y[],const int m, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CMannWhitneyU::CMannWhitneyUTest(x,n,y,m,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Sign test | -//| This test checks three hypotheses about the median of the given | -//| sample. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - the median is equal to | -//| the given value) | -//| * left-tailed test (null hypothesis - the median is greater | -//| than or equal to the given value) | -//| * right-tailed test (null hypothesis - the median is less | -//| than or equal to the given value) | -//| Requirements: | -//| * the scale of measurement should be ordinal, interval or | -//| ratio (i.e. the test could not be applied to nominal | -//| variables). | -//| The test is non-parametric and doesn't require distribution X to | -//| be normal | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of the sample. | -//| Median - assumed median value. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance levelthe null hypothesis is | -//| rejected. | -//| While calculating p-values high-precision binomial distribution | -//| approximation is used, so significance levels have about 15 exact| -//| digits. | -//+------------------------------------------------------------------+ -static void CAlglib::OneSampleSignTest(const double &x[],const int n, - const double median,double &bothTails, - double &leftTail,double &rightTail) - { -//--- function call - CSignTest::OneSampleSignTest(x,n,median,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| One-sample t-test | -//| This test checks three hypotheses about the mean of the given | -//| sample. The following tests are performed: | -//| * two-tailed test (null hypothesis - the mean is equal to the| -//| given value) | -//| * left-tailed test (null hypothesis - the mean is greater | -//| than or equal to the given value) | -//| * right-tailed test (null hypothesis - the mean is less than | -//| or equal to the given value). | -//| The test is based on the assumption that a given sample has a | -//| normal distribution and an unknown dispersion. If the | -//| distribution sharply differs from normal, the test will work | -//| incorrectly. | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of sample. | -//| Mean - assumed value of the mean. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::StudentTest1(const double &x[],const int n,const double mean, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CStudentTests::StudentTest1(x,n,mean,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Two-sample pooled test | -//| This test checks three hypotheses about the mean of the given | -//| samples. The following tests are performed: | -//| * two-tailed test (null hypothesis - the means are equal) | -//| * left-tailed test (null hypothesis - the mean of the first | -//| sample is greater than or equal to the mean of the second | -//| sample) | -//| * right-tailed test (null hypothesis - the mean of the first | -//| sample is less than or equal to the mean of the second | -//| sample). | -//| Test is based on the following assumptions: | -//| * given samples have normal distributions | -//| * dispersions are equal | -//| * samples are independent. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - size of sample. | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - size of sample. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::StudentTest2(const double &x[],const int n,const double &y[], - const int m,double &bothTails, - double &leftTail,double &rightTail) - { -//--- function call - CStudentTests::StudentTest2(x,n,y,m,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Two-sample unpooled test | -//| This test checks three hypotheses about the mean of the given | -//| samples. The following tests are performed: | -//| * two-tailed test (null hypothesis - the means are equal) | -//| * left-tailed test (null hypothesis - the mean of the first | -//| sample is greater than or equal to the mean of the second | -//| sample) | -//| * right-tailed test (null hypothesis - the mean of the first | -//| sample is less than or equal to the mean of the second | -//| sample). | -//| Test is based on the following assumptions: | -//| * given samples have normal distributions | -//| * samples are independent. | -//| Dispersion equality is not required | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - size of the sample. | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - size of the sample. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::UnequalVarianceTest(const double &x[],const int n, - const double &y[],const int m, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CStudentTests::UnequalVarianceTest(x,n,y,m,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Two-sample F-test | -//| This test checks three hypotheses about dispersions of the given | -//| samples. The following tests are performed: | -//| * two-tailed test (null hypothesis - the dispersions are | -//| equal) | -//| * left-tailed test (null hypothesis - the dispersion of the | -//| first sample is greater than or equal to the dispersion of | -//| the second sample). | -//| * right-tailed test (null hypothesis - the dispersion of the | -//| first sample is less than or equal to the dispersion of | -//| the second sample) | -//| The test is based on the following assumptions: | -//| * the given samples have normal distributions | -//| * the samples are independent. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - sample size. | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - sample size. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::FTest(const double &x[],const int n,const double &y[], - const int m,double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CVarianceTests::FTest(x,n,y,m,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| One-sample chi-square test | -//| This test checks three hypotheses about the dispersion of the | -//| given sample The following tests are performed: | -//| * two-tailed test (null hypothesis - the dispersion equals | -//| the given number) | -//| * left-tailed test (null hypothesis - the dispersion is | -//| greater than or equal to the given number) | -//| * right-tailed test (null hypothesis - dispersion is less | -//| than or equal to the given number). | -//| Test is based on the following assumptions: | -//| * the given sample has a normal distribution. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to | -//| N-1. | -//| N - size of the sample. | -//| Variance - dispersion value to compare with. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CAlglib::OneSampleVarianceTest(double &x[],int n,double variance, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- function call - CVarianceTests::OneSampleVarianceTest(x,n,variance,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ -//| Wilcoxon signed-rank test | -//| This test checks three hypotheses about the median of the given | -//| sample. The following tests are performed: | -//| * two-tailed test (null hypothesis - the median is equal to | -//| the given value) | -//| * left-tailed test (null hypothesis - the median is greater | -//| than or equal to the given value) | -//| * right-tailed test (null hypothesis - the median is less | -//| than or equal to the given value) | -//| Requirements: | -//| * the scale of measurement should be ordinal, interval or | -//| ratio (i.e. the test could not be applied to nominal | -//| variables). | -//| * the distribution should be continuous and symmetric | -//| relative to its median. | -//| * number of distinct values in the X array should be greater | -//| than 4 | -//| The test is non-parametric and doesn't require distribution X to | -//| be normal | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of the sample. | -//| Median - assumed median value. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| To calculate p-values, special approximation is used. This method| -//| lets us calculate p-values with two decimal places in interval | -//| [0.0001, 1]. | -//| "Two decimal places" does not sound very impressive, but in | -//| practice the relative error of less than 1% is enough to make a | -//| decision. | -//| There is no approximation outside the [0.0001, 1] interval. | -//| Therefore, if the significance level outlies this interval, the | -//| test returns 0.0001. | -//+------------------------------------------------------------------+ -static void CAlglib::WilcoxonSignedRankTest(const double &x[],const int n, - const double e,double &bothTails, - double &leftTail,double &rightTail) - { -//--- function call - CWilcoxonSignedRank::WilcoxonSignedRankTest(x,n,e,bothTails,leftTail,rightTail); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/alglibinternal.mqh b/Include/Math/Alglib/alglibinternal.mqh deleted file mode 100644 index 81031a5..0000000 --- a/Include/Math/Alglib/alglibinternal.mqh +++ /dev/null @@ -1,9732 +0,0 @@ -//+------------------------------------------------------------------+ -//| alglibinternal.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org);either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY;without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "ap.mqh" -//+------------------------------------------------------------------+ -//| Class stores serialized codes | -//+------------------------------------------------------------------+ -class CSCodes - { -public: - CSCodes(void); - ~CSCodes(void); - - static int GetRDFSerializationCode(void) { return(1); } - static int GetKDTreeSerializationCode(void) { return(2); } - static int GetMLPSerializationCode(void) { return(3); } - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSCodes::CSCodes(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSCodes::~CSCodes(void) - { - - } -//+------------------------------------------------------------------+ -//| Buffers for internal functions which need buffers: | -//| * check for size of the buffer you want to use. | -//| * if buffer is too small, resize it; leave unchanged, if it is | -//| larger than needed. | -//| * use it. | -//| We can pass this structure to multiple functions; after first | -//| run through functions buffer sizes will be finally determined, | -//| and on a next run no allocation will be required. | -//+------------------------------------------------------------------+ -class CApBuff - { -public: - //--- arrays - int m_ia0[]; - int m_ia1[]; - int m_ia2[]; - int m_ia3[]; - double m_ra0[]; - double m_ra1[]; - double m_ra2[]; - double m_ra3[]; - //--- constructor, destructor - CApBuff(void); - ~CApBuff(void); - //--- copy - void Copy(CApBuff &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CApBuff::CApBuff(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CApBuff::~CApBuff(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CApBuff::Copy(CApBuff &obj) - { -//--- copy arrays - ArrayCopy(m_ia0,obj.m_ia0); - ArrayCopy(m_ia1,obj.m_ia1); - ArrayCopy(m_ia2,obj.m_ia2); - ArrayCopy(m_ia3,obj.m_ia3); - ArrayCopy(m_ra0,obj.m_ra0); - ArrayCopy(m_ra1,obj.m_ra1); - ArrayCopy(m_ra2,obj.m_ra2); - ArrayCopy(m_ra3,obj.m_ra3); - } -//+------------------------------------------------------------------+ -//| Basic functions | -//+------------------------------------------------------------------+ -class CApServ - { -public: - CApServ(void); - ~CApServ(void); - //--- generate interpolation - static void TaskGenInt1D(const double a,const double b,const int n,double &x[],double &y[]); - static void TaskGenInt1DEquidist(const double a,const double b,const int n,double &x[],double &y[]); - static void TaskGenInt1DCheb1(const double a,const double b,const int n,double &x[],double &y[]); - static void TaskGenInt1DCheb2(const double a,const double b,const int n,double &x[],double &y[]); - //--- distinct - static bool AreDistinct(double &x[],const int n); - //--- resize arrays - static void BVectorSetLengthAtLeast(bool &x[],const int n); - static void IVectorSetLengthAtLeast(int &x[],const int n); - static void RVectorSetLengthAtLeast(double &x[],const int n); - static void RMatrixSetLengthAtLeast(CMatrixDouble &x,const int m,const int n); - //--- resize matrix - static void RMatrixResize(CMatrixDouble &x,const int m,const int n); - //--- check to infinity - static bool IsFiniteVector(const double &x[],const int n); - static bool IsFiniteComplexVector(al_complex &z[],const int n); - static bool IsFiniteMatrix(const CMatrixDouble &x,const int m,const int n); - static bool IsFiniteComplexMatrix(CMatrixComplex &x,const int m,const int n); - static bool IsFiniteRTrMatrix(CMatrixDouble &x,const int n,const bool isupper); - static bool IsFiniteCTrMatrix(CMatrixComplex &x,const int n,const bool isupper); - static bool IsFiniteOrNaNMatrix(CMatrixDouble &x,const int m,const int n); - //--- safe methods - static double SafePythag2(const double x,const double y); - static double SafePythag3(double x,double y,double z); - static int SafeRDiv(double x,double y,double &r); - static double SafeMinPosRV(const double x,const double y,const double v); - static void ApPeriodicMap(double &x,const double a,const double b,double &k); - static double BoundVal(const double x,const double b1,const double b2); - //--- serialization/unserialization - static void AllocComplex(CSerializer &s,al_complex &v); - static void SerializeComplex(CSerializer &s,al_complex &v); - static al_complex UnserializeComplex(CSerializer &s); - static void AllocRealArray(CSerializer &s,double &v[],int n); - static void SerializeRealArray(CSerializer &s,double &v[],int n); - static void UnserializeRealArray(CSerializer &s,double &v[]); - static void AllocIntegerArray(CSerializer &s,int &v[],int n); - static void SerializeIntegerArray(CSerializer &s,int &v[],int n); - static void UnserializeIntegerArray(CSerializer &s,int &v[]); - static void AllocRealMatrix(CSerializer &s,CMatrixDouble &v,int n0,int n1); - static void SerializeRealMatrix(CSerializer &s,CMatrixDouble &v,int n0,int n1); - static void UnserializeRealMatrix(CSerializer &s,CMatrixDouble &v); - //--- copy - static void CopyIntegerArray(int &src[],int &dst[]); - static void CopyRealArray(double &src[],double &dst[]); - static void CopyRealMatrix(CMatrixDouble &src,CMatrixDouble &dst); - //--- check array - static int RecSearch(int &a[],const int nrec,const int nheader,int i0,int i1,int &b[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CApServ::CApServ(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CApServ::~CApServ(void) - { - - } -//+------------------------------------------------------------------+ -//| This function generates 1-dimensional general interpolation | -//| task with moderate Lipshitz constant (close to 1.0) | -//| If N=1 then suborutine generates only one point at the middle | -//| of [A,B] | -//+------------------------------------------------------------------+ -static void CApServ::TaskGenInt1D(const double a,const double b,const int n, - double &x[],double &y[]) - { -//--- create variables - int i=0; - double h=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); -//--- check - if(n>1) - { - //--- change values - x[0]=a; - y[0]=2*CMath::RandomReal()-1; - h=(b-a)/(n-1); - for(i=1;i<=n-1;i++) - { - //--- check - if(i!=n-1) - x[i]=a+(i+0.2*(2*CMath::RandomReal()-1))*h; - else - x[i]=b; - y[i]=y[i-1]+(2*CMath::RandomReal()-1)*(x[i]-x[i-1]); - } - } - else - { - //--- change values - x[0]=0.5*(a+b); - y[0]=2*CMath::RandomReal()-1; - } - } -//+------------------------------------------------------------------+ -//| This function generates 1-dimensional equidistant interpolation | -//| task withmoderate Lipshitz constant(close to 1.0) | -//| If N=1 then suborutine generates only one point at the middle | -//| of[A,B] | -//+------------------------------------------------------------------+ -static void CApServ::TaskGenInt1DEquidist(const double a,const double b, - const int n,double &x[],double &y[]) - { -//--- create variables - int i=0; - double h=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); -//--- check - if(n>1) - { - //--- change values - x[0]=a; - y[0]=2*CMath::RandomReal()-1; - h=(b-a)/(n-1); - for(i=1;i<=n-1;i++) - { - x[i]=a+i*h; - y[i]=y[i-1]+(2*CMath::RandomReal()-1)*h; - } - } - else - { - //--- change values - x[0]=0.5*(a+b); - y[0]=2*CMath::RandomReal()-1; - } - } -//+------------------------------------------------------------------+ -//| This function generates 1-dimensional Chebyshev-1 interpolation | -//| task with moderate Lipshitz constant(close to 1.0) | -//| If N=1 then suborutine generates only one point at the middle | -//| of[A,B] | -//+------------------------------------------------------------------+ -static void CApServ::TaskGenInt1DCheb1(const double a,const double b, - const int n,double &x[],double &y[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); -//--- check - if(n>1) - { - for(i=0;i<=n-1;i++) - { - x[i]=0.5*(b+a)+0.5*(b-a)*MathCos(M_PI*(2*i+1)/(2*n)); - //--- check - if(i==0) - y[i]=2*CMath::RandomReal()-1; - else - y[i]=y[i-1]+(2*CMath::RandomReal()-1)*(x[i]-x[i-1]); - } - } - else - { - //--- change values - x[0]=0.5*(a+b); - y[0]=2*CMath::RandomReal()-1; - } - } -//+------------------------------------------------------------------+ -//| This function generates 1-dimensional Chebyshev-2 interpolation | -//| task with moderate Lipshitz constant(close to 1.0) | -//| If N=1 then suborutine generates only one point at the middle | -//| of[A,B] | -//+------------------------------------------------------------------+ -static void CApServ::TaskGenInt1DCheb2(const double a,const double b, - const int n,double &x[],double &y[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); -//--- check - if(n>1) - { - for(i=0;i<=n-1;i++) - { - x[i]=0.5*(b+a)+0.5*(b-a)*MathCos(M_PI*i/(n-1)); - //--- check - if(i==0) - y[i]=2*CMath::RandomReal()-1; - else - y[i]=y[i-1]+(2*CMath::RandomReal()-1)*(x[i]-x[i-1]); - } - } - else - { - //--- change values - x[0]=0.5*(a+b); - y[0]=2*CMath::RandomReal()-1; - } - } -//+------------------------------------------------------------------+ -//| This function checks that all values from X[] are distinct. | -//| It does more than just usual floating point comparison: | -//| * first, it calculates max(X) and min(X) | -//| * second, it maps X[] from [min,max] to [1,2] | -//| * only at this stage actual comparison is done | -//| The meaning of such check is to ensure that all values are | -//| "distinct enough" and will not cause interpolation subroutine | -//| to fail. | -//| NOTE: | -//| X[] must be sorted by ascending (subroutine ASSERT's it) | -//+------------------------------------------------------------------+ -static bool CApServ::AreDistinct(double &x[],const int n) - { -//--- create variables - double a=0; - double b=0; - int i=0; - bool nonsorted; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": internal error (N<1)")) - return(false); -//--- check - if(n==1) - { - //--- everything is alright, it is up to caller to decide whether it - //--- can interpolate something with just one point - return(true); - } -//--- initialization - a=x[0]; - b=x[0]; - nonsorted=false; - for(i=1;i<=n-1;i++) - { - a=MathMin(a,x[i]); - b=MathMax(b,x[i]); - nonsorted=nonsorted || x[i-1]>=x[i]; - } -//--- check - if(!CAp::Assert(!nonsorted,__FUNCTION__+": internal error (not sorted)")) - return(false); - for(i=1;i<=n-1;i++) - { - //--- check - if((x[i]-a)/(b-a)+1==(x[i-1]-a)/(b-a)+1) - return(false); - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| If Length(X)=0,__FUNCTION__+": internal error (N<0)")) - return(false); - for(i=0;i<=n-1;i++) - { - //--- check - if(!CMath::IsFinite(z[i].re) || !CMath::IsFinite(z[i].im)) - return(false); - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| This function checks that all values from X[] are finite | -//+------------------------------------------------------------------+ -static bool CApServ::IsFiniteVector(const double &x[],const int n) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- is finite? - for(int i=0;i=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m>=0,__FUNCTION__+": the error variable")) - return(false); -//--- is finite? - for(int i=0;i=0,__FUNCTION__+": internal error (N<0)")) - return(false); -//--- check - if(!CAp::Assert(m>=0,__FUNCTION__+": internal error (M<0)")) - return(false); -//--- is finite? - for(i=0;i=0,__FUNCTION__+": internal error (N<0)")) - return(false); - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - for(j=j1;j<=j2;j++) - { - //--- check - if(!CMath::IsFinite(x[i][j])) - return(false); - } - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| This function checks that all values from upper/lower triangle of| -//| X[0..N-1,0..N-1] are finite | -//+------------------------------------------------------------------+ -static bool CApServ::IsFiniteCTrMatrix(CMatrixComplex &x,const int n, - const bool isupper) - { -//--- create variables - int i=0; - int j1=0; - int j2=0; - int j=0; -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": internal error (N<0)")) - return(false); - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - for(j=j1; j<=j2; j++) - { - //--- check - if(!CMath::IsFinite(x[i][j].re) || !CMath::IsFinite(x[i][j].im)) - return(false); - } - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| This function checks that all values from X[0..M-1,0..N-1] are | -//| finite or NaN's. | -//+------------------------------------------------------------------+ -static bool CApServ::IsFiniteOrNaNMatrix(CMatrixDouble &x,const int m, - const int n) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": internal error (N<0)")) - return(false); -//--- check - if(!CAp::Assert(m>=0,__FUNCTION__+": internal error (M<0)")) - return(false); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=n-1;j++) - { - //--- check - if(!(CMath::IsFinite(x[i][j]) || CInfOrNaN::IsNaN(x[i][j]))) - return(false); - } - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Safe sqrt(x^2+y^2) | -//+------------------------------------------------------------------+ -static double CApServ::SafePythag2(const double x,const double y) - { -//--- create variables - double result=0; - double w=0; - double xabs=0; - double yabs=0; - double z=0; -//--- initialization - xabs=MathAbs(x); - yabs=MathAbs(y); - w=MathMax(xabs,yabs); - z=MathMin(xabs,yabs); -//--- check - if(z==0.0) - result=w; - else - result=w*MathSqrt(1+CMath::Sqr(z/w)); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Safe sqrt(x^2+y^2) | -//+------------------------------------------------------------------+ -static double CApServ::SafePythag3(double x,double y,double z) - { -//--- create a variable - double w=0; -//--- initialization - w=MathMax(MathAbs(x),MathMax(MathAbs(y),MathAbs(z))); -//--- check - if(w==0.0) - return(0); -//--- change values - x=x/w; - y=y/w; - z=z/w; -//--- return result - return(w*MathSqrt(CMath::Sqr(x)+CMath::Sqr(y)+CMath::Sqr(z))); - } -//+------------------------------------------------------------------+ -//| Safe division. | -//| This function attempts to calculate R=X/Y without overflow. | -//| It returns: | -//| * +1, if abs(X/Y)>=MaxRealNumber or undefined - overflow-like | -//| situation (no overlfow is generated, R is either NAN, | -//| PosINF, NegINF) | -//| * 0, if MinRealNumber0 | -//| (R contains result, may be zero) | -//| * -1, if 00 - if(y==0.0) - { - result=1; - //--- check - if(x==0.0) - r=CInfOrNaN::NaN(); - //--- check - if(x>0.0) - r=CInfOrNaN::PositiveInfinity(); - //--- check - if(x<0.0) - r=CInfOrNaN::NegativeInfinity(); - //--- return result - return(result); - } -//--- check - if(x==0.0) - { - r=0; - result=0; - //--- return result - return(result); - } -//--- make Y>0 - if(y<0.0) - { - x=-x; - y=-y; - } -//--- check - if(y>=1.0) - { - r=x/y; - //--- check - if(MathAbs(r)<=CMath::m_minrealnumber) - { - result=-1; - r=0; - } - else - result=0; - } - else - { - //--- check - if(MathAbs(x)>=CMath::m_maxrealnumber*y) - { - //--- check - if(x>0.0) - r=CInfOrNaN::PositiveInfinity(); - else - r=CInfOrNaN::NegativeInfinity(); - result=1; - } - else - { - r=x/y; - result=0; - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| This function calculates "safe" min(X/Y,V) for positive finite X,| -//| Y, V. No overflow is generated in any case. | -//+------------------------------------------------------------------+ -static double CApServ::SafeMinPosRV(const double x,const double y,const double v) - { -//--- create variables - double result=0; - double r=0; -//--- check - if(y>=1.0) - { - //--- Y>=1, we can safely divide by Y - r=x/y; - result=v; - //--- check - if(v>r) - result=r; - else - result=v; - } - else - { - //--- Y<1, we can safely multiply by Y - if(xB). It returns T which lies in [A,B] and | -//| integer K, such that X = T + K*(B-A). | -//| NOTES: | -//| * K is represented as real value, although actually it is integer| -//| * T is guaranteed to be in [A,B] | -//| * T replaces X | -//+------------------------------------------------------------------+ -static void CApServ::ApPeriodicMap(double &x,const double a,const double b, - double &k) - { -//--- initialization - k=0; -//--- check - if(!CAp::Assert(ab) - { - x=x-(b-a); - k=k+1; - } -//--- change values - x=MathMax(x,a); - x=MathMin(x,b); - } -//+------------------------------------------------------------------+ -//| 'bounds' value: maps X to [B1,B2] | -//+------------------------------------------------------------------+ -static double CApServ::BoundVal(const double x,const double b1,const double b2) - { -//--- check - if(x<=b1) - return(b1); -//--- check - if(x>=b2) - return(b2); -//--- return result - return(x); - } -//+------------------------------------------------------------------+ -//| Allocation of serializer: complex value | -//+------------------------------------------------------------------+ -static void CApServ::AllocComplex(CSerializer &s,al_complex &v) - { -//--- entry - s.Alloc_Entry(); - s.Alloc_Entry(); - } -//+------------------------------------------------------------------+ -//| Serialization: complex value | -//+------------------------------------------------------------------+ -static void CApServ::SerializeComplex(CSerializer &s,al_complex &v) - { -//--- serialization - s.Serialize_Double(v.re); - s.Serialize_Double(v.im); - } -//+------------------------------------------------------------------+ -//| Unserialization: complex value | -//+------------------------------------------------------------------+ -static al_complex CApServ::UnserializeComplex(CSerializer &s) - { -//--- create a variable - al_complex result; -//--- unserialization - result.re=s.Unserialize_Double(); - result.im=s.Unserialize_Double(); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Allocation of serializer: real array | -//+------------------------------------------------------------------+ -static void CApServ::AllocRealArray(CSerializer &s,double &v[],int n) - { -//--- create a variable - int i=0; -//--- check - if(n<0) - n=CAp::Len(v); -//--- entry - s.Alloc_Entry(); - for(i=0;i<=n-1;i++) - s.Alloc_Entry(); - } -//+------------------------------------------------------------------+ -//| Serialization: real array | -//+------------------------------------------------------------------+ -static void CApServ::SerializeRealArray(CSerializer &s,double &v[],int n) - { -//--- create a variable - int i=0; -//--- check - if(n<0) - n=CAp::Len(v); -//--- serialization - s.Serialize_Int(n); - for(i=0;i<=n-1;i++) - s.Serialize_Double(v[i]); - } -//+------------------------------------------------------------------+ -//| Unserialization: real array | -//+------------------------------------------------------------------+ -static void CApServ::UnserializeRealArray(CSerializer &s,double &v[]) - { -//--- create variables - int n=0; - int i=0; - double t=0; -//--- unserialization - n=s.Unserialize_Int(); -//--- check - if(n==0) - return; -//--- allocation - ArrayResizeAL(v,n); -//--- unserialization - for(i=0;i<=n-1;i++) - { - t=s.Unserialize_Double(); - v[i]=t; - } - } -//+------------------------------------------------------------------+ -//| Allocation of serializer: Integer array | -//+------------------------------------------------------------------+ -static void CApServ::AllocIntegerArray(CSerializer &s,int &v[],int n) - { -//--- create a variable - int i=0; -//--- check - if(n<0) - n=CAp::Len(v); -//--- entry - s.Alloc_Entry(); - for(i=0;i<=n-1;i++) - s.Alloc_Entry(); - } -//+------------------------------------------------------------------+ -//| Serialization: Integer array | -//+------------------------------------------------------------------+ -static void CApServ::SerializeIntegerArray(CSerializer &s,int &v[],int n) - { -//--- create a variable - int i=0; -//--- check - if(n<0) - n=CAp::Len(v); -//--- serialization - s.Serialize_Int(n); - for(i=0;i<=n-1;i++) - s.Serialize_Int(v[i]); - } -//+------------------------------------------------------------------+ -//| Unserialization: Integer array | -//+------------------------------------------------------------------+ -static void CApServ::UnserializeIntegerArray(CSerializer &s,int &v[]) - { -//--- create variables - int n=0; - int i=0; - int t=0; -//--- unserialization - n=s.Unserialize_Int(); -//--- check - if(n==0) - return; -//--- allocation - ArrayResizeAL(v,n); - for(i=0;i<=n-1;i++) - { - t=s.Unserialize_Int(); - v[i]=t; - } - } -//+------------------------------------------------------------------+ -//| Allocation of serializer: real matrix | -//+------------------------------------------------------------------+ -static void CApServ::AllocRealMatrix(CSerializer &s,CMatrixDouble &v,int n0,int n1) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(n0<0) - n0=CAp::Rows(v); -//--- check - if(n1<0) - n1=CAp::Cols(v); -//--- entry - s.Alloc_Entry(); - s.Alloc_Entry(); - for(i=0;i<=n0-1;i++) - { - for(j=0;j<=n1-1;j++) - s.Alloc_Entry(); - } - } -//+------------------------------------------------------------------+ -//| Serialization: real matrix | -//+------------------------------------------------------------------+ -static void CApServ::SerializeRealMatrix(CSerializer &s,CMatrixDouble &v,int n0,int n1) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(n0<0) - n0=CAp::Rows(v); -//--- check - if(n1<0) - n1=CAp::Cols(v); -//--- serialization - s.Serialize_Int(n0); -//--- serialization - s.Serialize_Int(n1); - for(i=0;i<=n0-1;i++) - for(j=0;j<=n1-1;j++) - s.Serialize_Double(v[i][j]); - } -//+------------------------------------------------------------------+ -//| Unserialization: real matrix | -//+------------------------------------------------------------------+ -static void CApServ::UnserializeRealMatrix(CSerializer &s,CMatrixDouble &v) - { -//--- create variables - int i=0; - int j=0; - int n0=0; - int n1=0; - double t=0; -//--- unserialization - n0=s.Unserialize_Int(); - n1=s.Unserialize_Int(); -//--- check - if(n0==0 || n1==0) - return; -//--- resize - v.Resize(n0,n1); -//--- unserialization - for(i=0;i<=n0-1;i++) - for(j=0;j<=n1-1;j++) - { - t=s.Unserialize_Double(); - v[i].Set(j,t); - } - } -//+------------------------------------------------------------------+ -//| Copy integer array | -//+------------------------------------------------------------------+ -static void CApServ::CopyIntegerArray(int &src[],int &dst[]) - { - int i=0; -//--- check - if(CAp::Len(src)>0) - { - //--- allocation - ArrayResizeAL(dst,CAp::Len(src)); - //--- copy - for(i=0;i<=CAp::Len(src)-1;i++) - dst[i]=src[i]; - } - } -//+------------------------------------------------------------------+ -//| Copy real array | -//+------------------------------------------------------------------+ -static void CApServ::CopyRealArray(double &src[],double &dst[]) - { - int i=0; -//--- check - if(CAp::Len(src)>0) - { - ArrayResizeAL(dst,CAp::Len(src)); - for(i=0;i<=CAp::Len(src)-1;i++) - dst[i]=src[i]; - } - } -//+------------------------------------------------------------------+ -//| Copy real matrix | -//+------------------------------------------------------------------+ -static void CApServ::CopyRealMatrix(CMatrixDouble &src,CMatrixDouble &dst) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(CAp::Rows(src)>0 && CAp::Cols(src)>0) - { - dst.Resize(CAp::Rows(src),CAp::Cols(src)); - //--- copy - for(i=0;i<=CAp::Rows(src)-1;i++) - for(j=0;j<=CAp::Cols(src)-1;j++) - dst[i].Set(j,src[i][j]); - } - } -//+------------------------------------------------------------------+ -//| This function searches integer array. Elements in this array are | -//| actually records, each NRec elements wide. Each record has unique| -//| header - NHeader integer values, which identify it. Records are | -//| lexicographically sorted by header. | -//| Records are identified by their index, not offset | -//| (offset = NRec*index). | -//| This function searches A (records with indices [I0,I1)) for a | -//| record with header B. It returns index of this record | -//| (not offset!), or -1 on failure. | -//+------------------------------------------------------------------+ -static int CApServ::RecSearch(int &a[],const int nrec,const int nheader,int i0,int i1,int &b[]) - { -//--- create variables - int mididx=0; - int cflag=0; - int k=0; - int offs=0; -//--- cycle - while(true) - { - //--- check - if(i0>=i1) - break; - //--- change values - mididx=(i0+i1)/2; - offs=nrec*mididx; - cflag=0; - for(k=0;k<=nheader-1;k++) - { - //--- check - if(a[offs+k]b[k]) - { - cflag=1; - break; - } - } - //--- check - if(cflag==0) - { - return(mididx); - } - //--- check - if(cflag<0) - i0=mididx+1; - else - i1=mididx; - } -//--- return result - return(-1); - } -//+------------------------------------------------------------------+ -//| Tag Sort | -//+------------------------------------------------------------------+ -class CTSort - { -private: - //--- private methods - static void TagSortFastIRec(double &a[],int &b[],double &bufa[],int &bufb[],const int i1,const int i2); - static void TagSortFastRRec(double &a[],double &b[],double &bufa[],double &bufb[],const int i1,const int i2); - static void TagSortFastRec(double &a[],double &bufa[],const int i1,const int i2); -public: - CTSort(void); - ~CTSort(void); - //--- public methods - static void TagSort(double &a[],const int n,int &p1[],int &p2[]); - static void TagSortBuf(double &a[],const int n,int &p1[],int &p2[],CApBuff &buf); - static void TagSortFastI(double &a[],int &b[],double &bufa[],int &bufb[],const int n); - static void TagSortFastR(double &a[],double &b[],double &bufa[],double &bufb[],const int n); - static void TagSortFast(double &a[],double &bufa[],const int n); - static void TagHeapPushI(double &a[],int &b[],int &n,const double va,const int vb); - static void TagHeapReplaceTopI(double &a[],int &b[],const int n,const double va,const int vb); - static void TagHeapPopI(double &a[],int &b[],int &n); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CTSort::CTSort(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTSort::~CTSort(void) - { - - } -//+------------------------------------------------------------------+ -//| This function sorts array of real keys by ascending. | -//| Its results are: | -//| * sorted array A | -//| * permutation tables P1, P2 | -//| Algorithm outputs permutation tables using two formats: | -//| * as usual permutation of [0..N-1]. If P1[i]=j, then sorted A[i] | -//| contains value which was moved there from J-th position. | -//| * as a sequence of pairwise permutations. Sorted A[] may be | -//| obtained byswaping A[i] and A[P2[i]] for all i from 0 to N-1. | -//| INPUT PARAMETERS: | -//| A - unsorted array | -//| N - array size | -//| OUPUT PARAMETERS: | -//| A - sorted array | -//| P1, P2 - permutation tables, array[N] | -//| NOTES: | -//| this function assumes that A[] is finite; it doesn't checks | -//| that condition. All other conditions (size of input arrays, | -//| etc.) are not checked too. | -//+------------------------------------------------------------------+ -static void CTSort::TagSort(double &a[],const int n,int &p1[],int &p2[]) - { -//--- create a variable - CApBuff buf; -//--- function call - TagSortBuf(a,n,p1,p2,buf); - } -//+------------------------------------------------------------------+ -//| Buffered variant of TagSort, which accepts preallocated output | -//| arrays as well as special structure for buffered allocations. If | -//| arrays are too short, they are reallocated. If they are large | -//| enough, no memoryallocation is done. | -//| It is intended to be used in the performance-critical parts of | -//| code, where additional allocations can lead to severe performance| -//| degradation | -//+------------------------------------------------------------------+ -static void CTSort::TagSortBuf(double &a[],const int n,int &p1[],int &p2[], - CApBuff &buf) - { -//--- create variables - int i=0; - int lv=0; - int lp=0; - int rv=0; - int rp=0; -//--- Special cases - if(n<=0) - return; -//--- check - if(n==1) - { - //--- function call - CApServ::IVectorSetLengthAtLeast(p1,1); - //--- function call - CApServ::IVectorSetLengthAtLeast(p2,1); - p1[0]=0; - p2[0]=0; - //--- exit the function - return; - } -//--- General case, N>1: prepare permutations table P1 - CApServ::IVectorSetLengthAtLeast(p1,n); - for(i=0;i<=n-1;i++) - p1[i]=i; -//--- General case, N>1: sort, update P1 - CApServ::RVectorSetLengthAtLeast(buf.m_ra0,n); -//--- function call - CApServ::IVectorSetLengthAtLeast(buf.m_ia0,n); - TagSortFastI(a,p1,buf.m_ra0,buf.m_ia0,n); -//--- General case, N>1: fill permutations table P2 -//--- To fill P2 we maintain two arrays: -//--- * PV (Buf.IA0), Position(Value). PV[i] contains position of I-th key at the moment -//--- * VP (Buf.IA1), Value(Position). VP[i] contains key which has position I at the moment -//--- At each step we making permutation of two items: -//--- Left,which is given by position/value pair LP/LV -//--- and Right,which is given by RP/RV -//--- and updating PV[] and VP[] correspondingly. - CApServ::IVectorSetLengthAtLeast(buf.m_ia0,n); -//--- function call - CApServ::IVectorSetLengthAtLeast(buf.m_ia1,n); -//--- function call - CApServ::IVectorSetLengthAtLeast(p2,n); - for(i=0;i<=n-1;i++) - { - buf.m_ia0[i]=i; - buf.m_ia1[i]=i; - } - for(i=0;i<=n-1;i++) - { - //--- calculate LP, LV, RP, RV - lp=i; - lv=buf.m_ia1[lp]; - rv=p1[i]; - rp=buf.m_ia0[rv]; - //--- Fill P2 - p2[i]=rp; - //--- update PV and VP - buf.m_ia1[lp]=rv; - buf.m_ia1[rp]=lv; - buf.m_ia0[lv]=rp; - buf.m_ia0[rv]=lp; - } - } -//+------------------------------------------------------------------+ -//| Same as TagSort, but optimized for real keys and integer labels. | -//| A is sorted, and same permutations are applied to B. | -//| NOTES: | -//| 1. this function assumes that A[] is finite; it doesn't checks | -//| that condition. All other conditions (size of input arrays, | -//| etc.) are not checked too. | -//| 2. this function uses two buffers, BufA and BufB, each is N | -//| elements large. They may be preallocated (which will save | -//| some time) or not, in which case function will automatically | -//| allocate memory. | -//+------------------------------------------------------------------+ -static void CTSort::TagSortFastI(double &a[],int &b[],double &bufa[], - int &bufb[],const int n) - { -//--- create variables - int i=0; - int j=0; - bool isascending; - bool isdescending; - double tmpr=0; - int tmpi=0; -//--- Special case - if(n<=1) - return; -//--- Test for already sorted set - isascending=true; - isdescending=true; - for(i=1;i<=n-1;i++) - { - isascending=isascending && a[i]>=a[i-1]; - isdescending=isdescending && a[i]<=a[i-1]; - } -//--- check - if(isascending) - return; -//--- check - if(isdescending) - { - for(i=0;i<=n-1;i++) - { - j=n-1-i; - //--- check - if(j<=i) - break; - //--- swap - tmpr=a[i]; - a[i]=a[j]; - a[j]=tmpr; - tmpi=b[i]; - b[i]=b[j]; - b[j]=tmpi; - } - //--- exit the function - return; - } -//--- General case - if(CAp::Len(bufa)=a[i-1]; - isdescending=isdescending && a[i]<=a[i-1]; - } -//--- check - if(isascending) - return; -//--- check - if(isdescending) - { - for(i=0;i<=n-1;i++) - { - j=n-1-i; - //--- check - if(j<=i) - break; - //--- swap - tmpr=a[i]; - a[i]=a[j]; - a[j]=tmpr; - tmpr=b[i]; - b[i]=b[j]; - b[j]=tmpr; - } - //--- exit the function - return; - } -//--- General case - if(CAp::Len(bufa)=a[i-1]; - isDesCending=isDesCending && a[i]<=a[i-1]; - } -//--- check - if(isAsCending) - return; -//--- check - if(isDesCending) - { - for(i=0;i0) - { - k=(j-1)/2; - v=a[k]; - //--- check - if(v=n) - { - //--- only one child. - //--- swap and terminate (because this child - //--- have no siblings due to heap structure) - v=a[k1]; - //--- check - if(v>va) - { - a[j]=v; - b[j]=b[k1]; - j=k1; - } - break; - } - else - { - //--- two childs - v1=a[k1]; - v2=a[k2]; - //--- check - if(v1>v2) - { - //--- check - if(va=1 | -//| On output top element is moved to A[N-1], B[N-1], heap is | -//| reordered, N is decreased by 1. | -//+------------------------------------------------------------------+ -static void CTSort::TagHeapPopI(double &a[],int &b[],int &n) - { -//--- create variables - double va=0; - int vb=0; -//--- check - if(n<1) - return; -//--- N=1 is a special case - if(n==1) - { - n=0; - return; - } -//--- swap top element and last element, -//--- then reorder heap - va=a[n-1]; - vb=b[n-1]; - a[n-1]=a[0]; - b[n-1]=b[0]; - n=n-1; -//--- function call - TagHeapReplaceTopI(a,b,n,va,vb); - } -//+------------------------------------------------------------------+ -//| Internal TagSortFastI: sorts A[I1...I2] (both bounds are | -//| included), applies same permutations to B. | -//+------------------------------------------------------------------+ -static void CTSort::TagSortFastIRec(double &a[],int &b[],double &bufa[], - int &bufb[],const int i1,const int i2) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int cntless=0; - int cnteq=0; - int cntgreater=0; - double tmpr=0; - int tmpi=0; - double v0=0; - double v1=0; - double v2=0; - double vp=0; -//--- Fast exit - if(i2<=i1) - return; -//--- Non-recursive sort for small arrays - if(i2-i1<=16) - { - for(j=i1+1;j<=i2;j++) - { - //--- Search elements [I1..J-1] for place to insert Jth element. - //--- This code stops immediately if we can leave A[J] at J-th position - //--- (all elements have same value of A[J] larger than any of them) - tmpr=a[j]; - tmpi=j; - for(k=j-1;k>=i1;k--) - { - //--- check - if(a[k]<=tmpr) - break; - tmpi=k; - } - k=tmpi; - //--- Insert Jth element into Kth position - if(k!=j) - { - //--- change values - tmpr=a[j]; - tmpi=b[j]; - for(i=j-1;i>=k;i--) - { - a[i+1]=a[i]; - b[i+1]=b[i]; - } - a[k]=tmpr; - b[k]=tmpi; - } - } - //--- exit the function - return; - } -//--- Quicksort: choose pivot -//--- Here we assume that I2-I1>=2 - v0=a[i1]; - v1=a[i1+(i2-i1)/2]; - v2=a[i2]; -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } -//--- check - if(v1>v2) - { - tmpr=v2; - v2=v1; - v1=tmpr; - } -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } - vp=v1; -//--- now pass through A/B and: -//--- * move elements that are LESS than VP to the left of A/B -//--- * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) -//--- * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order -//--- * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) -//--- * move elements from the left of BufA/BufB to the end of A/B - cntless=0; - cnteq=0; - cntgreater=0; - for(i=i1;i<=i2;i++) - { - v0=a[i]; - //--- check - if(v0=i1;k--) - { - //--- check - if(a[k]<=tmpr) - break; - tmpi=k; - } - k=tmpi; - //--- Insert Jth element into Kth position - if(k!=j) - { - //--- change values - tmpr=a[j]; - tmpr2=b[j]; - for(i=j-1;i>=k;i--) - { - a[i+1]=a[i]; - b[i+1]=b[i]; - } - a[k]=tmpr; - b[k]=tmpr2; - } - } - //--- exit the function - return; - } -//--- Quicksort: choose pivot -//--- Here we assume that I2-I1>=16 - v0=a[i1]; - v1=a[i1+(i2-i1)/2]; - v2=a[i2]; -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } -//--- check - if(v1>v2) - { - tmpr=v2; - v2=v1; - v1=tmpr; - } -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } - vp=v1; -//--- now pass through A/B and: -//--- * move elements that are LESS than VP to the left of A/B -//--- * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) -//--- * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order -//--- * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) -//--- * move elements from the left of BufA/BufB to the end of A/B - cntless=0; - cnteq=0; - cntgreater=0; - for(i=i1;i<=i2;i++) - { - v0=a[i]; - //--- check - if(v0=i1;k--) - { - //--- check - if(a[k]<=tmpr) - break; - tmpi=k; - } - k=tmpi; - //--- Insert Jth element into Kth position - if(k!=j) - { - tmpr=a[j]; - for(i=j-1;i>=k;i--) - a[i+1]=a[i]; - a[k]=tmpr; - } - } - return; - } -//--- Quicksort: choose pivot -//--- Here we assume that I2-I1>=16 - v0=a[i1]; - v1=a[i1+(i2-i1)/2]; - v2=a[i2]; -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } -//--- check - if(v1>v2) - { - tmpr=v2; - v2=v1; - v1=tmpr; - } -//--- check - if(v0>v1) - { - tmpr=v1; - v1=v0; - v0=tmpr; - } - vp=v1; -//--- now pass through A/B and: -//--- * move elements that are LESS than VP to the left of A/B -//--- * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) -//--- * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order -//--- * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) -//--- * move elements from the left of BufA/BufB to the end of A/B - cntLess=0; - cntEq=0; - cntGreat=0; - for(i=i1;i<=i2;i++) - { - v0=a[i]; - //--- check - if(v0=buf.m_ra1[t-1]) - t=1; - else - { - //--- swap - tmp=buf.m_ra1[k-1]; - buf.m_ra1[k-1]=buf.m_ra1[t-1]; - buf.m_ra1[t-1]=tmp; - tmpi=buf.m_ia1[k-1]; - buf.m_ia1[k-1]=buf.m_ia1[t-1]; - buf.m_ia1[t-1]=tmpi; - //--- set value - t=k; - } - } - //--- next iteration - i=i+1; - } - while(i<=n); - //--- set value - i=n-1; - //--- cycle - do - { - //--- swap - tmp=buf.m_ra1[i]; - buf.m_ra1[i]=buf.m_ra1[0]; - buf.m_ra1[0]=tmp; - tmpi=buf.m_ia1[i]; - buf.m_ia1[i]=buf.m_ia1[0]; - buf.m_ia1[0]=tmpi; - //--- set value - t=1; - while(t!=0) - { - k=2*t; - if(k>i) - t=0; - else - { - //--- check - if(kbuf.m_ra1[k-1]) - k++; - //--- check - if(buf.m_ra1[t-1]>=buf.m_ra1[k-1]) - t=0; - else - { - //--- swap - tmp=buf.m_ra1[k-1]; - buf.m_ra1[k-1]=buf.m_ra1[t-1]; - buf.m_ra1[t-1]=tmp; - tmpi=buf.m_ia1[k-1]; - buf.m_ia1[k-1]=buf.m_ia1[t-1]; - buf.m_ia1[t-1]=tmpi; - //--- set value - t=k; - } - } - } - i=i-1; - } - while(i>=1); - } -//--- compute tied ranks - i=0; - while(iMathAbs(x[result])) - result=i; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static int CBlas::ColumnIdxAbsMax(CMatrixDouble &x,const int i1,const int i2,const int j) - { -//--- create variables - int result=i1; - int i=0; - double a=0; -//--- calculation - a=MathAbs(x[result][j]); - for(i=i1+1;i<=i2;i++) - { - //--- check - if(MathAbs(x[i][j])>MathAbs(x[result][j])) - result=i; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static int CBlas::RowIdxAbsMax(CMatrixDouble &x,const int j1,const int j2,const int i) - { -//--- create variables - int result=j1; - int j=0; - double a=0; -//--- calculation - a=MathAbs(x[i][result]); - for(j=j1+1;j<=j2;j++) - { - //--- check - if(MathAbs(x[i][j])>MathAbs(x[i][result])) - result=j; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Upper Hessenberg norm | -//+------------------------------------------------------------------+ -static double CBlas::UpperHessenberg1Norm(CMatrixDouble &a,const int i1, - const int i2,const int j1, - const int j2,double &work[]) - { -//--- create variables - double result=0; - int i=0; - int j=0; -//--- check - if(!CAp::Assert(i2-i1==j2-j1,__FUNCTION__+": I2-I1!=J2-J1!")) - return(EMPTY_VALUE); - for(j=j1;j<=j2;j++) - work[j]=0; - for(i=i1;i<=i2;i++) - { - for(j=MathMax(j1,j1+i-i1-1);j<=j2;j++) - work[j]=work[j]+MathAbs(a[i][j]); - } -//--- get result - result=0; - for(j=j1;j<=j2;j++) - result=MathMax(result,work[j]); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Copy matrix | -//+------------------------------------------------------------------+ -static void CBlas::CopyMatrix(CMatrixDouble &a,const int is1,const int is2, - const int js1,const int js2,CMatrixDouble &b, - const int id1,const int id2,const int jd1,const int jd2) - { -//--- create variables - int isrc=0; - int idst=0; - int i_=0; - int i1_=0; -//--- check - if(is1>is2 || js1>js2) - return; -//--- check - if(!CAp::Assert(is2-is1==id2-id1,__FUNCTION__+": different sizes!")) - return; -//--- check - if(!CAp::Assert(js2-js1==jd2-jd1,__FUNCTION__+": different sizes!")) - return; -//--- copy - for(isrc=is1;isrc<=is2;isrc++) - { - idst=isrc-is1+id1; - i1_=js1-jd1; - for(i_=jd1;i_<=jd2;i_++) - b[idst].Set(i_,a[isrc][i_+i1_]); - } - } -//+------------------------------------------------------------------+ -//| Matrix transpose | -//+------------------------------------------------------------------+ -static void CBlas::InplaceTranspose(CMatrixDouble &a,const int i1,const int i2, - const int j1,const int j2,double &work[]) - { -//--- create variables - int i=0; - int j=0; - int ips=0; - int jps=0; - int l=0; - int i_=0; - int i1_=0; -//--- check - if(i1>i2 || j1>j2) - return; -//--- check - if(!CAp::Assert(i1-i2==j1-j2,__FUNCTION__+": incorrect array size!")) - return; - for(i=i1;i<=i2-1;i++) - { - //--- change values - j=j1+i-i1; - ips=i+1; - jps=j1+ips-i1; - l=i2-i; - i1_=ips-1; - //--- transpose - for(i_=1;i_<=l;i_++) - work[i_]=a[i_+i1_][j]; - i1_=jps-ips; - for(i_=ips;i_<=i2;i_++) - a[i_].Set(j,a[i][i_+i1_]); - i1_=1-jps; - for(i_=jps;i_<=j2;i_++) - a[i].Set(i_,work[i_+i1_]); - } - } -//+------------------------------------------------------------------+ -//| Copy and transpose matrix | -//+------------------------------------------------------------------+ -static void CBlas::CopyAndTranspose(CMatrixDouble &a,const int is1,const int is2, - const int js1,const int js2,CMatrixDouble &b, - const int id1,const int id2,const int jd1,const int jd2) - { -//--- create variables - int isrc=0; - int jdst=0; - int i_=0; - int i1_=0; -//--- check - if(is1>is2 || js1>js2) - return; -//--- check - if(!CAp::Assert(is2-is1==jd2-jd1,__FUNCTION__+": different sizes!")) - return; -//--- check - if(!CAp::Assert(js2-js1==id2-id1,__FUNCTION__+": different sizes!")) - return; -//--- copy and transpose - for(isrc=is1;isrc<=is2;isrc++) - { - jdst=isrc-is1+jd1; - i1_=js1-id1; - for(i_=id1;i_<=id2;i_++) - b[i_].Set(jdst,a[isrc][i_+i1_]); - } - } -//+------------------------------------------------------------------+ -//| Matrix vector multiply | -//+------------------------------------------------------------------+ -static void CBlas::MatrixVectorMultiply(CMatrixDouble &a,const int i1,const int i2, - const int j1,const int j2,const bool trans, - double &x[],const int ix1,const int ix2, - const double alpha,double &y[],const int iy1, - const int iy2,const double beta) - { -//--- create variables - int i=0; - double v=0; - int i_=0; - int i1_=0; -//--- check - if(!trans) - { - //--- y := alpha*A*x + beta*y; - if(i1>i2 || j1>j2) - return; - //--- check - if(!CAp::Assert(j2-j1==ix2-ix1,__FUNCTION__+": A and X dont match!")) - return; - //--- check - if(!CAp::Assert(i2-i1==iy2-iy1,__FUNCTION__+": A and Y dont match!")) - return; - //--- beta*y - if(beta==0.0) - { - for(i=iy1;i<=iy2;i++) - y[i]=0; - } - else - { - for(i_=iy1;i_<=iy2;i_++) - y[i_]=beta*y[i_]; - } - //--- alpha*A*x - for(i=i1;i<=i2;i++) - { - i1_=ix1-j1; - v=0.0; - for(i_=j1;i_<=j2;i_++) - v+=a[i][i_]*x[i_+i1_]; - y[iy1+i-i1]=y[iy1+i-i1]+alpha*v; - } - } - else - { - //--- y := alpha*A'*x + beta*y; - if(i1>i2 || j1>j2) - return; - //--- check - if(!CAp::Assert(i2-i1==ix2-ix1,"MatrixVectorMultiply: A and X dont match!")) - return; - //--- check - if(!CAp::Assert(j2-j1==iy2-iy1,"MatrixVectorMultiply: A and Y dont match!")) - return; - //--- beta*y - if(beta==0.0) - { - for(i=iy1;i<=iy2;i++) - y[i]=0; - } - else - { - for(i_=iy1;i_<=iy2;i_++) - y[i_]=beta*y[i_]; - } - //--- alpha*A'*x - for(i=i1;i<=i2;i++) - { - v=alpha*x[ix1+i-i1]; - i1_=j1-iy1; - for(i_=iy1;i_<=iy2;i_++) - y[i_]=y[i_]+v*a[i][i_+i1_]; - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static double CBlas::PyThag2(double x,double y) - { -//--- create variables - double result=0; - double w=0; - double xabs=0; - double yabs=0; - double z=0; -//--- initialization - xabs=MathAbs(x); - yabs=MathAbs(y); - w=MathMax(xabs,yabs); - z=MathMin(xabs,yabs); -//--- check - if(z==0.0) - result=w; - else - result=w*MathSqrt(1+CMath::Sqr(z/w)); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Matrix matrix multiply | -//+------------------------------------------------------------------+ -static void CBlas::MatrixMatrixMultiply(CMatrixDouble &a,const int ai1,const int ai2, - const int aj1,const int aj2,const bool transa, - CMatrixDouble &b,const int bi1,const int bi2, - const int bj1,const int bj2,const bool transb, - const double alpha,CMatrixDouble &c,const int ci1, - const int ci2,const int cj1,const int cj2, - const double beta,double &work[]) - { -//--- create variables - int arows=0; - int acols=0; - int brows=0; - int bcols=0; - int crows=0; - int ccols=0; - int i=0; - int j=0; - int k=0; - int l=0; - int r=0; - double v=0; - int i_=0; - int i1_=0; -//--- Setup - if(!transa) - { - arows=ai2-ai1+1; - acols=aj2-aj1+1; - } - else - { - arows=aj2-aj1+1; - acols=ai2-ai1+1; - } -//--- check - if(!transb) - { - brows=bi2-bi1+1; - bcols=bj2-bj1+1; - } - else - { - brows=bj2-bj1+1; - bcols=bi2-bi1+1; - } -//--- check - if(!CAp::Assert(acols==brows,__FUNCTION__+": incorrect matrix sizes!")) - return; -//--- check - if(arows<=0 || acols<=0 || brows<=0 || bcols<=0) - return; - crows=arows; - ccols=bcols; -//--- Test WORK - i=MathMax(arows,acols); - i=MathMax(brows,i); - i=MathMax(i,bcols); - work[1]=0; - work[i]=0; -//--- Prepare C - if(beta==0.0) - { - for(i=ci1;i<=ci2;i++) - for(j=cj1;j<=cj2;j++) - c[i].Set(j,0); - } - else - { - for(i=ci1;i<=ci2;i++) - for(i_=cj1;i_<=cj2;i_++) - c[i].Set(i_,beta*c[i][i_]); - } -//--- A*B - if(!transa && !transb) - { - for(l=ai1;l<=ai2;l++) - { - for(r=bi1;r<=bi2;r++) - { - //--- change values - v=alpha*a[l][aj1+r-bi1]; - k=ci1+l-ai1; - i1_=bj1-cj1; - for(i_=cj1;i_<=cj2;i_++) - c[k].Set(i_,c[k][i_]+v*b[r][i_+i1_]); - } - } - //--- exit the function - return; - } -//--- A*B' - if(!transa && transb) - { - //--- check - if(arows*acols=CMath::m_maxrealnumber*CMath::m_machineepsilon) - { - //--- change parameters - s=CMath::m_maxrealnumber*CMath::m_machineepsilon; - v=1/s; - //--- change x - for(i_=1;i_<=n;i_++) - x[i_]=v*x[i_]; - mx=mx*v; - } - } - } -//--- XNORM = DNRM2( N-1, X, INCX ) - alpha=x[1]; - xnorm=0; -//--- check - if(mx!=0.0) - { - for(j=2;j<=n;j++) - xnorm=xnorm+CMath::Sqr(x[j]/mx); - xnorm=MathSqrt(xnorm)*mx; - } -//--- check - if(xnorm==0.0) - { - //--- H = I - tau=0; - x[1]=x[1]*s; - //--- exit the function - return; - } -//--- general case - mx=MathMax(MathAbs(alpha),MathAbs(xnorm)); - beta=-(mx*MathSqrt(CMath::Sqr(alpha/mx)+CMath::Sqr(xnorm/mx))); -//--- check - if(alpha<0.0) - beta=-beta; -//--- change parameters - tau=(beta-alpha)/beta; - v=1/(alpha-beta); -//--- change x - for(i_=2;i_<=n;i_++) - x[i_]=v*x[i_]; - x[1]=beta; -//--- Scale back outputs - x[1]=x[1]*s; - } -//+------------------------------------------------------------------+ -//| Application of an elementary reflection to a rectangular matrix | -//| of size MxN | -//| The algorithm pre-multiplies the matrix by an elementary | -//| reflection transformation which is given by column V and scalar | -//| Tau (see the description of the GenerateReflection procedure). | -//| Not the whole matrix but only a part of it is transformed (rows | -//| from M1 to M2, columns from N1 to N2). Only the elements of this | -//| submatrix are changed. | -//| Input parameters: | -//| C - matrix to be transformed. | -//| Tau - scalar defining the transformation. | -//| V - column defining the transformation. | -//| Array whose index ranges within [1..M2-M1+1]. | -//| M1, M2 - range of rows to be transformed. | -//| N1, N2 - range of columns to be transformed. | -//| WORK - working array whose indexes goes from N1 to N2. | -//| Output parameters: | -//| C - the result of multiplying the input matrix C by | -//| the transformation matrix which is given by Tau | -//| and V. If N1>N2 or M1>M2, C is not modified. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CReflections::ApplyReflectionFromTheLeft(CMatrixDouble &c,const double tau, - const double &v[],const int m1, - const int m2,const int n1, - const int n2,double &work[]) - { -//--- check - if(tau==0.0 || n1>n2 || m1>m2) - return; -//--- create variables - double t=0; - int i=0; - int vm=0; - int i_=0; -//--- w := C' * v - vm=m2-m1+1; - for(i=n1;i<=n2;i++) - work[i]=0; - for(i=m1;i<=m2;i++) - { - t=v[i+1-m1]; - //--- change array - for(i_=n1;i_<=n2;i_++) - work[i_]+=t*c[i][i_]; - } -//--- C := C - tau * v * w' - for(i=m1;i<=m2;i++) - { - t=v[i-m1+1]*tau; - for(i_=n1;i_<=n2;i_++) - c[i].Set(i_,c[i][i_]-t*work[i_]); - } - } -//+------------------------------------------------------------------+ -//| Application of an elementary reflection to a rectangular matrix | -//| of size MxN | -//| The algorithm post-multiplies the matrix by an elementary | -//| reflection transformation which is given by column V and scalar | -//| Tau (see the description of the GenerateReflection procedure). | -//| Not the whole matrix but only a part of it is transformed (rows | -//| from M1 to M2, columns from N1 to N2). Only the elements of this | -//| submatrix are changed. | -//| Input parameters: | -//| C - matrix to be transformed. | -//| Tau - scalar defining the transformation. | -//| V - column defining the transformation. | -//| Array whose index ranges within [1..N2-N1+1]. | -//| M1, M2 - range of rows to be transformed. | -//| N1, N2 - range of columns to be transformed. | -//| WORK - working array whose indexes goes from M1 to M2. | -//| Output parameters: | -//| C - the result of multiplying the input matrix C by | -//| the transformation matrix which is given by Tau | -//| and V. If N1>N2 or M1>M2, C is not modified. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CReflections::ApplyReflectionFromTheRight(CMatrixDouble &c,const double tau, - const double &v[],const int m1, - const int m2,const int n1, - const int n2,double &work[]) - { -//--- check - if(tau==0.0 || n1>n2 || m1>m2) - return; -//--- create variables - double t=0; - int i=0; - int vm=n2-n1+1; - int i_=0; - int i1_=0; -//--- change matrix - for(i=m1;i<=m2;i++) - { - i1_=1-n1; - t=0.0; - //--- calculation parameters - for(i_=n1;i_<=n2;i_++) - t+=c[i][i_]*v[i_+i1_]; - t=t*tau; - i1_=1-n1; - for(i_=n1;i_<=n2;i_++) - c[i].Set(i_,c[i][i_]-t*v[i_+i1_]); - } - } -//+------------------------------------------------------------------+ -//| Complex reflections | -//+------------------------------------------------------------------+ -class CComplexReflections - { -public: - //--- constructor, destructor - void CComplexReflections(void); - void ~CComplexReflections(void); - //--- methods - static void ComplexGenerateReflection(al_complex &x[],const int n,al_complex &tau); - static void ComplexApplyReflectionFromTheLeft(CMatrixComplex &c,al_complex &tau,al_complex &v[],const int m1,const int m2,const int n1,const int n2,al_complex &work[]); - static void ComplexApplyReflectionFromTheRight(CMatrixComplex &c,al_complex &tau,al_complex &v[],const int m1,const int m2,const int n1,const int n2,al_complex &work[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CComplexReflections::CComplexReflections(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CComplexReflections::~CComplexReflections(void) - { - - } -//+------------------------------------------------------------------+ -//| Generation of an elementary complex reflection transformation | -//| The subroutine generates elementary complex reflection H of | -//| order N, so that, for a given X, the following equality holds | -//| true: | -//| ( X(1) ) ( Beta ) | -//| H' * ( .. ) = ( 0 ), H'*H = I, Beta is a real number | -//| ( X(n) ) ( 0 ) | -//| where | -//| ( V(1) ) | -//| H = 1 - Tau * ( .. ) * ( conj(V(1)), ..., conj(V(n)) ) | -//| ( V(n) ) | -//| where the first component of vector V equals 1. | -//| Input parameters: | -//| X - vector. Array with elements [1..N]. | -//| N - reflection order. | -//| Output parameters: | -//| X - components from 2 to N are replaced by vector V. | -//| The first component is replaced with parameter Beta. | -//| Tau - scalar value Tau. | -//| This subroutine is the modification of CLARFG subroutines from | -//| the LAPACK library. It has similar functionality except for the | -//| fact that it doesn?t handle errors when intermediate results | -//| cause an overflow. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CComplexReflections::ComplexGenerateReflection(al_complex &x[], - const int n, - al_complex &tau) - { -//--- check - if(n<=0) - { - tau=0; - //--- exit the function - return; - } -//--- create variables - int j=0; - al_complex alpha=0; - double alphi=0; - double alphr=0; - double beta=0; - double xnorm=0; - double mx=0; - al_complex t=0; - double s=1; - al_complex v=0; - int i_=0; - al_complex One(1,0); -//--- Scale if needed (to avoid overflow/underflow during intermediate -//--- calculations). - for(j=1;j<=n;j++) - mx=MathMax(CMath::AbsComplex(x[j]),mx); -//--- check - if(mx!=0) - { - //--- check - if(mx<1) - { - s=MathSqrt(CMath::m_minrealnumber); - v=1/s; - //--- change x - for(i_=1;i_<=n;i_++) - x[i_]=v*x[i_]; - } - else - { - s=MathSqrt(CMath::m_maxrealnumber); - v=1/s; - //--- change x - for(i_=1;i_<=n;i_++) - x[i_]=v*x[i_]; - } - } -//--- calculate - alpha=x[1]; - mx=0; - for(j=2;j<=n;j++) - mx=MathMax(CMath::AbsComplex(x[j]),mx); - xnorm=0; -//--- check - if(mx!=0) - { - for(j=2;j<=n;j++) - { - t=x[j]/mx; - xnorm=xnorm+(t*CMath::Conj(t)).re; - } - xnorm=MathSqrt(xnorm)*mx; - } -//--- change parameters - alphr=alpha.re; - alphi=alpha.im; -//--- check - if((xnorm==0) && (alphi==0)) - { - tau=0; - x[1]=x[1]*s; - //--- exit the function - return; - } -//--- change parameters - mx=MathMax(MathAbs(alphr),MathAbs(alphi)); - mx=MathMax(mx,MathAbs(xnorm)); - beta=-(mx*MathSqrt(CMath::Sqr(alphr/mx)+CMath::Sqr(alphi/mx)+CMath::Sqr(xnorm/mx))); -//--- check - if(alphr<0) - beta=-beta; -//--- change parameters - tau.re=(beta-alphr)/beta; - tau.im=-(alphi/beta); - alpha=One/(alpha-beta); -//--- check - if(n>1) - { - //--- change x - for(i_=2;i_<=n;i_++) - x[i_]=alpha*x[i_]; - } - alpha=beta; - x[1]=alpha; -//--- Scale back - x[1]=x[1]*s; - } -//+------------------------------------------------------------------+ -//| Application of an elementary reflection to a rectangular matrix | -//| of size MxN | -//| The algorithm pre-multiplies the matrix by an elementary | -//| reflection transformation which is given by column V and | -//| scalar Tau (see the description of the GenerateReflection). Not | -//| the whole matrix but only a part of it is transformed (rows | -//| from M1 to M2, columns from N1 to N2). Only the elements of this | -//| submatrix are changed. | -//| Note: the matrix is multiplied by H, not by H'. If it is | -//| required to multiply the matrix by H', it is necessary to pass | -//| Conj(Tau) instead of Tau. | -//| Input parameters: | -//| C - matrix to be transformed. | -//| Tau - scalar defining transformation. | -//| V - column defining transformation. | -//| Array whose index ranges within [1..M2-M1+1] | -//| M1, M2 - range of rows to be transformed. | -//| N1, N2 - range of columns to be transformed. | -//| WORK - working array whose index goes from N1 to N2. | -//| Output parameters: | -//| C - the result of multiplying the input matrix C by | -//| the transformation matrix which is given by Tau | -//| and V. If N1>N2 or M1>M2, C is not modified. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CComplexReflections::ComplexApplyReflectionFromTheLeft(CMatrixComplex &c, - al_complex &tau, - al_complex &v[], - const int m1, - const int m2, - const int n1, - const int n2, - al_complex &work[]) - { - al_complex Zero(0,0); -//--- check - if(tau==Zero || n1>n2 || m1>m2) - return; -//--- create variables - al_complex t=0; - int i=0; - int vm=0; - int i_=0; -//--- w := C^T * conj(v) - vm=m2-m1+1; - for(i=n1;i<=n2;i++) - work[i]=0; - for(i=m1;i<=m2;i++) - { - t=CMath::Conj(v[i+1-m1]); - for(i_=n1;i_<=n2;i_++) - work[i_]=work[i_]+t*c[i][i_]; - } -//--- C := C - tau * v * w^T - for(i=m1;i<=m2;i++) - { - t=v[i-m1+1]*tau; - for(i_=n1;i_<=n2;i_++) - c[i].Set(i_,c[i][i_]-t*work[i_]); - } - } -//+------------------------------------------------------------------+ -//| Application of an elementary reflection to a rectangular matrix | -//| of size MxN | -//| The algorithm post-multiplies the matrix by an elementary | -//| reflection transformation which is given by column V and | -//| scalar Tau (see the description of the GenerateReflection). | -//| Not the whole matrix but only a part of it is transformed | -//| (rows from M1 to M2, columns from N1 to N2). Only the elements | -//| of this submatrix are changed. | -//| Input parameters: | -//| C - matrix to be transformed. | -//| Tau - scalar defining transformation. | -//| V - column defining transformation. | -//| Array whose index ranges within [1..N2-N1+1] | -//| M1, M2 - range of rows to be transformed. | -//| N1, N2 - range of columns to be transformed. | -//| WORK - working array whose index goes from M1 to M2. | -//| Output parameters: | -//| C - the result of multiplying the input matrix C by | -//| the transformation matrix which is given by Tau | -//| and V. If N1>N2 or M1>M2, C is not modified. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| September 30, 1994 | -//+------------------------------------------------------------------+ -static void CComplexReflections::ComplexApplyReflectionFromTheRight(CMatrixComplex &c, - al_complex &tau, - al_complex &v[], - const int m1, - const int m2, - const int n1, - const int n2, - al_complex &work[]) - { - al_complex Zero(0,0); -//--- check - if(tau==Zero || n1>n2 || m1>m2) - return; -//--- create variables - al_complex t=0; - int i=0; - int vm=0; - int i_=0; - int i1_=0; -//--- w := C * v - vm=n2-n1+1; - for(i=m1;i<=m2;i++) - { - i1_=1-n1; - t=0.0; - //--- change values - for(i_=n1;i_<=n2;i_++) - t+=c[i][i_]*v[i_+i1_]; - work[i]=t; - } -//--- C := C - w * conj(v^T) - for(i_=1;i_<=vm;i_++) - v[i_]=CMath::Conj(v[i_]); -//--- get result - for(i=m1;i<=m2;i++) - { - t=work[i]*tau; - i1_=1-n1; - for(i_=n1;i_<=n2;i_++) - c[i].Set(i_,c[i][i_]-t*v[i_+i1_]); - } - for(i_=1;i_<=vm;i_++) - v[i_]=CMath::Conj(v[i_]); - } -//+------------------------------------------------------------------+ -//| Work with the symmetric matrix | -//+------------------------------------------------------------------+ -class CSblas - { -public: - //--- constructor, destructor - CSblas(void); - ~CSblas(void); - //--- methods - static void SymmetricMatrixVectorMultiply(const CMatrixDouble &a,const bool isupper,const int i1,const int i2,const double &x[],const double alpha,double &y[]); - static void SymmetricRank2Update(CMatrixDouble &a,const bool isupper,const int i1,const int i2,const double &x[],const double &y[],double &t[],const double alpha); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSblas::CSblas(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSblas::~CSblas(void) - { - - } -//+------------------------------------------------------------------+ -//| Multiply | -//+------------------------------------------------------------------+ -static void CSblas::SymmetricMatrixVectorMultiply(const CMatrixDouble &a, - const bool isupper, - const int i1,const int i2, - const double &x[], - const double alpha, - double &y[]) - { -//--- create variables - int i=0; - int ba1=0; - int ba2=0; - int by1=0; - int by2=0; - int bx1=0; - int bx2=0; - int n=i2-i1+1; - double v=0; - int i_=0; - int i1_=0; -//--- check - if(n<=0) - return; -//--- Let A = L + D + U, where -//--- L is strictly lower triangular (main diagonal is zero) -//--- D is diagonal -//--- U is strictly upper triangular (main diagonal is zero) -//--- A*x = L*x + D*x + U*x -//--- Calculate D*x first - for(i=i1;i<=i2;i++) - y[i-i1+1]=a[i][i]*x[i-i1+1]; -//--- Add L*x + U*x - if(isupper) - { - for(i=i1;im2 || n1>n2) - return; -//--- Form P * A - if(isforward) - { - //--- check - if(n1!=n2) - { - //--- Common case: N1<>N2 - for(j=m1;jN2 - for(j=m2-1;j>=m1;j--) - { - ctemp=c[j-m1+1]; - stemp=s[j-m1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - jp1=j+1; - //--- prepare array - for(i_=n1;i_<=n2;i_++) - work[i_]=ctemp*a[jp1][i_]; - for(i_=n1;i_<=n2;i_++) - work[i_]=work[i_]-stemp*a[j][i_]; - for(i_=n1;i_<=n2;i_++) - a[j].Set(i_,ctemp*a[j][i_]); - //--- get result - for(i_=n1;i_<=n2;i_++) - a[j].Set(i_,a[j][i_]+stemp*a[jp1][i_]); - for(i_=n1;i_<=n2;i_++) - a[jp1].Set(i_,work[i_]); - } - } - } - else - { - //--- Special case: N1=N2 - for(j=m2-1;j>=m1;j--) - { - ctemp=c[j-m1+1]; - stemp=s[j-m1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - temp=a[j+1][n1]; - //--- get result - a[j+1].Set(n1,ctemp*temp-stemp*a[j][n1]); - a[j].Set(n1,stemp*temp+ctemp*a[j][n1]); - } - } - } - } - } -//+------------------------------------------------------------------+ -//| Application of a sequence of elementary rotations to a matrix | -//| The algorithm post-multiplies the matrix by a sequence of | -//| rotation transformations which is given by arrays C and S. | -//| Depending on the value of the IsForward parameter either 1 and 2,| -//| 3 and 4 and so on (if IsForward=true) rows are rotated, or the | -//| rows N and N-1, N-2 and N-3 and so on are rotated. | -//| Not the whole matrix but only a part of it is transformed (rows | -//| from M1 to M2, columns from N1 to N2). Only the elements of this | -//| submatrix are changed. | -//| Input parameters: | -//| IsForward - the sequence of the rotation application. | -//| M1,M2 - the range of rows to be transformed. | -//| N1, N2 - the range of columns to be transformed. | -//| C,S - transformation coefficients. | -//| Array whose index ranges within [1..N2-N1]. | -//| A - processed matrix. | -//| WORK - working array whose index ranges within | -//| [M1..M2]. | -//| Output parameters: | -//| A - transformed matrix. | -//| Utility subroutine. | -//+------------------------------------------------------------------+ -static void CRotations::ApplyRotationsFromTheRight(const bool isforward, - const int m1,const int m2, - const int n1,const int n2, - double &c[],double &s[], - CMatrixDouble &a, - double &work[]) - { -//--- create variables - int j=0; - int jp1=0; - double ctemp=0; - double stemp=0; - double temp=0; - int i_=0; -//--- Form A * P' - if(isforward) - { - //--- check - if(m1!=m2) - { - //--- Common case: M1<>M2 - for(j=n1;j<=n2-1;j++) - { - ctemp=c[j-n1+1]; - stemp=s[j-n1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - jp1=j+1; - //--- prepare array - for(i_=m1;i_<=m2;i_++) - work[i_]=ctemp*a[i_][jp1]; - for(i_=m1;i_<=m2;i_++) - work[i_]=work[i_]-stemp*a[i_][j]; - //--- get result - for(i_=m1;i_<=m2;i_++) - a[i_].Set(j,ctemp*a[i_][j]); - for(i_=m1;i_<=m2;i_++) - a[i_].Set(j,a[i_][j]+stemp*a[i_][jp1]); - for(i_=m1;i_<=m2;i_++) - a[i_].Set(jp1,work[i_]); - } - } - } - else - { - //--- Special case: M1=M2 - for(j=n1;j<=n2-1;j++) - { - ctemp=c[j-n1+1]; - stemp=s[j-n1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - temp=a[m1][j+1]; - //--- get result - a[m1].Set(j+1,ctemp*temp-stemp*a[m1][j]); - a[m1].Set(j,stemp*temp+ctemp*a[m1][j]); - } - } - } - } - else - { - //--- check - if(m1!=m2) - { - //--- Common case: M1<>M2 - for(j=n2-1;j>=n1;j--) - { - ctemp=c[j-n1+1]; - stemp=s[j-n1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - jp1=j+1; - //--- prepare array - for(i_=m1;i_<=m2;i_++) - work[i_]=ctemp*a[i_][jp1]; - for(i_=m1;i_<=m2;i_++) - work[i_]=work[i_]-stemp*a[i_][j]; - //--- get result - for(i_=m1;i_<=m2;i_++) - a[i_].Set(j,ctemp*a[i_][j]); - for(i_=m1;i_<=m2;i_++) - a[i_].Set(j,a[i_][j]+stemp*a[i_][jp1]); - for(i_=m1;i_<=m2;i_++) - a[i_].Set(jp1,work[i_]); - } - } - } - else - { - //--- Special case: M1=M2 - for(j=n2-1;j>=n1;j--) - { - ctemp=c[j-n1+1]; - stemp=s[j-n1+1]; - //--- check - if(ctemp!=1.0 || stemp!=0.0) - { - temp=a[m1][j+1]; - //--- get result - a[m1].Set(j+1,ctemp*temp-stemp*a[m1][j]); - a[m1].Set(j,stemp*temp+ctemp*a[m1][j]); - } - } - } - } - } -//+------------------------------------------------------------------+ -//| The subroutine generates the elementary rotation, so that: | -//| [ CS SN ] . [ F ] = [ R ] | -//| [ -SN CS ] [ G ] [ 0 ] | -//| CS**2 + SN**2 = 1 | -//+------------------------------------------------------------------+ -static void CRotations::GenerateRotation(const double f,const double g, - double &cs,double &sn,double &r) - { -//--- create variables - double f1=0; - double g1=0; -//--- check - if(g==0.0) - { - //--- get result - cs=1; - sn=0; - r=f; - } - else - { - //--- check - if(f==0.0) - { - //--- get result - cs=0; - sn=1; - r=g; - } - else - { - f1=f; - g1=g; - //--- check - if(MathAbs(f1)>MathAbs(g1)) - r=MathAbs(f1)*MathSqrt(1+CMath::Sqr(g1/f1)); - else - r=MathAbs(g1)*MathSqrt(1+CMath::Sqr(f1/g1)); - cs=f1/r; - sn=g1/r; - //--- check - if(MathAbs(f)>MathAbs(g) && cs<0.0) - { - //--- get result - cs=-cs; - sn=-sn; - r=-r; - } - } - } - } -//+------------------------------------------------------------------+ -//| Schur decomposition of Hessenberg matrix | -//+------------------------------------------------------------------+ -class CHsSchur - { -private: - //--- private methods - static void InternalAuxSchur(const bool wantt,const bool wantz,const int n,const int ilo,const int ihi,CMatrixDouble &h,double &wr[],double &wi[],const int iloz,const int ihiz,CMatrixDouble &z,double &work[],double &workv3[],double &workc1[],double &works1[],int &info); - static void Aux2x2Schur(double &a,double &b,double &c,double &d,double &rt1r,double &rt1i,double &rt2r,double &rt2i,double &cs,double &sn); - static double ExtSchurSign(const double a,const double b); - static int ExtSchurSignToone(const double b); -public: - //--- constructor, destructor - CHsSchur(void); - ~CHsSchur(void); - //--- public methods - static bool UpperHessenbergSchurDecomposition(CMatrixDouble &h,const int n,CMatrixDouble &s); - static void InternalSchurDecomposition(CMatrixDouble &h,const int n,const int tneeded,const int zneeded,double &wr[],double &wi[],CMatrixDouble &z,int &info); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CHsSchur::CHsSchur(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CHsSchur::~CHsSchur(void) - { - - } -//+------------------------------------------------------------------+ -//| Subroutine performing the Schur decomposition of a matrix in | -//| upper Hessenberg form using the QR algorithm with multiple | -//| shifts. | -//| The source matrix H is represented as S'*H*S = T, where H - | -//| matrix in upper Hessenberg form, S - orthogonal matrix (Schur | -//| vectors), T - upper quasi-triangular matrix (with blocks of sizes| -//| 1x1 and 2x2 on the main diagonal). | -//| Input parameters: | -//| H - matrix to be decomposed. | -//| Array whose indexes range within [1..N, 1..N]. | -//| N - size of H, N>=0. | -//| Output parameters: | -//| H ? contains the matrix T. | -//| Array whose indexes range within [1..N, 1..N]. | -//| All elements below the blocks on the main diagonal | -//| are equal to 0. | -//| S - contains Schur vectors. | -//| Array whose indexes range within [1..N, 1..N]. | -//| Note 1: | -//| The block structure of matrix T could be easily recognized: | -//| since all the elements below the blocks are zeros, the | -//| elements a[i+1,i] which are equal to 0 show the block border.| -//| Note 2: | -//| the algorithm performance depends on the value of the | -//| internal parameter NS of InternalSchurDecomposition | -//| subroutine which defines the number of shifts in the QR | -//| algorithm (analog of the block width in block matrix | -//| algorithms in linear algebra). If you require maximum | -//| performance on your machine, it is recommended to | -//| adjust thisparameter manually. | -//| Result: | -//| True, if the algorithm has converged and the parameters H and| -//| S contain the result. | -//| False, if the algorithm has not converged. | -//| Algorithm implemented on the basis of subroutine DHSEQR | -//| (LAPACK 3.0 library). | -//+------------------------------------------------------------------+ -static bool CHsSchur::UpperHessenbergSchurDecomposition(CMatrixDouble &h, - const int n, - CMatrixDouble &s) - { -//--- create variables - bool result; - int info=0; -//--- create arrays - double wi[]; - double wr[]; -//--- function call - InternalSchurDecomposition(h,n,1,2,wr,wi,s,info); - result=info==0; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CHsSchur::InternalSchurDecomposition(CMatrixDouble &h,const int n, - const int tneeded, - const int zneeded, - double &wr[],double &wi[], - CMatrixDouble &z,int &info) - { -//--- create variables - int i=0; - int i1=0; - int i2=0; - int ierr=0; - int ii=0; - int itemp=0; - int itn=0; - int its=0; - int j=0; - int k=0; - int l=0; - int maxb=0; - int nr=0; - int ns=0; - int nv=0; - double absw=0; - double ovfl=0; - double smlnum=0; - double tau=0; - double temp=0; - double tst1=0; - double ulp=0; - double unfl=0; - bool initz; - bool wantt; - bool wantz; - double cnst=0; - bool failflag; - int p1=0; - int p2=0; - double vt=0; - int i_=0; - int i1_=0; -//--- create arrays - double v[]; - double vv[]; - double work[]; - double workc1[]; - double works1[]; - double workv3[]; - double tmpwr[]; - double tmpwi[]; - CMatrixDouble s; -//--- initialization - info=0; -//--- Set the order of the multi-shift QR algorithm to be used. -//--- If you want to tune algorithm, change this values - ns=12; - maxb=50; -//--- Now 2 < NS <= MAXB < NH. - maxb=(int)MathMax(3,maxb); - ns=MathMin(maxb,ns); -//--- Initialize - cnst=1.5; -//--- allocation - ArrayResizeAL(work,(int)MathMax(n,1)+1); - s.Resize(ns+1,ns+1); - ArrayResizeAL(v,ns+2); - ArrayResizeAL(vv,ns+2); - ArrayResizeAL(wr,(int)MathMax(n,1)+1); - ArrayResizeAL(wi,(int)MathMax(n,1)+1); - ArrayResizeAL(workc1,2); - ArrayResizeAL(works1,2); - ArrayResizeAL(workv3,4); - ArrayResizeAL(tmpwr,(int)MathMax(n,1)+1); - ArrayResizeAL(tmpwi,(int)MathMax(n,1)+1); -//--- check - if(!CAp::Assert(n>=0,"InternalSchurDecomposition: incorrect N!")) - return; -//--- check - if(!CAp::Assert(tneeded==0 || tneeded==1,"InternalSchurDecomposition: incorrect TNeeded!")) - return; -//--- check - if(!CAp::Assert((zneeded==0 || zneeded==1) || zneeded==2,"InternalSchurDecomposition: incorrect ZNeeded!")) - return; -//--- initialization - wantt=tneeded==1; - initz=zneeded==2; - wantz=zneeded!=0; - info=0; -//--- Initialize Z, if necessary - if(initz) - { - z.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - for(j=1;j<=n;j++) - { - //--- check - if(i==j) - z[i].Set(j,1); - else - z[i].Set(j,0); - } - } - } -//--- Quick return if possible - if(n==0) - return; -//--- check - if(n==1) - { - wr[1]=h[1][1]; - wi[1]=0; - //--- exit the function - return; - } -//--- Set rows and columns 1 to N to zero below the first -//--- subdiagonal. - for(j=1;j<=n-2;j++) - for(i=j+2;i<=n;i++) - h[i].Set(j,0); -//--- Test if N is sufficiently small - if((ns<=2 || ns>n) || maxb>=n) - { - //--- Use the standard double-shift algorithm - InternalAuxSchur(wantt,wantz,n,1,n,h,wr,wi,1,n,z,work,workv3,workc1,works1,info); - //--- fill entries under diagonal blocks of T with zeros - if(wantt) - { - j=1; - while(j<=n) - { - //--- check - if(wi[j]==0.0) - { - for(i=j+1;i<=n;i++) - h[i].Set(j,0); - j=j+1; - } - else - { - for(i=j+2;i<=n;i++) - { - h[i].Set(j,0); - h[i].Set(j+1,0); - } - j=j+2; - } - } - } - //--- exit the function - return; - } -//--- change values - unfl=CMath::m_minrealnumber; - ovfl=1/unfl; - ulp=2*CMath::m_machineepsilon; - smlnum=unfl*(n/ulp); -//--- I1 and I2 are the indices of the first row and last column of H -//--- to which transformations must be applied. If eigenvalues only are -//--- being computed, I1 and I2 are set inside the main loop. - i1=1; - i2=n; -//--- ITN is the total number of multiple-shift QR iterations allowed. - itn=30*n; -//--- main block - i=n; - while(true) - { - l=1; - //--- check - if(i<1) - { - //--- fill entries under diagonal blocks of T with zeros - if(wantt) - { - j=1; - while(j<=n) - { - //--- check - if(wi[j]==0.0) - { - for(i=j+1;i<=n;i++) - h[i].Set(j,0); - j=j+1; - } - else - { - for(i=j+2;i<=n;i++) - { - h[i].Set(j,0); - h[i].Set(j+1,0); - } - j=j+2; - } - } - } - //--- Exit - return; - } - //--- Perform multiple-shift QR iterations on rows and columns ILO to I - //--- until a submatrix of order at most MAXB splits off at the bottom - //--- because a subdiagonal element has become negligible. - failflag=true; - for(its=0;its<=itn;its++) - { - //--- Look for a single small subdiagonal element. - for(k=i;k>=l+1;k--) - { - tst1=MathAbs(h[k-1][k-1])+MathAbs(h[k][k]); - //--- check - if(tst1==0.0) - tst1=CBlas::UpperHessenberg1Norm(h,l,i,l,i,work); - //--- check - if(MathAbs(h[k][k-1])<=MathMax(ulp*tst1,smlnum)) - break; - } - l=k; - //--- check - if(l>1) - //--- H(L,L-1) is negligible. - h[l].Set(l-1,0); - //--- Exit from loop if a submatrix of order <= MAXB has split off. - if(l>=i-maxb+1) - { - failflag=false; - break; - } - //--- Now the active submatrix is in rows and columns L to I. If - //--- eigenvalues only are being computed, only the active submatrix - //--- need be transformed. - if(its==20 || its==30) - { - //--- Exceptional shifts. - for(ii=i-ns+1;ii<=i;ii++) - { - wr[ii]=cnst*(MathAbs(h[ii][ii-1])+MathAbs(h[ii][ii])); - wi[ii]=0; - } - } - else - { - //--- Use eigenvalues of trailing submatrix of order NS as shifts. - CBlas::CopyMatrix(h,i-ns+1,i,i-ns+1,i,s,1,ns,1,ns); - //--- function call - InternalAuxSchur(false,false,ns,1,ns,s,tmpwr,tmpwi,1,ns,z,work,workv3,workc1,works1,ierr); - for(p1=1;p1<=ns;p1++) - { - wr[i-ns+p1]=tmpwr[p1]; - wi[i-ns+p1]=tmpwi[p1]; - } - //--- check - if(ierr>0) - { - //--- If DLAHQR failed to compute all NS eigenvalues, use the - //--- unconverged diagonal elements as the remaining shifts. - for(ii=1;ii<=ierr;ii++) - { - wr[i-ns+ii]=s[ii][ii]; - wi[i-ns+ii]=0; - } - } - } - //--- Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns)) - //--- where G is the Hessenberg submatrix H(L:I,L:I) and w is - //--- the vector of shifts (stored in WR and WI). The result is - //--- stored in the local array V. - v[1]=1; - for(ii=2;ii<=ns+1;ii++) - v[ii]=0; - nv=1; - for(j=i-ns+1;j<=i;j++) - { - //--- check - if(wi[j]>=0.0) - { - //--- check - if(wi[j]==0.0) - { - //--- real shift - p1=nv+1; - for(i_=1;i_<=p1;i_++) - vv[i_]=v[i_]; - //--- function call - CBlas::MatrixVectorMultiply(h,l,l+nv,l,l+nv-1,false,vv,1,nv,1.0,v,1,nv+1,-wr[j]); - nv=nv+1; - } - else - { - //--- check - if(wi[j]>0.0) - { - //--- complex conjugate pair of shifts - p1=nv+1; - for(i_=1;i_<=p1;i_++) - vv[i_]=v[i_]; - //--- function call - CBlas::MatrixVectorMultiply(h,l,l+nv,l,l+nv-1,false,v,1,nv,1.0,vv,1,nv+1,-(2*wr[j])); - //--- function call - itemp=CBlas::VectorIdxAbsMax(vv,1,nv+1); - temp=1/MathMax(MathAbs(vv[itemp]),smlnum); - p1=nv+1; - for(i_=1;i_<=p1;i_++) - vv[i_]=temp*vv[i_]; - //--- function call - absw=CBlas::PyThag2(wr[j],wi[j]); - temp=temp*absw*absw; - //--- function call - CBlas::MatrixVectorMultiply(h,l,l+nv+1,l,l+nv,false,vv,1,nv+1,1.0,v,1,nv+2,temp); - nv=nv+2; - } - } - //--- Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero, - //--- reset it to the unit vector. - itemp=CBlas::VectorIdxAbsMax(v,1,nv); - temp=MathAbs(v[itemp]); - //--- check - if(temp==0.0) - { - v[1]=1; - for(ii=2;ii<=nv;ii++) - v[ii]=0; - } - else - { - temp=MathMax(temp,smlnum); - vt=1/temp; - for(i_=1;i_<=nv;i_++) - v[i_]=vt*v[i_]; - } - } - } - //--- Multiple-shift QR step - for(k=l;k<=i-1;k++) - { - //--- The first iteration of this loop determines a reflection G - //--- from the vector V and applies it from left and right to H, - //--- thus creating a nonzero bulge below the subdiagonal. - //--- Each subsequent iteration determines a reflection G to - //--- restore the Hessenberg form in the (K-1)th column, and thus - //--- chases the bulge one step toward the bottom of the active - //--- submatrix. NR is the order of G. - nr=MathMin(ns+1,i-k+1); - //--- check - if(k>l) - { - //--- change values - p1=k-1; - p2=k+nr-1; - i1_=k-1; - for(i_=1;i_<=nr;i_++) - v[i_]=h[i_+i1_][p1]; - } - //--- function call - CReflections::GenerateReflection(v,nr,tau); - //--- check - if(k>l) - { - h[k].Set(k-1,v[1]); - for(ii=k+1;ii<=i;ii++) - h[ii].Set(k-1,0); - } - v[1]=1; - //--- Apply G from the left to transform the rows of the matrix in - //--- columns K to I2. - CReflections::ApplyReflectionFromTheLeft(h,tau,v,k,k+nr-1,k,i2,work); - //--- Apply G from the right to transform the columns of the - //--- matrix in rows I1 to min(K+NR,I). - CReflections::ApplyReflectionFromTheRight(h,tau,v,i1,MathMin(k+nr,i),k,k+nr-1,work); - //--- check - if(wantz) - //--- Accumulate transformations in the matrix Z - CReflections::ApplyReflectionFromTheRight(z,tau,v,1,n,k,k+nr-1,work); - } - } - //--- Failure to converge in remaining number of iterations - if(failflag) - { - info=i; - //--- exit the function - return; - } - //--- A submatrix of order <= MAXB in rows and columns L to I has split - //--- off. Use the double-shift QR algorithm to handle it. - InternalAuxSchur(wantt,wantz,n,l,i,h,wr,wi,1,n,z,work,workv3,workc1,works1,info); - //--- check - if(info>0) - return; - //--- Decrement number of remaining iterations, and return to start of - //--- the main loop with a new value of I. - itn=itn-its; - i=l-1; - } - } -//+------------------------------------------------------------------+ -//| The auxiliary function -//+------------------------------------------------------------------+ -static void CHsSchur::InternalAuxSchur(const bool wantt,const bool wantz, - const int n,const int ilo,const int ihi, - CMatrixDouble &h,double &wr[],double &wi[], - const int iloz,const int ihiz,CMatrixDouble &z, - double &work[],double &workv3[], - double &workc1[],double &works1[],int &info) - { -//--- create variables - int i=0; - int i1=0; - int i2=0; - int itn=0; - int its=0; - int j=0; - int k=0; - int l=0; - int m=0; - int nh=0; - int nr=0; - int nz=0; - double ave=0; - double cs=0; - double disc=0; - double h00=0; - double h10=0; - double h11=0; - double h12=0; - double h21=0; - double h22=0; - double h33=0; - double h33s=0; - double h43h34=0; - double h44=0; - double h44s=0; - double ovfl=0; - double s=0; - double smlnum=0; - double sn=0; - double sum=0; - double t1=0; - double t2=0; - double t3=0; - double tst1=0; - double unfl=0; - double v1=0; - double v2=0; - double v3=0; - bool failflag; - double dat1=0; - double dat2=0; - int p1=0; - double him1im1=0; - double him1i=0; - double hiim1=0; - double hii=0; - double wrim1=0; - double wri=0; - double wiim1=0; - double wii=0; - double ulp=0; -//--- initialization - info=0; - dat1=0.75; - dat2=-0.4375; - ulp=CMath::m_machineepsilon; -//--- Quick return if possible - if(n==0) - return; -//--- check - if(ilo==ihi) - { - wr[ilo]=h[ilo][ilo]; - wi[ilo]=0; - //--- exit the function - return; - } -//--- initialization - nh=ihi-ilo+1; - nz=ihiz-iloz+1; -//--- Set machine-dependent constants for the stopping criterion. -//--- If norm(H) <= sqrt(OVFL), overflow should not occur. - unfl=CMath::m_minrealnumber; - ovfl=1/unfl; - smlnum=unfl*(nh/ulp); -//--- I1 and I2 are the indices of the first row and last column of H -//--- to which transformations must be applied. If eigenvalues only are -//--- being computed, I1 and I2 are set inside the main loop. - i1=1; - i2=n; -//--- ITN is the total number of QR iterations allowed. - itn=30*nh; -//--- The main loop begins here. I is the loop index and decreases from -//--- IHI to ILO in steps of 1 or 2. Each iteration of the loop works -//--- with the active submatrix in rows and columns L to I. -//--- Eigenvalues I+1 to IHI have already converged. Either L = ILO or -//--- H(L,L-1) is negligible so that the matrix splits. - i=ihi; - while(true) - { - l=ilo; - //--- check - if(i=l+1;k--) - { - tst1=MathAbs(h[k-1][k-1])+MathAbs(h[k][k]); - //--- check - if(tst1==0.0) - tst1=CBlas::UpperHessenberg1Norm(h,l,i,l,i,work); - //--- check - if(MathAbs(h[k][k-1])<=MathMax(ulp*tst1,smlnum)) - break; - } - l=k; - //--- check - if(l>ilo) - //--- H(L,L-1) is negligible - h[l].Set(l-1,0); - //--- Exit from loop if a submatrix of order 1 or 2 has split off. - if(l>=i-1) - { - failflag=false; - break; - } - //--- Now the active submatrix is in rows and columns L to I. If - //--- eigenvalues only are being computed, only the active submatrix - //--- need be transformed. - if(its==10 || its==20) - { - //--- Exceptional shift. - s=MathAbs(h[i][i-1])+MathAbs(h[i-1][i-2]); - h44=dat1*s+h[i][i]; - h33=h44; - h43h34=dat2*s*s; - } - else - { - //--- Prepare to use Francis' double shift - //--- (i.e. 2nd degree generalized Rayleigh quotient) - h44=h[i][i]; - h33=h[i-1][i-1]; - h43h34=h[i][i-1]*h[i-1][i]; - s=h[i-1][i-2]*h[i-1][i-2]; - disc=(h33-h44)*0.5; - disc=disc*disc+h43h34; - //--- check - if(disc>0.0) - { - //--- Real roots: use Wilkinson's shift twice - disc=MathSqrt(disc); - ave=0.5*(h33+h44); - //--- check - if(MathAbs(h33)-MathAbs(h44)>0.0) - { - h33=h33*h44-h43h34; - h44=h33/(ExtSchurSign(disc,ave)+ave); - } - else - h44=ExtSchurSign(disc,ave)+ave; - h33=h44; - h43h34=0; - } - } - //--- Look for two consecutive small subdiagonal elements. - for(m=i-2;m>=l;m--) - { - //--- Determine the effect of starting the double-shift QR - //--- iteration at row M, and see if this would make H(M,M-1) - //--- negligible. - h11=h[m][m]; - h22=h[m+1][m+1]; - h21=h[m+1][m]; - h12=h[m][m+1]; - h44s=h44-h11; - h33s=h33-h11; - v1=(h33s*h44s-h43h34)/h21+h12; - v2=h22-h11-h33s-h44s; - v3=h[m+2][m+1]; - s=MathAbs(v1)+MathAbs(v2)+MathAbs(v3); - v1=v1/s; - v2=v2/s; - v3=v3/s; - workv3[1]=v1; - workv3[2]=v2; - workv3[3]=v3; - //--- check - if(m==l) - break; - h00=h[m-1][m-1]; - h10=h[m][m-1]; - tst1=MathAbs(v1)*(MathAbs(h00)+MathAbs(h11)+MathAbs(h22)); - //--- check - if(MathAbs(h10)*(MathAbs(v2)+MathAbs(v3))<=ulp*tst1) - break; - } - //--- Double-shift QR step - for(k=m;k<=i-1;k++) - { - //--- The first iteration of this loop determines a reflection G - //--- from the vector V and applies it from left and right to H, - //--- thus creating a nonzero bulge below the subdiagonal. - //--- Each subsequent iteration determines a reflection G to - //--- restore the Hessenberg form in the (K-1)th column, and thus - //--- chases the bulge one step toward the bottom of the active - //--- submatrix. NR is the order of G. - nr=(int)MathMin(3,i-k+1); - //--- check - if(k>m) - { - for(p1=1;p1<=nr;p1++) - workv3[p1]=h[k+p1-1][k-1]; - } - //--- function call - CReflections::GenerateReflection(workv3,nr,t1); - //--- check - if(k>m) - { - h[k].Set(k-1,workv3[1]); - h[k+1].Set(k-1,0); - //--- check - if(kl) - h[k].Set(k-1,-h[k][k-1]); - } - v2=workv3[2]; - t2=t1*v2; - //--- check - if(nr==3) - { - v3=workv3[3]; - t3=t1*v3; - //--- Apply G from the left to transform the rows of the matrix - //--- in columns K to I2. - for(j=k;j<=i2;j++) - { - sum=h[k][j]+v2*h[k+1][j]+v3*h[k+2][j]; - h[k].Set(j,h[k][j]-sum*t1); - h[k+1].Set(j,h[k+1][j]-sum*t2); - h[k+2].Set(j,h[k+2][j]-sum*t3); - } - //--- Apply G from the right to transform the columns of the - //--- matrix in rows I1 to min(K+3,I). - for(j=i1;j<=MathMin(k+3,i);j++) - { - sum=h[j][k]+v2*h[j][k+1]+v3*h[j][k+2]; - h[j].Set(k,h[j][k]-sum*t1); - h[j].Set(k+1,h[j][k+1]-sum*t2); - h[j].Set(k+2,h[j][k+2]-sum*t3); - } - //--- check - if(wantz) - { - //--- Accumulate transformations in the matrix Z - for(j=iloz;j<=ihiz;j++) - { - sum=z[j][k]+v2*z[j][k+1]+v3*z[j][k+2]; - z[j].Set(k,z[j][k]-sum*t1); - z[j].Set(k+1,z[j][k+1]-sum*t2); - z[j].Set(k+2,z[j][k+2]-sum*t3); - } - } - } - else - { - //--- check - if(nr==2) - { - //--- Apply G from the left to transform the rows of the matrix - //--- in columns K to I2. - for(j=k;j<=i2;j++) - { - sum=h[k][j]+v2*h[k+1][j]; - h[k].Set(j,h[k][j]-sum*t1); - h[k+1].Set(j,h[k+1][j]-sum*t2); - } - //--- Apply G from the right to transform the columns of the - //--- matrix in rows I1 to min(K+3,I). - for(j=i1;j<=i;j++) - { - sum=h[j][k]+v2*h[j][k+1]; - h[j].Set(k,h[j][k]-sum*t1); - h[j].Set(k+1,h[j][k+1]-sum*t2); - } - //--- check - if(wantz) - { - //--- Accumulate transformations in the matrix Z - for(j=iloz;j<=ihiz;j++) - { - sum=z[j][k]+v2*z[j][k+1]; - z[j].Set(k,z[j][k]-sum*t1); - z[j].Set(k+1,z[j][k+1]-sum*t2); - } - } - } - } - } - } - //--- check - if(failflag) - { - //--- Failure to converge in remaining number of iterations - info=i; - //--- exit the function - return; - } - //--- check - if(l==i) - { - //--- H(I,I-1) is negligible: one eigenvalue has converged. - wr[i]=h[i][i]; - wi[i]=0; - } - else - { - //--- check - if(l==i-1) - { - //--- H(I-1,I-2) is negligible: a pair of eigenvalues have converged. - //--- Transform the 2-by-2 submatrix to standard Schur form, - //--- and compute and store the eigenvalues. - him1im1=h[i-1][i-1]; - him1i=h[i-1][i]; - hiim1=h[i][i-1]; - hii=h[i][i]; - //--- function call - Aux2x2Schur(him1im1,him1i,hiim1,hii,wrim1,wiim1,wri,wii,cs,sn); - //--- change values - wr[i-1]=wrim1; - wi[i-1]=wiim1; - wr[i]=wri; - wi[i]=wii; - h[i-1].Set(i-1,him1im1); - h[i-1].Set(i,him1i); - h[i].Set(i-1,hiim1); - h[i].Set(i,hii); - //--- check - if(wantt) - { - //--- Apply the transformation to the rest of H. - if(i2>i) - { - workc1[1]=cs; - works1[1]=sn; - //--- function call - CRotations::ApplyRotationsFromTheLeft(true,i-1,i,i+1,i2,workc1,works1,h,work); - } - workc1[1]=cs; - works1[1]=sn; - //--- function call - CRotations::ApplyRotationsFromTheRight(true,i1,i-2,i-1,i,workc1,works1,h,work); - } - //--- check - if(wantz) - { - //--- Apply the transformation to Z. - workc1[1]=cs; - works1[1]=sn; - //--- function call - CRotations::ApplyRotationsFromTheRight(true,iloz,iloz+nz-1,i-1,i,workc1,works1,z,work); - } - } - } - //--- Decrement number of remaining iterations, and return to start of - //--- the main loop with new value of I. - itn=itn-its; - i=l-1; - } - } -//+------------------------------------------------------------------+ -//| 2x2 | -//+------------------------------------------------------------------+ -static void CHsSchur::Aux2x2Schur(double &a,double &b,double &c,double &d, - double &rt1r,double &rt1i,double &rt2r, - double &rt2i,double &cs,double &sn) - { -//--- create variables - double multpl=0; - double aa=0; - double bb=0; - double bcmax=0; - double bcmis=0; - double cc=0; - double cs1=0; - double dd=0; - double eps=0; - double p=0; - double sab=0; - double sac=0; - double scl=0; - double sigma=0; - double sn1=0; - double tau=0; - double temp=0; - double z=0; -//--- initialization - rt1r=0; - rt1i=0; - rt2r=0; - rt2i=0; - cs=0; - sn=0; - multpl=4.0; - eps=CMath::m_machineepsilon; -//--- check - if(c==0.0) - { - cs=1; - sn=0; - } - else - { - //--- check - if(b==0.0) - { - //--- Swap rows and columns - cs=0; - sn=1; - temp=d; - d=a; - a=temp; - b=-c; - c=0; - } - else - { - //--- check - if(a-d==0.0 && ExtSchurSignToone(b)!=ExtSchurSignToone(c)) - { - cs=1; - sn=0; - } - else - { - //--- change values - temp=a-d; - p=0.5*temp; - bcmax=MathMax(MathAbs(b),MathAbs(c)); - bcmis=MathMin(MathAbs(b),MathAbs(c))*ExtSchurSignToone(b)*ExtSchurSignToone(c); - scl=MathMax(MathAbs(p),bcmax); - z=p/scl*p+bcmax/scl*bcmis; - //--- If Z is of the order of the machine accuracy, postpone the - //--- decision on the nature of eigenvalues - if(z>=multpl*eps) - { - //--- Real eigenvalues. Compute A and D. - z=p+ExtSchurSign(MathSqrt(scl)*MathSqrt(z),p); - a=d+z; - d=d-bcmax/z*bcmis; - //--- Compute B and the rotation matrix - tau=CBlas::PyThag2(c,z); - cs=z/tau; - sn=c/tau; - b=b-c; - c=0; - } - else - { - //--- Complex eigenvalues, or real (almost) equal eigenvalues. - //--- Make diagonal elements equal. - sigma=b+c; - tau=CBlas::PyThag2(sigma,temp); - cs=MathSqrt(0.5*(1+MathAbs(sigma)/tau)); - sn=-(p/(tau*cs)*ExtSchurSign(1,sigma)); - //--- Compute [ AA BB ] = [ A B ] [ CS -SN ] - //--- [ CC DD ] [ C D ] [ SN CS ] - aa=a*cs+b*sn; - bb=-(a*sn)+b*cs; - cc=c*cs+d*sn; - dd=-(c*sn)+d*cs; - //--- Compute [ A B ] = [ CS SN ] [ AA BB ] - //--- [ C D ] [-SN CS ] [ CC DD ] - a=aa*cs+cc*sn; - b=bb*cs+dd*sn; - c=-(aa*sn)+cc*cs; - d=-(bb*sn)+dd*cs; - temp=0.5*(a+d); - a=temp; - d=temp; - //--- check - if(c!=0.0) - { - //--- check - if(b!=0.0) - { - //--- check - if(ExtSchurSignToone(b)==ExtSchurSignToone(c)) - { - //--- Real eigenvalues: reduce to upper triangular form - sab=MathSqrt(MathAbs(b)); - sac=MathSqrt(MathAbs(c)); - //--- function call - p=ExtSchurSign(sab*sac,c); - tau=1/MathSqrt(MathAbs(b+c)); - a=temp+p; - d=temp-p; - b=b-c; - c=0; - cs1=sab*tau; - sn1=sac*tau; - temp=cs*cs1-sn*sn1; - sn=cs*sn1+sn*cs1; - cs=temp; - } - } - else - { - //--- change values - b=-c; - c=0; - temp=cs; - cs=-sn; - sn=temp; - } - } - } - } - } - } -//--- Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I). - rt1r=a; - rt2r=d; -//--- check - if(c==0.0) - { - rt1i=0; - rt2i=0; - } - else - { - rt1i=MathSqrt(MathAbs(b))*MathSqrt(MathAbs(c)); - rt2i=-rt1i; - } - } -//+------------------------------------------------------------------+ -//| Schur sign | -//+------------------------------------------------------------------+ -static double CHsSchur::ExtSchurSign(const double a,const double b) - { -//--- create variables - double result=0; -//--- check - if(b>=0.0) - result=MathAbs(a); - else - result=-MathAbs(a); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Schur sign (1 or -1) | -//+------------------------------------------------------------------+ -static int CHsSchur::ExtSchurSignToone(const double b) - { -//--- create variables - int result=0; -//--- check - if(b>=0.0) - result=1; - else - result=-1; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Safe solutions for tridiagonal linear matrix | -//+------------------------------------------------------------------+ -class CTrLinSolve - { -public: - //--- constructor, destructor - CTrLinSolve(void); - ~CTrLinSolve(void); - //--- methods - static void RMatrixTrSafeSolve(CMatrixDouble &a,const int n,double &x[],double &s,const bool isupper,const bool istrans,const bool isunit); - static void SafeSolveTriangular(CMatrixDouble &a,const int n,double &x[],double &s,const bool isupper,const bool istrans,const bool isunit,const bool normin,double &cnorm[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CTrLinSolve::CTrLinSolve(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTrLinSolve::~CTrLinSolve(void) - { - - } -//+------------------------------------------------------------------+ -//| Utility subroutine performing the "safe" solution of system of | -//| linear equations with triangular coefficient matrices. | -//| The subroutine uses scaling and solves the scaled system A*x=s*b | -//| (where s is a scalar value) instead of A*x=b, choosing | -//| s so that x can be represented by a floating-point number. The | -//| closer the system gets to a singular, the less s is. If the | -//| system is singular, s=0 and x contains the non-trivial solution | -//| of equation A*x=0. | -//| The feature of an algorithm is that it could not cause an | -//| overflow or a division by zero regardless of the matrix used | -//| as the input. | -//| The algorithm can solve systems of equations with upper/lower | -//| triangular matrices, with/without unit diagonal, and systems of | -//| type A*x=b or A'*x=b (where A' is a transposed matrix A). | -//| Input parameters: | -//| A - system matrix. Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| X - right-hand member of a system. | -//| Array whose index ranges within [0..N-1]. | -//| IsUpper - matrix type. If it is True, the system matrix is | -//| the upper triangular and is located in the | -//| corresponding part of matrix A. | -//| Trans - problem type. If it is True, the problem to be | -//| solved is A'*x=b, otherwise it is A*x=b. | -//| Isunit - matrix type. If it is True, the system matrix has| -//| a unit diagonal (the elements on the main | -//| diagonal are not used in the calculation | -//| process), otherwise the matrix is considered to | -//| be a general triangular matrix. | -//| Output parameters: | -//| X - solution. Array whose index ranges within | -//| [0..N-1]. | -//| S - scaling factor. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| June 30, 1992 | -//+------------------------------------------------------------------+ -static void CTrLinSolve::RMatrixTrSafeSolve(CMatrixDouble &a,const int n, - double &x[],double &s, - const bool isupper, - const bool istrans, - const bool isunit) - { -//--- create variables - bool normin; - int i=0; - int i_=0; - int i1_=0; -//--- create arrays - double cnorm[]; - double x1[]; -//--- create matrix - CMatrixDouble a1; -//--- initialization - s=0; -//--- From 0-based to 1-based - normin=false; -//--- allocation - a1.Resize(n+1,n+1); - ArrayResizeAL(x1,n+1); - for(i=1;i<=n;i++) - { - i1_=-1; - for(i_=1;i_<=n;i_++) - a1[i].Set(i_,a[i-1][i_+i1_]); - } -//--- change values - i1_=-1; - for(i_=1;i_<=n;i_++) - x1[i_]=x[i_+i1_]; -//--- Solve 1-based - SafeSolveTriangular(a1,n,x1,s,isupper,istrans,isunit,normin,cnorm); -//--- From 1-based to 0-based - i1_=1; - for(i_=0;i_<=n-1;i_++) - x[i_]=x1[i_+i1_]; - } -//+------------------------------------------------------------------+ -//| Obsolete 1-based subroutine. | -//| See RMatrixTRSafeSolve for 0-based replacement. | -//+------------------------------------------------------------------+ -static void CTrLinSolve::SafeSolveTriangular(CMatrixDouble &a,const int n, - double &x[],double &s, - const bool isupper, - const bool istrans, - const bool isunit, - const bool normin, - double &cnorm[]) - { -//--- create variables - int i=0; - int imax=0; - int j=0; - int jfirst=0; - int jinc=0; - int jlast=0; - int jm1=0; - int jp1=0; - int ip1=0; - int im1=0; - int k=0; - int flg=0; - double v=0; - double vd=0; - double bignum=0; - double grow=0; - double rec=0; - double smlnum=0; - double sumj=0; - double tjj=0; - double tjjs=0; - double tmax=0; - double tscal=0; - double uscal=0; - double xbnd=0; - double xj=0; - double xmax=0; - bool notran; - bool upper; - bool nounit; - int i_=0; -//--- initialization - s=0; - upper=isupper; - notran=!istrans; - nounit=!isunit; -//--- these initializers are not really necessary, -//--- but without them compiler complains about uninitialized locals - tjjs=0; -//--- Quick return if possible - if(n==0) - return; -//--- Determine machine dependent parameters to control overflow. - smlnum=CMath::m_minrealnumber/(CMath::m_machineepsilon*2); - bignum=1/smlnum; - s=1; -//--- check - if(!normin) - { - ArrayResizeAL(cnorm,n+1); - //--- Compute the 1-norm of each column,not including the diagonal. - if(upper) - { - //--- A is upper triangular. - for(j=1;j<=n;j++) - { - v=0; - for(k=1;k<=j-1;k++) - v=v+MathAbs(a[k][j]); - cnorm[j]=v; - } - } - else - { - //--- A is lower triangular. - for(j=1;j<=n-1;j++) - { - v=0; - for(k=j+1;k<=n;k++) - v=v+MathAbs(a[k][j]); - cnorm[j]=v; - } - cnorm[n]=0; - } - } -//--- Scale the column norms by TSCAL if the maximum element in CNORM is -//--- greater than BIGNUM. - imax=1; - for(k=2;k<=n;k++) - { - //--- check - if(cnorm[k]>cnorm[imax]) - imax=k; - } - tmax=cnorm[imax]; -//--- check - if(tmax<=bignum) - tscal=1; - else - { - tscal=1/(smlnum*tmax); - for(i_=1;i_<=n;i_++) - cnorm[i_]=tscal*cnorm[i_]; - } -//--- Compute a bound on the computed solution vector to see if the -//--- Level 2 BLAS routine DTRSV can be used. - j=1; - for(k=2;k<=n;k++) - { - //--- check - if(MathAbs(x[k])>MathAbs(x[j])) - j=k; - } -//--- change values - xmax=MathAbs(x[j]); - xbnd=xmax; -//--- check - if(notran) - { - //--- Compute the growth in A * x=b. - if(upper) - { - jfirst=n; - jlast=1; - jinc=-1; - } - else - { - jfirst=1; - jlast=n; - jinc=1; - } - //--- check - if(tscal!=1.0) - grow=0; - else - { - //--- check - if(nounit) - { - //--- A is non-unit triangular. - //--- Compute GROW=1/G(j) and XBND=1/M(j). - //--- Initially,G(0)=max{x(i),i=1,...,n}. - grow=1/MathMax(xbnd,smlnum); - xbnd=grow; - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Exit the loop if the growth factor is too small. - if(grow<=smlnum) - break; - //--- M(j)=G(j-1) / abs(A(j,j)) - tjj=MathAbs(a[j][j]); - xbnd=MathMin(xbnd,MathMin(1,tjj)*grow); - //--- check - if(tjj+cnorm[j]>=smlnum) - { - //--- G(j)=G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) ) - grow=grow*(tjj/(tjj+cnorm[j])); - } - else - { - //--- G(j) could overflow,set GROW to 0. - grow=0; - } - //--- check - if(j==jlast) - grow=xbnd; - j=j+jinc; - } - } - else - { - //--- A is unit triangular. - //--- Compute GROW=1/G(j), where G(0)=max{x(i), i=1,...,n}. - grow=MathMin(1,1/MathMax(xbnd,smlnum)); - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Exit the loop if the growth factor is too small. - if(grow<=smlnum) - break; - //--- G(j) = G(j-1)*( 1 + CNORM(j) ) - grow=grow*(1/(1+cnorm[j])); - j=j+jinc; - } - } - } - } - else - { - //--- Compute the growth in A' * x = b. - if(upper) - { - jfirst=1; - jlast=n; - jinc=1; - } - else - { - jfirst=n; - jlast=1; - jinc=-1; - } - //--- check - if(tscal!=1.0) - grow=0; - else - { - //--- check - if(nounit) - { - //--- A is non-unit triangular. - //--- Compute GROW=1/G(j) and XBND=1/M(j). - //--- Initially, M(0)=max{x(i), i=1,...,n}. - grow=1/MathMax(xbnd,smlnum); - xbnd=grow; - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Exit the loop if the growth factor is too small. - if(grow<=smlnum) - break; - //--- G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) ) - xj=1+cnorm[j]; - grow=MathMin(grow,xbnd/xj); - //--- M(j)=M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j)) - tjj=MathAbs(a[j][j]); - //--- check - if(xj>tjj) - xbnd=xbnd*(tjj/xj); - //--- check - if(j==jlast) - grow=MathMin(grow,xbnd); - j=j+jinc; - } - } - else - { - //--- A is unit triangular. - //--- Compute GROW=1/G(j), where G(0)=max{x(i), i=1,...,n}. - grow=MathMin(1,1/MathMax(xbnd,smlnum)); - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Exit the loop if the growth factor is too small. - if(grow<=smlnum) - break; - //--- G(j)=( 1 + CNORM(j) )*G(j-1) - xj=1+cnorm[j]; - grow=grow/xj; - j=j+jinc; - } - } - } - } - if(grow*tscal>smlnum) - { - //--- Use the Level 2 BLAS solve if the reciprocal of the bound on - //--- elements of X is not too small. - if((upper && notran) || (!upper && !notran)) - { - //--- check - if(nounit) - vd=a[n][n]; - else - vd=1; - x[n]=x[n]/vd; - for(i=n-1;i>=1;i--) - { - ip1=i+1; - //--- check - if(upper) - { - v=0.0; - for(i_=ip1;i_<=n;i_++) - v+=a[i][i_]*x[i_]; - } - else - { - v=0.0; - for(i_=ip1;i_<=n;i_++) - v+=a[i_][i]*x[i_]; - } - //--- check - if(nounit) - vd=a[i][i]; - else - vd=1; - x[i]=(x[i]-v)/vd; - } - } - else - { - //--- check - if(nounit) - vd=a[1][1]; - else - vd=1; - x[1]=x[1]/vd; - for(i=2;i<=n;i++) - { - im1=i-1; - //--- check - if(upper) - { - v=0.0; - for(i_=1;i_<=im1;i_++) - v+=a[i_][i]*x[i_]; - } - else - { - v=0.0; - for(i_=1;i_<=im1;i_++) - v+=a[i][i_]*x[i_]; - } - //--- check - if(nounit) - vd=a[i][i]; - else - vd=1; - x[i]=(x[i]-v)/vd; - } - } - } - else - { - //--- Use a Level 1 BLAS solve, scaling intermediate results. - if(xmax>bignum) - { - //--- Scale X so that its components are less than or equal to - //--- BIGNUM in absolute value. - s=bignum/xmax; - for(i_=1;i_<=n;i_++) - x[i_]=s*x[i_]; - xmax=bignum; - } - //--- check - if(notran) - { - //--- Solve A * x = b - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Compute x(j)=b(j) / A(j,j), scaling x if necessary. - xj=MathAbs(x[j]); - flg=0; - //--- check - if(nounit) - tjjs=a[j][j]*tscal; - else - { - tjjs=tscal; - //--- check - if(tscal==1.0) - flg=100; - } - //--- check - if(flg!=100) - { - tjj=MathAbs(tjjs); - if(tjj>smlnum) - { - //--- abs(A(j,j)) > SMLNUM: - if(tjj<1.0) - { - //--- check - if(xj>(double)(tjj*bignum)) - { - //--- Scale x by 1/b(j). - rec=1/xj; - for(i_=1;i_<=n;i_++) - { - x[i_]=rec*x[i_]; - } - s=s*rec; - xmax=xmax*rec; - } - } - x[j]=x[j]/tjjs; - xj=MathAbs(x[j]); - } - else - { - //--- check - if(tjj>0.0) - { - //--- 0 < abs(A(j,j)) <=SMLNUM: - if(xj>(double)(tjj*bignum)) - { - //--- Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM - //--- to avoid overflow when dividing by A(j,j). - rec=tjj*bignum/xj; - //--- check - if(cnorm[j]>1.0) - { - //--- Scale by 1/CNORM(j) to avoid overflow when - //--- multiplying x(j) times column j. - rec=rec/cnorm[j]; - } - for(i_=1;i_<=n;i_++) - x[i_]=rec*x[i_]; - s=s*rec; - xmax=xmax*rec; - } - x[j]=x[j]/tjjs; - xj=MathAbs(x[j]); - } - else - { - //--- A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and - //--- scale = 0, and compute a solution to A*x = 0. - for(i=1;i<=n;i++) - x[i]=0; - //--- change values - x[j]=1; - xj=1; - s=0; - xmax=0; - } - } - } - //--- Scale x if necessary to avoid overflow when adding a - //--- multiple of column j of A. - if(xj>1.0) - { - rec=1/xj; - //--- check - if(cnorm[j]>(bignum-xmax)*rec) - { - //--- Scale x by 1/(2*abs(x(j))). - rec=rec*0.5; - for(i_=1;i_<=n;i_++) - x[i_]=rec*x[i_]; - s=s*rec; - } - } - else - { - //--- check - if(xj*cnorm[j]>bignum-xmax) - { - //--- Scale x by 1/2. - for(i_=1;i_<=n;i_++) - x[i_]=0.5*x[i_]; - s=s*0.5; - } - } - //--- check - if(upper) - { - //--- check - if(j>1) - { - //--- Compute the update - //--- x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j) - v=x[j]*tscal; - jm1=j-1; - //--- change x - for(i_=1;i_<=jm1;i_++) - x[i_]=x[i_]-v*a[i_][j]; - i=1; - for(k=2;k<=j-1;k++) - { - //--- check - if(MathAbs(x[k])>MathAbs(x[i])) - i=k; - } - xmax=MathAbs(x[i]); - } - } - else - { - //--- check - if(jMathAbs(x[i])) - i=k; - } - xmax=MathAbs(x[i]); - } - } - j=j+jinc; - } - } - else - { - //--- Solve A' * x = b - j=jfirst; - while((jinc>0 && j<=jlast) || (jinc<0 && j>=jlast)) - { - //--- Compute x(j) = b(j) - sum A(k,j)*x(k). - //--- k<>j - xj=MathAbs(x[j]); - uscal=tscal; - rec=1/MathMax(xmax,1); - //--- check - if(cnorm[j]>(bignum-xj)*rec) - { - //--- If x(j) could overflow,scale x by 1/(2*XMAX). - rec=rec*0.5; - //--- check - if(nounit) - tjjs=a[j][j]*tscal; - else - tjjs=tscal; - tjj=MathAbs(tjjs); - //--- check - if(tjj>1.0) - { - //--- Divide by A(j,j) when scaling x if A(j,j) > 1. - rec=MathMin(1,rec*tjj); - uscal=uscal/tjjs; - } - //--- check - if(rec<1.0) - { - for(i_=1;i_<=n;i_++) - x[i_]=rec*x[i_]; - s=s*rec; - xmax=xmax*rec; - } - } - sumj=0; - //--- check - if(uscal==1.0) - { - //--- If the scaling needed for A in the dot product is 1, - //--- call DDOT to perform the dot product. - if(upper) - { - //--- check - if(j>1) - { - jm1=j-1; - sumj=0.0; - for(i_=1;i_<=jm1;i_++) - sumj+=a[i_][j]*x[i_]; - } - else - sumj=0; - } - else - { - //--- check - if(jsmlnum) - { - //--- abs(A(j,j)) > SMLNUM: - if(tjj<1.0) - { - //--- check - if(xj>(double)(tjj*bignum)) - { - //--- Scale X by 1/abs(x(j)). - rec=1/xj; - for(i_=1;i_<=n;i_++) - x[i_]=rec*x[i_]; - s=s*rec; - xmax=xmax*rec; - } - } - x[j]=x[j]/tjjs; - } - else - { - //--- check - if(tjj>0.0) - { - //--- 0 < abs(A(j,j)) <=SMLNUM: - if(xj>(double)(tjj*bignum)) - { - //--- Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. - rec=tjj*bignum/xj; - for(i_=1;i_<=n;i_++) - x[i_]=rec*x[i_]; - s=s*rec; - xmax=xmax*rec; - } - x[j]=x[j]/tjjs; - } - else - { - //--- A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and - //--- scale = 0, and compute a solution to A'*x = 0. - for(i=1;i<=n;i++) - x[i]=0; - x[j]=1; - s=0; - xmax=0; - } - } - } - } - else - { - //--- Compute x(j) := x(j) / A(j,j) - sumj if the dot - //--- product has already been divided by 1/A(j,j). - x[j]=x[j]/tjjs-sumj; - } - xmax=MathMax(xmax,MathAbs(x[j])); - j=j+jinc; - } - } - s=s/tscal; - } -//--- Scale the column norms by 1/TSCAL for return. - if(tscal!=1.0) - { - v=1/tscal; - for(i_=1;i_<=n;i_++) - cnorm[i_]=v*cnorm[i_]; - } - } -//+------------------------------------------------------------------+ -//| Safe solvers | -//+------------------------------------------------------------------+ -class CSafeSolve - { -private: - //--- private method - static bool CBasicSolveAndUpdate(al_complex &alpha,al_complex &beta,const double lnmax,const double bnorm,const double maxgrowth,double &xnorm,al_complex &x); -public: - //--- constructor, destructor - CSafeSolve(void); - ~CSafeSolve(void); - //--- public methods - static bool RMatrixScaledTrSafeSolve(CMatrixDouble &a,const double sa,const int n,double &x[],const bool isupper,const int trans,const bool isunit,const double maxgrowth); - static bool CMatrixScaledTrSafeSolve(CMatrixComplex &a,const double sa,const int n,al_complex &x[],const bool isupper,const int trans,const bool isunit,const double maxgrowth); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSafeSolve::CSafeSolve(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSafeSolve::~CSafeSolve(void) - { - - } -//+------------------------------------------------------------------+ -//| Real implementation of CMatrixScaledTRSafeSolve | -//+------------------------------------------------------------------+ -static bool CSafeSolve::RMatrixScaledTrSafeSolve(CMatrixDouble &a,const double sa, - const int n,double &x[], - const bool isupper,const int trans, - const bool isunit,const double maxgrowth) - { -//--- create variables - bool result; - double lnmax=0; - double nrmb=0; - double nrmx=0; - double vr=0; - al_complex alpha=0; - al_complex beta=0; - al_complex cx=0; - int i_=0; - int i=0; -//--- create array - double tmp[]; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return(false); -//--- check - if(!CAp::Assert(trans==0 || trans==1,__FUNCTION__+": incorrect Trans!")) - return(false); -//--- initialization - result=true; - lnmax=MathLog(CMath::m_maxrealnumber); -//--- Quick return if possible - if(n<=0) - return(result); -//--- Load norms: right part and X - nrmb=0; - for(i=0;i=0;i--) - { - //--- Task is reduced to alpha*x[i] = beta - if(isunit) - alpha=sa; - else - alpha=a[i][i]*sa; - //--- check - if(i0) - { - for(i_=0;i_=0;i--) - { - //--- Task is reduced to alpha*x[i] = beta - if(isunit) - alpha=sa; - else - alpha=a[i][i]*sa; - beta=x[i]; - //--- solve alpha*x[i] = beta - result=CBasicSolveAndUpdate(alpha,beta,lnmax,nrmb,maxgrowth,nrmx,cx); - //--- check - if(!result) - return(result); - //--- change values - x[i]=cx.re; - //--- update the rest of right part - if(i>0) - { - vr=cx.re; - for(i_=0;i_0,__FUNCTION__+": incorrect N!")) - return(false); -//--- check - if(!CAp::Assert((trans==0 || trans==1) || trans==2,__FUNCTION__+": incorrect Trans!")) - return(false); -//--- initialization - result=true; - lnmax=MathLog(CMath::m_maxrealnumber); -//--- Quick return if possible - if(n<=0) - return(result); -//--- Load norms: right part and X - nrmb=0; - for(i=0;i=0;i--) - { - //--- Task is reduced to alpha*x[i] = beta - if(isunit) - alpha=sa; - else - alpha=a[i][i]*sa; - //--- check - if(i0) - { - for(i_=0;i_=0;i--) - { - //--- Task is reduced to alpha*x[i] = beta - if(isunit) - alpha=sa; - else - alpha=a[i][i]*sa; - beta=x[i]; - //--- solve alpha*x[i] = beta - result=CBasicSolveAndUpdate(alpha,beta,lnmax,nrmb,maxgrowth,nrmx,vc); - //--- check - if(!result) - return(result); - x[i]=vc; - //--- update the rest of right part - if(i>0) - { - for(i_=0;i_=0;i--) - { - //--- Task is reduced to alpha*x[i] = beta - if(isunit) - alpha=sa; - else - alpha=CMath::Conj(a[i][i])*sa; - beta=x[i]; - //--- solve alpha*x[i] = beta - result=CBasicSolveAndUpdate(alpha,beta,lnmax,nrmb,maxgrowth,nrmx,vc); - //--- check - if(!result) - return(result); - x[i]=vc; - //--- update the rest of right part - if(i>0) - { - for(i_=0;i_lnmax) - return(result); - x=beta/alpha; - } - else - { - //--- alpha*x[i]=0 - x=0; - } -//--- update NrmX, test growth limit - xnorm=MathMax(xnorm,CMath::AbsComplex(x)); -//--- check - if(xnorm>maxgrowth*bnorm) - return(result); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Dot-product | -//+------------------------------------------------------------------+ -class CXblas - { -private: - //--- private methods - static void XSum(double &w[],const double mx,const int n,double &r,double &rerr); - static double XFastPow(const double r,const int n); -public: - //--- constructor, destructor - CXblas(void); - ~CXblas(void); - //--- public methods - static void XDot(double &a[],double &b[],const int n,double &temp[],double &r,double &rerr); - static void XCDot(al_complex &a[],al_complex &b[],const int n,double &temp[],al_complex &r,double &rerr); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CXblas::CXblas(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CXblas::~CXblas(void) - { - - } -//+------------------------------------------------------------------+ -//| More precise dot-product. Absolute error of subroutine result is | -//| about 1 ulp of max(MX,V), where: | -//| MX = max( |a[i]*b[i]| ) | -//| V = |(a,b)| | -//| INPUT PARAMETERS | -//| A - array[0..N-1], vector 1 | -//| B - array[0..N-1], vector 2 | -//| N - vectors length, N<2^29. | -//| Temp - array[0..N-1], pre-allocated temporary storage | -//| OUTPUT PARAMETERS | -//| R - (A,B) | -//| RErr - estimate of error. This estimate accounts for | -//| both errors during calculation of (A,B) and | -//| errors introduced by rounding of A and B to fit in| -//| double (about 1 ulp). | -//+------------------------------------------------------------------+ -static void CXblas::XDot(double &a[],double &b[],const int n,double &temp[], - double &r,double &rerr) - { -//--- create variables - int i=0; - double mx=0; - double v=0; -//--- initialization - r=0; - rerr=0; -//--- special cases: -//--- * N=0 - if(n==0) - { - r=0; - rerr=0; - //--- exit the function - return; - } - mx=0; -//--- calculations - for(i=0;i<=n-1;i++) - { - v=a[i]*b[i]; - temp[i]=v; - mx=MathMax(mx,MathAbs(v)); - } -//--- check - if(mx==0.0) - { - r=0; - rerr=0; - //--- exit the function - return; - } -//--- function call - XSum(temp,mx,n,r,rerr); - } -//+------------------------------------------------------------------+ -//| More precise complex dot-product. Absolute error of subroutine | -//| result is about 1 ulp of max(MX,V), where: | -//| MX = max( |a[i]*b[i]| ) | -//| V = |(a,b)| | -//| INPUT PARAMETERS | -//| A - array[0..N-1], vector 1 | -//| B - array[0..N-1], vector 2 | -//| N - vectors length, N<2^29. | -//| Temp - array[0..2*N-1], pre-allocated temporary storage | -//| OUTPUT PARAMETERS | -//| R - (A,B) | -//| RErr - estimate of error. This estimate accounts for | -//| both errors during calculation of (A,B) and | -//| errors introduced by rounding of A and B to fit | -//| in double (about 1 ulp). | -//+------------------------------------------------------------------+ -static void CXblas::XCDot(al_complex &a[],al_complex &b[],const int n,double &temp[], - al_complex &r,double &rerr) - { -//--- create variables - int i=0; - double mx=0; - double v=0; - double rerrx=0; - double rerry=0; -//--- initialization - r=0; - rerr=0; -//--- special cases: -//--- * N=0 - if(n==0) - { - r=0; - rerr=0; - //--- exit the function - return; - } -//--- calculate real part - mx=0; - for(i=0;i<=n-1;i++) - { - //--- change values - v=a[i].re*b[i].re; - temp[2*i+0]=v; - mx=MathMax(mx,MathAbs(v)); - v=-(a[i].im*b[i].im); - temp[2*i+1]=v; - mx=MathMax(mx,MathAbs(v)); - } -//--- check - if(mx==0.0) - { - r.re=0; - rerrx=0; - } - else - XSum(temp,mx,2*n,r.re,rerrx); -//--- calculate imaginary part - mx=0; - for(i=0;i<=n-1;i++) - { - //--- change values - v=a[i].re*b[i].im; - temp[2*i+0]=v; - mx=MathMax(mx,MathAbs(v)); - v=a[i].im*b[i].re; - temp[2*i+1]=v; - mx=MathMax(mx,MathAbs(v)); - } -//--- check - if(mx==0.0) - { - r.im=0; - rerry=0; - } - else - XSum(temp,mx,2*n,r.im,rerry); -//--- total error - if(rerrx==0.0 && rerry==0.0) - rerr=0; - else - rerr=MathMax(rerrx,rerry)*MathSqrt(1+CMath::Sqr(MathMin(rerrx,rerry)/MathMax(rerrx,rerry))); - } -//+------------------------------------------------------------------+ -//| Internal subroutine for extra-precise calculation of SUM(w[i]). | -//| INPUT PARAMETERS: | -//| W - array[0..N-1], values to be added | -//| W is modified during calculations. | -//| MX - max(W[i]) | -//| N - array size | -//| OUTPUT PARAMETERS: | -//| R - SUM(w[i]) | -//| RErr- error estimate for R | -//+------------------------------------------------------------------+ -static void CXblas::XSum(double &w[],const double mx,const int n,double &r, - double &rerr) - { -//--- create variables - int i=0; - int k=0; - int ks=0; - double v=0; - double s=0; - double ln2=0; - double chunk=0; - double invchunk=0; - bool allzeros; - int i_=0; -//--- initialization - r=0; - rerr=0; -//--- special cases: -//--- * N=0 -//--- * N is too large to use integer arithmetics - if(n==0) - { - r=0; - rerr=0; - //--- exit the function - return; - } -//--- check - if(mx==0.0) - { - r=0; - rerr=0; - //--- exit the function - return; - } -//--- check - if(!CAp::Assert(n<536870912,__FUNCTION__+": N is too large!")) - return; -//--- Prepare - ln2=MathLog(2); - rerr=mx*CMath::m_machineepsilon; -//--- 1. find S such that 0.5<=S*MX<1 -//--- 2. multiply W by S, so task is normalized in some sense -//--- 3. S:=1/S so we can obtain original vector multiplying by S - k=(int)MathRound(MathLog(mx)/ln2); - s=XFastPow(2,-k); -//--- change s - while(s*mx>=1.0) - s=0.5*s; - while(s*mx<0.5) - s=2*s; - for(i_=0;i_<=n-1;i_++) - w[i_]=s*w[i_]; - s=1/s; -//--- find Chunk=2^M such that N*Chunk<2^29 -//--- we have chosen upper limit (2^29) with enough space left -//--- to tolerate possible problems with rounding and N's close -//--- to the limit, so we don't want to be very strict here. - k=(int)(MathLog((double)536870912/(double)n)/ln2); - chunk=XFastPow(2,k); -//--- check - if(chunk<2.0) - chunk=2; - invchunk=1/chunk; -//--- calculate result - r=0; - for(i_=0;i_<=n-1;i_++) - w[i_]=chunk*w[i_]; -//--- cycle - while(true) - { - //--- change values - s=s*invchunk; - allzeros=true; - ks=0; - for(i=0;i<=n-1;i++) - { - v=w[i]; - k=(int)(v); - //--- check - if(v!=k) - allzeros=false; - w[i]=chunk*(v-k); - ks=ks+k; - } - r=r+s*ks; - v=MathAbs(r); - //--- check - if(allzeros || s*n+mx==mx) - break; - } -//--- correct error - rerr=MathMax(rerr,MathAbs(r)*CMath::m_machineepsilon); - } -//+------------------------------------------------------------------+ -//| Fast Pow | -//+------------------------------------------------------------------+ -static double CXblas::XFastPow(const double r,const int n) - { -//--- create a variable - double result=0; -//--- check - if(n>0) - { - //--- check - if(n%2==0) - result=CMath::Sqr(XFastPow(r,n/2)); - else - result=r*XFastPow(r,n-1); - //--- return result - return(result); - } -//--- check - if(n==0) - result=1; -//--- check - if(n<0) - result=XFastPow(1/r,-n); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CLinMin | -//+------------------------------------------------------------------+ -class CLinMinState - { -public: - //--- class variables - bool m_brackt; - bool m_stage1; - int m_infoc; - double m_dg; - double m_dgm; - double m_dginit; - double m_dgtest; - double m_dgx; - double m_dgxm; - double m_dgy; - double m_dgym; - double m_finit; - double m_ftest1; - double m_fm; - double m_fx; - double m_fxm; - double m_fy; - double m_fym; - double m_stx; - double m_sty; - double m_stmin; - double m_stmax; - double m_width; - double m_width1; - double m_xtrapf; - //--- constructor, destructor - CLinMinState(void); - ~CLinMinState(void); - //--- create a copy - void Copy(CLinMinState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLinMinState::CLinMinState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLinMinState::~CLinMinState(void) - { - - } -//+------------------------------------------------------------------+ -//| Create a copy | -//+------------------------------------------------------------------+ -void CLinMinState::Copy(CLinMinState &obj) - { -//--- copy variables - m_brackt=obj.m_brackt; - m_stage1=obj.m_stage1; - m_infoc=obj.m_infoc; - m_dg=obj.m_dg; - m_dgm=obj.m_dgm; - m_dginit=obj.m_dginit; - m_dgtest=obj.m_dgtest; - m_dgx=obj.m_dgx; - m_dgxm=obj.m_dgxm; - m_dgy=obj.m_dgy; - m_dgym=obj.m_dgym; - m_finit=obj.m_finit; - m_ftest1=obj.m_ftest1; - m_fm=obj.m_fm; - m_fx=obj.m_fx; - m_fxm=obj.m_fxm; - m_fy=obj.m_fy; - m_fym=obj.m_fym; - m_stx=obj.m_stx; - m_sty=obj.m_sty; - m_stmin=obj.m_stmin; - m_stmax=obj.m_stmax; - m_width=obj.m_width; - m_width1=obj.m_width1; - m_xtrapf=obj.m_xtrapf; - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CLinMin | -//+------------------------------------------------------------------+ -class CArmijoState - { -public: - bool m_needf; - double m_x[]; - double m_f; - int m_n; - double m_xbase[]; - double m_s[]; - double m_stplen; - double m_fcur; - double m_stpmax; - int m_fmax; - int m_nfev; - int m_info; - RCommState m_rstate; - //--- constructor, destructor - CArmijoState(void); - ~CArmijoState(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CArmijoState::CArmijoState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CArmijoState::~CArmijoState(void) - { - - } -//+------------------------------------------------------------------+ -//| Minimization of linear forms | -//+------------------------------------------------------------------+ -class CLinMin - { -private: - //--- private methods - static void MCStep(double &stx,double &fx,double &dx,double &sty,double &fy,double &dy,double &stp,double fp,double dp,bool &m_brackt,double stmin,double stmax,int &info); - //--- auxiliary functions for ArmijoIteration - static void Func_lbl_rcomm(CArmijoState &state,int n,double v); - static bool Func_lbl_6(CArmijoState &state,int &n,double &v); - static bool Func_lbl_10(CArmijoState &state,int &n,double &v); -public: - //--- class constants - static const double m_ftol; - static const double m_xtol; - static const int m_maxfev; - static const double m_stpmin; - static const double m_defstpmax; - static const double m_armijofactor; - //--- constructor, destructor - CLinMin(void); - ~CLinMin(void); - //--- public methods - static void LinMinNormalized(double &d[],double &stp,const int n); - static void MCSrch(const int n,double &x[],double &f,double &g[],double &s[],double &stp,double stpmax,double gtol,int &info,int &nfev,double &wa[],CLinMinState &state,int &stage); - static void ArmijoCreate(const int n,double &x[],const double f,double &s[],const double stp,const double stpmax,const int ffmax,CArmijoState &state); - static void ArmijoResults(CArmijoState &state,int &info,double &stp,double &f); - static bool ArmijoIteration(CArmijoState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CLinMin::m_ftol=0.001; -const double CLinMin::m_xtol=100*CMath::m_machineepsilon; -const int CLinMin::m_maxfev=20; -const double CLinMin::m_stpmin=1.0E-50; -const double CLinMin::m_defstpmax=1.0E+50; -const double CLinMin::m_armijofactor=1.3; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLinMin::CLinMin(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLinMin::~CLinMin(void) - { - - } -//+------------------------------------------------------------------+ -//| Normalizes direction/step pair: makes |D|=1,scales Stp. | -//| If |D|=0,it returns,leavind D/Stp unchanged. | -//+------------------------------------------------------------------+ -static void CLinMin::LinMinNormalized(double &d[],double &stp,const int n) - { -//--- create variables - double mx=0; - double s=0; - int i=0; - int i_=0; -//--- first, scale D to avoid underflow/overflow durng squaring - mx=0; - for(i=0;i<=n-1;i++) - mx=MathMax(mx,MathAbs(d[i])); -//--- check - if(mx==0.0) - return; - s=1/mx; - for(i_=0;i_<=n-1;i_++) - d[i_]=s*d[i_]; - stp=stp/s; -//--- normalize D - s=0.0; - for(i_=0;i_<=n-1;i_++) - s+=d[i_]*d[i_]; - s=1/MathSqrt(s); - for(i_=0;i_<=n-1;i_++) - d[i_]=s*d[i_]; - stp=stp/s; - } -//+------------------------------------------------------------------+ -//| The purpose of MCSrch is to find a step which satisfies a | -//| sufficient decrease condition and a curvature condition. | -//| At each stage the subroutine updates an interval of uncertainty | -//| with endpoints stx and sty. The interval of uncertainty is | -//| initially chosen so that it contains a minimizer of the modified | -//| function | -//| f(x+stp*s) - f(x) - ftol*stp*(gradf(x)'s). | -//| If a step is obtained for which the modified function has a | -//| nonpositive function value and nonnegative derivative, then the | -//| interval of uncertainty is chosen so that it contains a minimizer| -//| of f(x+stp*s). | -//| The algorithm is designed to find a step which satisfies the | -//| sufficient decrease condition | -//| f(x+stp*s) .le. f(x) + ftol*stp*(gradf(x)'s), | -//| and the curvature condition | -//| abs(gradf(x+stp*s)'s)) .le. gtol*abs(gradf(x)'s). | -//| If ftol is less than gtol and if, for example, the function is | -//| bounded below, then there is always a step which satisfies both | -//| conditions. If no step can be found which satisfies both | -//| conditions, then the algorithm usually stops when rounding errors| -//| prevent further progress. In this case stp only satisfies the | -//| sufficient decrease condition. | -//| :::::::::::::important notes::::::::::::: | -//| note 1: | -//| This routine guarantees that it will stop at the last point | -//| where function value was calculated. It won't make several | -//| additional function evaluations after finding good point. So if | -//| you store function evaluations requested by this routine, you can| -//| be sure that last one is the point where we've stopped. | -//| NOTE 2: | -//| when 0stpmax) - stp=stpmax; -//--- Main cycle - while(true) - { - //--- check - if(stage==0) - { - //--- NEXT - stage=2; - continue; - } - //--- check - if(stage==2) - { - state.m_infoc=1; - info=0; - //--- check the input parameters for errors. - if(stpmax0.0) - { - info=5; - stp=0.0; - //--- exit the function - return; - } - //--- check - if(n<=0 || stp<=0.0 || m_ftol<0.0 || gtol=0.0) - { - stage=0; - return; - } - //--- initialize local variables. - state.m_brackt=false; - state.m_stage1=true; - nfev=0; - state.m_finit=f; - state.m_dgtest=m_ftol*state.m_dginit; - state.m_width=stpmax-m_stpmin; - state.m_width1=state.m_width/p5; - for(i_=0;i_<=n-1;i_++) - wa[i_]=x[i_]; - //--- the variables stx,fx,dgx contain the values of the step, - //--- function,and directional derivative at the best step. - //--- the variables sty,fy,dgy contain the value of the step, - //--- function,and derivative at the other endpoint of - //--- the interval of uncertainty. - //--- the variables stp,f,dg contain the values of the step, - //--- function,and derivative at the current step. - state.m_stx=0; - state.m_fx=state.m_finit; - state.m_dgx=state.m_dginit; - state.m_sty=0; - state.m_fy=state.m_finit; - state.m_dgy=state.m_dginit; - //--- next - stage=3; - continue; - } - //--- check - if(stage==3) - { - //--- start of iteration. - //--- set the minimum and maximum steps to correspond - //--- to the present interval of uncertainty. - if(state.m_brackt) - { - //--- check - if(state.m_stxstpmax) - stp=stpmax; - //--- check - if(stp=state.m_stmax)) || nfev>=m_maxfev-1 || state.m_infoc==0 || - (state.m_brackt && state.m_stmax-state.m_stmin<=m_xtol*state.m_stmax)) - { - stp=state.m_stx; - } - //--- evaluate the function and gradient at stp - //--- and compute the directional derivative. - for(i_=0;i_<=n-1;i_++) - x[i_]=wa[i_]; - for(i_=0;i_<=n-1;i_++) - x[i_]=x[i_]+stp*s[i_]; - //--- NEXT - stage=4; - return; - } - //--- check - if(stage==4) - { - info=0; - nfev=nfev+1; - v=0.0; - for(i_=0;i_<=n-1;i_++) - v+=g[i_]*s[i_]; - state.m_dg=v; - state.m_ftest1=state.m_finit+stp*state.m_dgtest; - //--- test for convergence. - if((state.m_brackt && (stp<=state.m_stmin || stp>=state.m_stmax)) || state.m_infoc==0) - info=6; - //--- check - if((stp==stpmax && f<=state.m_ftest1) && state.m_dg<=state.m_dgtest) - info=5; - //--- check - if(stp==m_stpmin && (f>state.m_ftest1 || state.m_dg>=state.m_dgtest)) - info=4; - //--- check - if(nfev>=m_maxfev) - info=3; - //--- check - if(state.m_brackt && state.m_stmax-state.m_stmin<=m_xtol*state.m_stmax) - info=2; - //--- check - if(f<=state.m_ftest1 && MathAbs(state.m_dg)<=-(gtol*state.m_dginit)) - info=1; - //--- check for termination. - if(info!=0) - { - stage=0; - return; - } - //--- in the first stage we seek a step for which the modified - //--- function has a nonpositive value and nonnegative derivative. - if((state.m_stage1 && f<=state.m_ftest1) && state.m_dg>=MathMin(m_ftol,gtol)*state.m_dginit) - state.m_stage1=false; - //--- a modified function is used to predict the step only if - //--- we have not obtained a step for which the modified - //--- function has a nonpositive function value and nonnegative - //--- derivative,and if a lower function value has been - //--- obtained but the decrease is not sufficient. - if((state.m_stage1 && f<=state.m_fx) && f>state.m_ftest1) - { - //--- define the modified function and derivative values. - state.m_fm=f-stp*state.m_dgtest; - state.m_fxm=state.m_fx-state.m_stx*state.m_dgtest; - state.m_fym=state.m_fy-state.m_sty*state.m_dgtest; - state.m_dgm=state.m_dg-state.m_dgtest; - state.m_dgxm=state.m_dgx-state.m_dgtest; - state.m_dgym=state.m_dgy-state.m_dgtest; - //--- call cstep to update the interval of uncertainty - //--- and to compute the new step. - MCStep(state.m_stx,state.m_fxm,state.m_dgxm,state.m_sty,state.m_fym,state.m_dgym,stp,state.m_fm,state.m_dgm,state.m_brackt,state.m_stmin,state.m_stmax,state.m_infoc); - //--- reset the function and gradient values for f. - state.m_fx=state.m_fxm+state.m_stx*state.m_dgtest; - state.m_fy=state.m_fym+state.m_sty*state.m_dgtest; - state.m_dgx=state.m_dgxm+state.m_dgtest; - state.m_dgy=state.m_dgym+state.m_dgtest; - } - else - { - //--- call mcstep to update the interval of uncertainty - //--- and to compute the new step. - MCStep(state.m_stx,state.m_fx,state.m_dgx,state.m_sty,state.m_fy,state.m_dgy,stp,f,state.m_dg,state.m_brackt,state.m_stmin,state.m_stmax,state.m_infoc); - } - //--- force a sufficient decrease in the size of the - //--- interval of uncertainty. - if(state.m_brackt) - { - //--- check - if(MathAbs(state.m_sty-state.m_stx)>=p66*state.m_width1) - stp=state.m_stx+p5*(state.m_sty-state.m_stx); - state.m_width1=state.m_width; - state.m_width=MathAbs(state.m_sty-state.m_stx); - } - //--- next. - stage=3; - continue; - } - } - } -//+------------------------------------------------------------------+ -//| These functions perform Armijo line search using at most FMAX | -//| function evaluations. It doesn't enforce some kind of | -//| "sufficient decrease" criterion - it just tries different Armijo | -//| steps and returns optimum found so far. | -//| Optimization is done using F-rcomm interface: | -//| * ArmijoCreate initializes State structure | -//| (reusing previously allocated buffers) | -//| * ArmijoIteration is subsequently called | -//| * ArmijoResults returns results | -//| INPUT PARAMETERS: | -//| N - problem size | -//| X - array[N], starting point | -//| F - F(X+S*STP) | -//| S - step direction, S>0 | -//| STP - step length | -//| STPMAX - maximum value for STP or zero (if no limit is | -//| imposed) | -//| FMAX - maximum number of function evaluations | -//| State - optimization state | -//+------------------------------------------------------------------+ -static void CLinMin::ArmijoCreate(const int n,double &x[],const double f, - double &s[],const double stp,const double stpmax, - const int ffmax,CArmijoState &state) - { -//--- create a variable - int i_=0; -//--- check - if(CAp::Len(state.m_x)=MathMax(stx,sty))) || dx*(stp-stx)>=0.0) || stmaxfx) - { - //--- initialization - info=1; - bound=true; - theta=3*(fx-fp)/(stp-stx)+dx+dp; - s=MathMax(MathAbs(theta),MathMax(MathAbs(dx),MathAbs(dp))); - gamma=s*MathSqrt(CMath::Sqr(theta/s)-dx/s*(dp/s)); - //--- check - if(stpstx) - gamma=-gamma; - //--- initialization - p=gamma-dp+theta; - q=gamma-dp+gamma+dx; - r=p/q; - stpc=stp+r*(stx-stp); - stpq=stp+dp/(dp-dx)*(stx-stp); - //--- check - if(MathAbs(stpc-stp)>MathAbs(stpq-stp)) - stpf=stpc; - else - stpf=stpq; - m_brackt=true; - } - else - { - //--- check - if(MathAbs(dp)stx) - gamma=-gamma; - p=gamma-dp+theta; - q=gamma+(dx-dp)+gamma; - r=p/q; - //--- check - if(r<0.0 && (double)(gamma)!=0.0) - stpc=stp+r*(stx-stp); - else - { - //--- check - if(stp>stx) - stpc=stmax; - else - stpc=stmin; - } - stpq=stp+dp/(dp-dx)*(stx-stp); - //--- check - if(m_brackt) - { - //--- check - if(MathAbs(stp-stpc)MathAbs(stp-stpq)) - stpf=stpc; - else - stpf=stpq; - } - } - else - { - //--- fourth case. a lower function value,derivatives of the - //--- same sign, and the magnitude of the derivative does - //--- not decrease. if the minimum is not bracketed, the step - //--- is either stpmin or stpmax, else the cubic step is taken. - info=4; - bound=false; - //--- check - if(m_brackt) - { - theta=3*(fp-fy)/(sty-stp)+dy+dp; - s=MathMax(MathAbs(theta),MathMax(MathAbs(dy),MathAbs(dp))); - gamma=s*MathSqrt(CMath::Sqr(theta/s)-dy/s*(dp/s)); - //--- check - if(stp>sty) - gamma=-gamma; - //--- initialization - p=gamma-dp+theta; - q=gamma-dp+gamma+dy; - r=p/q; - stpc=stp+r*(sty-stp); - stpf=stpc; - } - else - { - //--- check - if(stp>stx) - stpf=stmax; - else - stpf=stmin; - } - } - } - } -//--- update the interval of uncertainty. this update does not -//--- depend on the new step or the case analysis above. - if(fp>fx) - { - //--- set value - sty=stp; - fy=fp; - dy=dp; - } - else - { - //--- check - if(sgnd<0.0) - { - //--- set value - sty=stx; - fy=fx; - dy=dx; - } - //--- set value - stx=stp; - fx=fp; - dx=dp; - } -//--- compute the new step and safeguard it. - stpf=MathMin(stmax,stpf); - stpf=MathMax(stmin,stpf); - stp=stpf; -//--- check - if(m_brackt && bound) - { - //--- check - if(sty>stx) - stp=MathMin(stx+0.66*(sty-stx),stp); - else - stp=MathMax(stx+0.66*(sty-stx),stp); - } - } -//+------------------------------------------------------------------+ -//| This is rcomm-based search function | -//+------------------------------------------------------------------+ -static bool CLinMin::ArmijoIteration(CArmijoState &state) - { -//--- create variables - double v=0; - int n=0; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - v=state.m_rstate.ra[0]; - } - else - { - //--- initialization - n=-983; - v=-989; - } -//--- check - if(state.m_rstate.stage==0) - { - state.m_nfev=state.m_nfev+1; - //--- check - if(state.m_f>=state.m_fcur) - { - //--- Decrease length - v=state.m_stplen/m_armijofactor; - //--- copy - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+v*state.m_s[i_]; - state.m_rstate.stage=2; - //--- Saving state - Func_lbl_rcomm(state,n,v); - //--- return result - return(true); - } - //--- change values - state.m_stplen=v; - state.m_fcur=state.m_f; - //--- function call, return result - return(Func_lbl_6(state,n,v)); - } -//--- check - if(state.m_rstate.stage==1) - { - state.m_nfev=state.m_nfev+1; - //--- make decision - if(state.m_f=state.m_fcur) - { - //--- Nothing to be done - state.m_info=1; - //--- return result - return(false); - } - //--- change values - state.m_stplen=state.m_stplen/m_armijofactor; - state.m_fcur=state.m_f; - //--- function call, return result - return(Func_lbl_10(state,n,v)); - } -//--- check - if(state.m_rstate.stage==3) - { - state.m_nfev=state.m_nfev+1; - //--- make decision - if(state.m_fstate.m_stpmax && state.m_stpmax!=0.0) - state.m_stplen=state.m_stpmax; -//--- Increase length - v=state.m_stplen*m_armijofactor; -//--- check - if(v>state.m_stpmax && state.m_stpmax!=0.0) - v=state.m_stpmax; -//--- copy - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+v*state.m_s[i_]; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,v); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ArmijoIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CLinMin::Func_lbl_rcomm(CArmijoState &state,int n,double v) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ra[0]=v; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ArmijoIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLinMin::Func_lbl_6(CArmijoState &state,int &n,double &v) - { -//--- test stopping conditions - if(state.m_nfev>=state.m_fmax) - { - state.m_info=3; - //--- return result - return(false); - } -//--- check - if(state.m_stplen>=state.m_stpmax) - { - state.m_info=5; - //--- return result - return(false); - } -//--- evaluate F - v=state.m_stplen*m_armijofactor; -//--- check - if(v>state.m_stpmax && state.m_stpmax!=0.0) - v=state.m_stpmax; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+v*state.m_s[i_]; - state.m_rstate.stage=1; -//--- Saving state - Func_lbl_rcomm(state,n,v); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ArmijoIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLinMin::Func_lbl_10(CArmijoState &state,int &n,double &v) - { -//--- test stopping conditions - if(state.m_nfev>=state.m_fmax) - { - state.m_info=3; - //--- return result - return(false); - } -//--- check - if(state.m_stplen<=m_stpmin) - { - state.m_info=4; - //--- return result - return(false); - } -//--- evaluate F - v=state.m_stplen/m_armijofactor; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+v*state.m_s[i_]; - state.m_rstate.stage=3; -//--- Saving state - Func_lbl_rcomm(state,n,v); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary functions for other classes | -//+------------------------------------------------------------------+ -class COptServ - { -public: - //--- constructor, destructor - COptServ(void); - ~COptServ(void); - //--- methods - static void TrimPrepare(const double f,double &threshold); - static void TrimFunction(double &f,double &g[],const int n,const double threshold); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -COptServ::COptServ(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -COptServ::~COptServ(void) - { - - } -//+------------------------------------------------------------------+ -//| This subroutine is used to prepare threshold value which will be | -//| used for trimming of the target function (see comments on | -//| TrimFunction() for more information). | -//| This function accepts only one parameter: function value at the | -//| starting point. It returns threshold which will be used for | -//| trimming. | -//+------------------------------------------------------------------+ -static void COptServ::TrimPrepare(const double f,double &threshold) - { -//--- calculation - threshold=10*(MathAbs(f)+1); - } -//+------------------------------------------------------------------+ -//| This subroutine is used to "trim" target function, i.e. to do | -//| following transformation: | -//| { {F,G} if F=Threshold | -//| Such transformation allows us to solve problems with | -//| singularities by redefining function in such way that it becomes | -//| bounded from above. | -//+------------------------------------------------------------------+ -static void COptServ::TrimFunction(double &f,double &g[],const int n, - const double threshold) - { -//--- create a variable - int i=0; -//--- check - if(f>=threshold) - { - f=threshold; - for(i=0;i<=n-1;i++) - g[i]=0.0; - } - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CFtBase | -//+------------------------------------------------------------------+ -class CFtPlan - { -public: - //--- arrays - int m_plan[]; - double m_precomputed[]; - double m_tmpbuf[]; - double m_stackbuf[]; - //--- constructor, destructor - CFtPlan(void); - ~CFtPlan(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFtPlan::CFtPlan(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFtPlan::~CFtPlan(void) - { - - } -//+------------------------------------------------------------------+ -//| Generation FFT, FHT plans | -//+------------------------------------------------------------------+ -class CFtBase - { -private: - //--- private methods - static void FtBaseGeneratePlanRec(const int n,int tasktype,CFtPlan &plan,int &plansize,int &precomputedsize,int &planarraysize,int &tmpmemsize,int &stackmemsize,int stackptr); - static void FtBasePrecomputePlanRec(CFtPlan &plan,const int entryoffset,const int stackptr); - static void FFtTwCalc(double &a[],const int aoffset,const int n1,const int n2); - static void InternalComplexLinTranspose(double &a[],const int m,const int n,const int astart,double &buf[]); - static void InternalRealLinTranspose(double &a[],const int m,const int n,const int astart,double &buf[]); - static void FFtICLTRec(double &a[],const int astart,const int astride,double &b[],const int bstart,const int bstride,const int m,const int n); - static void FFtIRLTRec(double &a[],const int astart,const int astride,double &b[],const int bstart,const int bstride,const int m,const int n); - static void FtBaseFindSmoothRec(const int n,const int seed,const int leastfactor,int &best); - static void FFtArrayResize(int &a[],int &asize,const int newasize); - static void ReFFHt(double &a[],const int n,const int offs); -public: - //--- class constants - static const int m_ftbaseplanentrysize; - static const int m_ftbasecffttask; - static const int m_ftbaserfhttask; - static const int m_ftbaserffttask; - static const int m_fftcooleytukeyplan; - static const int m_fftbluesteinplan; - static const int m_fftcodeletplan; - static const int m_fhtcooleytukeyplan; - static const int m_fhtcodeletplan; - static const int m_fftrealcooleytukeyplan; - static const int m_fftemptyplan; - static const int m_fhtn2plan; - static const int m_ftbaseupdatetw; - static const int m_ftbasecodeletrecommended; - static const double m_ftbaseinefficiencyfactor; - static const int m_ftbasemaxsmoothfactor; - //--- constructor, destructor - CFtBase(void); - ~CFtBase(void); - //--- public methods - static void FtBaseGenerateComplexFFtPlan(const int n,CFtPlan &plan); - static void FtBaseGenerateRealFFtPlan(const int n,CFtPlan &plan); - static void FtBaseGenerateRealFHtPlan(const int n,CFtPlan &plan); - static void FtBaseExecutePlan(double &a[],const int aoffset,const int n,CFtPlan &plan); - static void FtBaseExecutePlanRec(double &a[],const int aoffset,CFtPlan &plan,const int entryoffset,const int stackptr); - static void FtBaseFactorize(const int n,const int tasktype,int &n1,int &n2); - static bool FtBaseIsSmooth(int n); - static int FtBaseFindSmooth(const int n); - static int FtBaseFindSmoothEven(const int n); - static double FtBaseGetFlopEstimate(const int n); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFtBase::CFtBase(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFtBase::~CFtBase(void) - { - - } -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CFtBase::m_ftbaseplanentrysize=8; -const int CFtBase::m_ftbasecffttask=0; -const int CFtBase::m_ftbaserfhttask=1; -const int CFtBase::m_ftbaserffttask=2; -const int CFtBase::m_fftcooleytukeyplan=0; -const int CFtBase::m_fftbluesteinplan=1; -const int CFtBase::m_fftcodeletplan=2; -const int CFtBase::m_fhtcooleytukeyplan=3; -const int CFtBase::m_fhtcodeletplan=4; -const int CFtBase::m_fftrealcooleytukeyplan=5; -const int CFtBase::m_fftemptyplan=6; -const int CFtBase::m_fhtn2plan=999; -const int CFtBase::m_ftbaseupdatetw=4; -const int CFtBase::m_ftbasecodeletrecommended=5; -const double CFtBase::m_ftbaseinefficiencyfactor=1.3; -const int CFtBase::m_ftbasemaxsmoothfactor=5; -//+------------------------------------------------------------------+ -//| This subroutine generates FFT plan - a decomposition of a | -//| N-length FFT to the more simpler operations. Plan consists of the| -//| root entry and the child entries. | -//| Subroutine parameters: | -//| N task size | -//| Output parameters: | -//| Plan plan | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseGenerateComplexFFtPlan(const int n,CFtPlan &plan) - { -//--- create variables - int planarraysize=0; - int plansize=0; - int precomputedsize=0; - int tmpmemsize=0; - int stackmemsize=0; - int stackptr=0; -//--- initialization - planarraysize=1; - plansize=0; - precomputedsize=0; - stackmemsize=0; - stackptr=0; - tmpmemsize=2*n; -//--- allocation - ArrayResizeAL(plan.m_plan,planarraysize); -//--- function call - FtBaseGeneratePlanRec(n,m_ftbasecffttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; -//--- allocation - ArrayResizeAL(plan.m_stackbuf,(int)MathMax(stackmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_tmpbuf,(int)MathMax(tmpmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_precomputed,(int)MathMax(precomputedsize,1)); - stackptr=0; -//--- function call - FtBasePrecomputePlanRec(plan,0,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; - } -//+------------------------------------------------------------------+ -//| Generates real FFT plan | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseGenerateRealFFtPlan(const int n,CFtPlan &plan) - { -//--- create variables - int planarraysize=0; - int plansize=0; - int precomputedsize=0; - int tmpmemsize=0; - int stackmemsize=0; - int stackptr=0; -//--- initialization - planarraysize=1; - plansize=0; - precomputedsize=0; - stackmemsize=0; - stackptr=0; - tmpmemsize=2*n; -//--- allocation - ArrayResizeAL(plan.m_plan,planarraysize); -//--- function call - FtBaseGeneratePlanRec(n,m_ftbaserffttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; -//--- allocation - ArrayResizeAL(plan.m_stackbuf,(int)MathMax(stackmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_tmpbuf,(int)MathMax(tmpmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_precomputed,(int)MathMax(precomputedsize,1)); - stackptr=0; -//--- function call - FtBasePrecomputePlanRec(plan,0,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; - } -//+------------------------------------------------------------------+ -//| Generates real FHT plan | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseGenerateRealFHtPlan(const int n,CFtPlan &plan) - { -//--- create variables - int planarraysize=0; - int plansize=0; - int precomputedsize=0; - int tmpmemsize=0; - int stackmemsize=0; - int stackptr=0; -//--- initialization - planarraysize=1; - plansize=0; - precomputedsize=0; - stackmemsize=0; - stackptr=0; - tmpmemsize=n; -//--- allocation - ArrayResizeAL(plan.m_plan,planarraysize); -//--- function call - FtBaseGeneratePlanRec(n,m_ftbaserfhttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; -//--- allocation - ArrayResizeAL(plan.m_stackbuf,(int)MathMax(stackmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_tmpbuf,(int)MathMax(tmpmemsize,1)); -//--- allocation - ArrayResizeAL(plan.m_precomputed,(int)MathMax(precomputedsize,1)); - stackptr=0; -//--- function call - FtBasePrecomputePlanRec(plan,0,stackptr); -//--- check - if(!CAp::Assert(stackptr==0,__FUNCTION__+": stack ptr!")) - return; - } -//+------------------------------------------------------------------+ -//| This subroutine executes FFT/FHT plan. | -//| If Plan is a: | -//| * complex FFT plan - sizeof(A)=2*N, | -//| A contains interleaved real/imaginary | -//| values | -//| * real FFT plan - sizeof(A)=2*N, | -//| A contains real values interleaved with | -//| zeros | -//| * real FHT plan - sizeof(A)=2*N, | -//| A contains real values interleaved with | -//| zeros | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseExecutePlan(double &a[],const int aoffset, - const int n,CFtPlan &plan) - { -//--- create a variable - int stackptr=0; -//--- function call - FtBaseExecutePlanRec(a,aoffset,plan,0,stackptr); - } -//+------------------------------------------------------------------+ -//| Recurrent subroutine for the FTBaseExecutePlan | -//| Parameters: | -//| A FFT'ed array | -//| AOffset offset of the FFT'ed part (distance is measured | -//| in doubles) | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseExecutePlanRec(double &a[],const int aoffset, - CFtPlan &plan,const int entryoffset, - const int stackptr) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int n1=0; - int n2=0; - int n=0; - int m=0; - int offs=0; - int offs1=0; - int offs2=0; - int offsa=0; - int offsb=0; - int offsp=0; - double hk=0; - double hnk=0; - double x=0; - double y=0; - double bx=0; - double by=0; - double emptyarray[]; - double a0x=0; - double a0y=0; - double a1x=0; - double a1y=0; - double a2x=0; - double a2y=0; - double a3x=0; - double a3y=0; - double v0=0; - double v1=0; - double v2=0; - double v3=0; - double t1x=0; - double t1y=0; - double t2x=0; - double t2y=0; - double t3x=0; - double t3y=0; - double t4x=0; - double t4y=0; - double t5x=0; - double t5y=0; - double m1x=0; - double m1y=0; - double m2x=0; - double m2y=0; - double m3x=0; - double m3y=0; - double m4x=0; - double m4y=0; - double m5x=0; - double m5y=0; - double s1x=0; - double s1y=0; - double s2x=0; - double s2y=0; - double s3x=0; - double s3y=0; - double s4x=0; - double s4y=0; - double s5x=0; - double s5y=0; - double c1=0; - double c2=0; - double c3=0; - double c4=0; - double c5=0; - double tmp[]; - int i_=0; - int i1_=0; -//--- check - if(plan.m_plan[entryoffset+3]==m_fftemptyplan) - return; -//--- check - if(plan.m_plan[entryoffset+3]==m_fftcooleytukeyplan) - { - //--- Cooley-Tukey plan - //--- * transposition - //--- * row-wise FFT - //--- * twiddle factors: - //--- - TwBase is a basis twiddle factor for I=1,J=1 - //--- - TwRow is a twiddle factor for a second element in a row (J=1) - //--- - Tw is a twiddle factor for a current element - //--- * transposition again - //--- * row-wise FFT again - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - //--- function call - InternalComplexLinTranspose(a,n1,n2,aoffset,plan.m_tmpbuf); - for(i=0;i<=n2-1;i++) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+i*n1*2,plan,plan.m_plan[entryoffset+5],stackptr); - } - //--- function call - FFtTwCalc(a,aoffset,n1,n2); - //--- function call - InternalComplexLinTranspose(a,n2,n1,aoffset,plan.m_tmpbuf); - for(i=0;i<=n1-1;i++) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+i*n2*2,plan,plan.m_plan[entryoffset+6],stackptr); - } - //--- function call - InternalComplexLinTranspose(a,n1,n2,aoffset,plan.m_tmpbuf); - //--- exit the function - return; - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fftrealcooleytukeyplan) - { - //--- Cooley-Tukey plan - //--- * transposition - //--- * row-wise FFT - //--- * twiddle factors: - //--- - TwBase is a basis twiddle factor for I=1,J=1 - //--- - TwRow is a twiddle factor for a second element in a row (J=1) - //--- - Tw is a twiddle factor for a current element - //--- * transposition again - //--- * row-wise FFT again - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - //--- function call - InternalComplexLinTranspose(a,n2,n1,aoffset,plan.m_tmpbuf); - for(i=0;i<=n1/2-1;i++) - { - //--- pack two adjacent smaller real FFT's together, - //--- make one complex FFT, - //--- unpack result - offs=aoffset+2*i*n2*2; - for(k=0;k<=n2-1;k++) - a[offs+2*k+1]=a[offs+2*n2+2*k+0]; - //--- function call - FtBaseExecutePlanRec(a,offs,plan,plan.m_plan[entryoffset+6],stackptr); - //--- change values - plan.m_tmpbuf[0]=a[offs+0]; - plan.m_tmpbuf[1]=0; - plan.m_tmpbuf[2*n2+0]=a[offs+1]; - plan.m_tmpbuf[2*n2+1]=0; - for(k=1;k<=n2-1;k++) - { - //--- change values - offs1=2*k; - offs2=2*n2+2*k; - hk=a[offs+2*k+0]; - hnk=a[offs+2*(n2-k)+0]; - plan.m_tmpbuf[offs1+0]=0.5*(hk+hnk); - plan.m_tmpbuf[offs2+1]=-(0.5*(hk-hnk)); - hk=a[offs+2*k+1]; - hnk=a[offs+2*(n2-k)+1]; - plan.m_tmpbuf[offs2+0]=0.5*(hk+hnk); - plan.m_tmpbuf[offs1+1]=0.5*(hk-hnk); - } - i1_=-offs; - for(i_=offs;i_<=offs+2*n2*2-1;i_++) - a[i_]=plan.m_tmpbuf[i_+i1_]; - } - //--- check - if(n1%2!=0) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+(n1-1)*n2*2,plan,plan.m_plan[entryoffset+6],stackptr); - } - //--- function call - FFtTwCalc(a,aoffset,n2,n1); - //--- function call - InternalComplexLinTranspose(a,n1,n2,aoffset,plan.m_tmpbuf); - for(i=0;i<=n2-1;i++) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+i*n1*2,plan,plan.m_plan[entryoffset+5],stackptr); - } - //--- function call - InternalComplexLinTranspose(a,n2,n1,aoffset,plan.m_tmpbuf); - //--- exit the function - return; - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fhtcooleytukeyplan) - { - //--- Cooley-Tukey FHT plan: - //--- * transpose \ - //--- * smaller FHT's | - //--- * pre-process | - //--- * multiply by twiddle factors | corresponds to multiplication by H1 - //--- * post-process | - //--- * transpose again / - //--- * multiply by H2 (smaller FHT's) - //--- * final transposition - //--- For more details see Vitezslav Vesely,"Fast algorithms - //--- of Fourier and Hartley transform and their implementation in MATLAB", - //--- page 31. - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - n=n1*n2; - //--- function call - InternalRealLinTranspose(a,n1,n2,aoffset,plan.m_tmpbuf); - for(i=0;i<=n2-1;i++) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+i*n1,plan,plan.m_plan[entryoffset+5],stackptr); - } - for(i=0;i<=n2-1;i++) - { - for(j=0;j<=n1-1;j++) - { - //--- change values - offsa=aoffset+i*n1; - hk=a[offsa+j]; - hnk=a[offsa+(n1-j)%n1]; - offs=2*(i*n1+j); - plan.m_tmpbuf[offs+0]=-(0.5*(hnk-hk)); - plan.m_tmpbuf[offs+1]=0.5*(hk+hnk); - } - } - //--- function call - FFtTwCalc(plan.m_tmpbuf,0,n1,n2); - for(j=0;j<=n1-1;j++) - a[aoffset+j]=plan.m_tmpbuf[2*j+0]+plan.m_tmpbuf[2*j+1]; - //--- check - if(n2%2==0) - { - offs=2*(n2/2)*n1; - offsa=aoffset+n2/2*n1; - for(j=0;j<=n1-1;j++) - a[offsa+j]=plan.m_tmpbuf[offs+2*j+0]+plan.m_tmpbuf[offs+2*j+1]; - } - for(i=1;i<=(n2+1)/2-1;i++) - { - //--- change values - offs=2*i*n1; - offs2=2*(n2-i)*n1; - offsa=aoffset+i*n1; - for(j=0;j<=n1-1;j++) - a[offsa+j]=plan.m_tmpbuf[offs+2*j+1]+plan.m_tmpbuf[offs2+2*j+0]; - offsa=aoffset+(n2-i)*n1; - for(j=0;j<=n1-1;j++) - a[offsa+j]=plan.m_tmpbuf[offs+2*j+0]+plan.m_tmpbuf[offs2+2*j+1]; - } - //--- function call - InternalRealLinTranspose(a,n2,n1,aoffset,plan.m_tmpbuf); - for(i=0;i<=n1-1;i++) - { - //--- function call - FtBaseExecutePlanRec(a,aoffset+i*n2,plan,plan.m_plan[entryoffset+6],stackptr); - } - //--- function call - InternalRealLinTranspose(a,n1,n2,aoffset,plan.m_tmpbuf); - //--- exit the function - return; - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fhtn2plan) - { - //--- Cooley-Tukey FHT plan - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - n=n1*n2; - ReFFHt(a,n,aoffset); - //--- exit the function - return; - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fftcodeletplan) - { - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - n=n1*n2; - //--- check - if(n==2) - { - //--- change values - a0x=a[aoffset+0]; - a0y=a[aoffset+1]; - a1x=a[aoffset+2]; - a1y=a[aoffset+3]; - v0=a0x+a1x; - v1=a0y+a1y; - v2=a0x-a1x; - v3=a0y-a1y; - a[aoffset+0]=v0; - a[aoffset+1]=v1; - a[aoffset+2]=v2; - a[aoffset+3]=v3; - //--- exit the function - return; - } - //--- check - if(n==3) - { - //--- change values - offs=plan.m_plan[entryoffset+7]; - c1=plan.m_precomputed[offs+0]; - c2=plan.m_precomputed[offs+1]; - a0x=a[aoffset+0]; - a0y=a[aoffset+1]; - a1x=a[aoffset+2]; - a1y=a[aoffset+3]; - a2x=a[aoffset+4]; - a2y=a[aoffset+5]; - t1x=a1x+a2x; - t1y=a1y+a2y; - a0x=a0x+t1x; - a0y=a0y+t1y; - m1x=c1*t1x; - m1y=c1*t1y; - m2x=c2*(a1y-a2y); - m2y=c2*(a2x-a1x); - s1x=a0x+m1x; - s1y=a0y+m1y; - a1x=s1x+m2x; - a1y=s1y+m2y; - a2x=s1x-m2x; - a2y=s1y-m2y; - a[aoffset+0]=a0x; - a[aoffset+1]=a0y; - a[aoffset+2]=a1x; - a[aoffset+3]=a1y; - a[aoffset+4]=a2x; - a[aoffset+5]=a2y; - //--- exit the function - return; - } - //--- check - if(n==4) - { - //--- change values - a0x=a[aoffset+0]; - a0y=a[aoffset+1]; - a1x=a[aoffset+2]; - a1y=a[aoffset+3]; - a2x=a[aoffset+4]; - a2y=a[aoffset+5]; - a3x=a[aoffset+6]; - a3y=a[aoffset+7]; - t1x=a0x+a2x; - t1y=a0y+a2y; - t2x=a1x+a3x; - t2y=a1y+a3y; - m2x=a0x-a2x; - m2y=a0y-a2y; - m3x=a1y-a3y; - m3y=a3x-a1x; - a[aoffset+0]=t1x+t2x; - a[aoffset+1]=t1y+t2y; - a[aoffset+4]=t1x-t2x; - a[aoffset+5]=t1y-t2y; - a[aoffset+2]=m2x+m3x; - a[aoffset+3]=m2y+m3y; - a[aoffset+6]=m2x-m3x; - a[aoffset+7]=m2y-m3y; - //--- exit the function - return; - } - //--- check - if(n==5) - { - //--- change values - offs=plan.m_plan[entryoffset+7]; - c1=plan.m_precomputed[offs+0]; - c2=plan.m_precomputed[offs+1]; - c3=plan.m_precomputed[offs+2]; - c4=plan.m_precomputed[offs+3]; - c5=plan.m_precomputed[offs+4]; - t1x=a[aoffset+2]+a[aoffset+8]; - t1y=a[aoffset+3]+a[aoffset+9]; - t2x=a[aoffset+4]+a[aoffset+6]; - t2y=a[aoffset+5]+a[aoffset+7]; - t3x=a[aoffset+2]-a[aoffset+8]; - t3y=a[aoffset+3]-a[aoffset+9]; - t4x=a[aoffset+6]-a[aoffset+4]; - t4y=a[aoffset+7]-a[aoffset+5]; - t5x=t1x+t2x; - t5y=t1y+t2y; - a[aoffset+0]=a[aoffset+0]+t5x; - a[aoffset+1]=a[aoffset+1]+t5y; - m1x=c1*t5x; - m1y=c1*t5y; - m2x=c2*(t1x-t2x); - m2y=c2*(t1y-t2y); - m3x=-(c3*(t3y+t4y)); - m3y=c3*(t3x+t4x); - m4x=-(c4*t4y); - m4y=c4*t4x; - m5x=-(c5*t3y); - m5y=c5*t3x; - s3x=m3x-m4x; - s3y=m3y-m4y; - s5x=m3x+m5x; - s5y=m3y+m5y; - s1x=a[aoffset+0]+m1x; - s1y=a[aoffset+1]+m1y; - s2x=s1x+m2x; - s2y=s1y+m2y; - s4x=s1x-m2x; - s4y=s1y-m2y; - a[aoffset+2]=s2x+s3x; - a[aoffset+3]=s2y+s3y; - a[aoffset+4]=s4x+s5x; - a[aoffset+5]=s4y+s5y; - a[aoffset+6]=s4x-s5x; - a[aoffset+7]=s4y-s5y; - a[aoffset+8]=s2x-s3x; - a[aoffset+9]=s2y-s3y; - //--- exit the function - return; - } - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fhtcodeletplan) - { - //--- change values - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - n=n1*n2; - //--- check - if(n==2) - { - //--- change values - a0x=a[aoffset+0]; - a1x=a[aoffset+1]; - a[aoffset+0]=a0x+a1x; - a[aoffset+1]=a0x-a1x; - //--- exit the function - return; - } - //--- check - if(n==3) - { - //--- change values - offs=plan.m_plan[entryoffset+7]; - c1=plan.m_precomputed[offs+0]; - c2=plan.m_precomputed[offs+1]; - a0x=a[aoffset+0]; - a1x=a[aoffset+1]; - a2x=a[aoffset+2]; - t1x=a1x+a2x; - a0x=a0x+t1x; - m1x=c1*t1x; - m2y=c2*(a2x-a1x); - s1x=a0x+m1x; - a[aoffset+0]=a0x; - a[aoffset+1]=s1x-m2y; - a[aoffset+2]=s1x+m2y; - //--- exit the function - return; - } - //--- check - if(n==4) - { - //--- change values - a0x=a[aoffset+0]; - a1x=a[aoffset+1]; - a2x=a[aoffset+2]; - a3x=a[aoffset+3]; - t1x=a0x+a2x; - t2x=a1x+a3x; - m2x=a0x-a2x; - m3y=a3x-a1x; - a[aoffset+0]=t1x+t2x; - a[aoffset+1]=m2x-m3y; - a[aoffset+2]=t1x-t2x; - a[aoffset+3]=m2x+m3y; - //--- exit the function - return; - } - //--- check - if(n==5) - { - //--- change values - offs=plan.m_plan[entryoffset+7]; - c1=plan.m_precomputed[offs+0]; - c2=plan.m_precomputed[offs+1]; - c3=plan.m_precomputed[offs+2]; - c4=plan.m_precomputed[offs+3]; - c5=plan.m_precomputed[offs+4]; - t1x=a[aoffset+1]+a[aoffset+4]; - t2x=a[aoffset+2]+a[aoffset+3]; - t3x=a[aoffset+1]-a[aoffset+4]; - t4x=a[aoffset+3]-a[aoffset+2]; - t5x=t1x+t2x; - v0=a[aoffset+0]+t5x; - a[aoffset+0]=v0; - m2x=c2*(t1x-t2x); - m3y=c3*(t3x+t4x); - s3y=m3y-c4*t4x; - s5y=m3y+c5*t3x; - s1x=v0+c1*t5x; - s2x=s1x+m2x; - s4x=s1x-m2x; - a[aoffset+1]=s2x-s3y; - a[aoffset+2]=s4x-s5y; - a[aoffset+3]=s4x+s5y; - a[aoffset+4]=s2x+s3y; - //--- exit the function - return; - } - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fftbluesteinplan) - { - //--- Bluestein plan: - //--- 1. multiply by precomputed coefficients - //--- 2. make convolution: forward FFT,multiplication by precomputed FFT - //--- and backward FFT. backward FFT is represented as - //--- invfft(x)=fft(x')'/M - //--- for performance reasons reduction of inverse FFT to - //--- forward FFT is merged with multiplication of FFT components - //--- and last stage of Bluestein's transformation. - //--- 3. post-multiplication by Bluestein factors - n=plan.m_plan[entryoffset+1]; - m=plan.m_plan[entryoffset+4]; - offs=plan.m_plan[entryoffset+7]; - for(i=stackptr+2*n;i<=stackptr+2*m-1;i++) - plan.m_stackbuf[i]=0; - //--- change values - offsp=offs+2*m; - offsa=aoffset; - offsb=stackptr; - for(i=0;i<=n-1;i++) - { - //--- change values - bx=plan.m_precomputed[offsp+0]; - by=plan.m_precomputed[offsp+1]; - x=a[offsa+0]; - y=a[offsa+1]; - plan.m_stackbuf[offsb+0]=x*bx-y*-by; - plan.m_stackbuf[offsb+1]=x*-by+y*bx; - offsp=offsp+2; - offsa=offsa+2; - offsb=offsb+2; - } - //--- function call - FtBaseExecutePlanRec(plan.m_stackbuf,stackptr,plan,plan.m_plan[entryoffset+5],stackptr+2*2*m); - offsb=stackptr; - offsp=offs; - for(i=0;i<=m-1;i++) - { - //--- change values - x=plan.m_stackbuf[offsb+0]; - y=plan.m_stackbuf[offsb+1]; - bx=plan.m_precomputed[offsp+0]; - by=plan.m_precomputed[offsp+1]; - plan.m_stackbuf[offsb+0]=x*bx-y*by; - plan.m_stackbuf[offsb+1]=-(x*by+y*bx); - offsb=offsb+2; - offsp=offsp+2; - } - //--- function call - FtBaseExecutePlanRec(plan.m_stackbuf,stackptr,plan,plan.m_plan[entryoffset+5],stackptr+2*2*m); - offsb=stackptr; - offsp=offs+2*m; - offsa=aoffset; - for(i=0;i<=n-1;i++) - { - //--- change values - x=plan.m_stackbuf[offsb+0]/m; - y=-(plan.m_stackbuf[offsb+1]/m); - bx=plan.m_precomputed[offsp+0]; - by=plan.m_precomputed[offsp+1]; - a[offsa+0]=x*bx-y*-by; - a[offsa+1]=x*-by+y*bx; - offsp=offsp+2; - offsa=offsa+2; - offsb=offsb+2; - } - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| Returns good factorization N=N1*N2. | -//| Usually N1<=N2 (but not always - small N's may be exception). | -//| if N1<>1 then N2<>1. | -//| Factorization is chosen depending on task type and codelets we | -//| have. | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseFactorize(const int n,const int tasktype, - int &n1,int &n2) - { -//--- create a variable - int j=0; -//--- initialization - n1=0; - n2=0; -//--- try to find good codelet - if(n1*n2!=n) - { - for(j=m_ftbasecodeletrecommended;j>=2;j--) - { - //--- check - if(n%j==0) - { - n1=j; - n2=n/j; - break; - } - } - } -//--- try to factorize N - if(n1*n2!=n) - { - for(j=m_ftbasecodeletrecommended+1;j<=n-1;j++) - { - //--- check - if(n%j==0) - { - n1=j; - n2=n/j; - break; - } - } - } -//--- looks like N is prime :( - if(n1*n2!=n) - { - n1=1; - n2=n; - } -//--- normalize - if(n2==1 && n1!=1) - { - n2=n1; - n1=1; - } - } -//+------------------------------------------------------------------+ -//| Is number smooth? | -//+------------------------------------------------------------------+ -static bool CFtBase::FtBaseIsSmooth(int n) - { -//--- create a variable - int i=0; -//--- change n - for(i=2;i<=m_ftbasemaxsmoothfactor;i++) - { - while(n%i==0) - n=n/i; - } -//--- check - if(n==1) - return(true); -//--- return result - return(false); - } -//+------------------------------------------------------------------+ -//| Returns smallest smooth (divisible only by 2, 3, 5) number that | -//| is greater than or equal to max(N,2) | -//+------------------------------------------------------------------+ -static int CFtBase::FtBaseFindSmooth(const int n) - { -//--- create a variable - int best=0; -//--- calculation - best=2; - while(bestplanarraysize) - FFtArrayResize(plan.m_plan,planarraysize,8*planarraysize); - entryoffset=plansize; - esize=m_ftbaseplanentrysize; - plansize=plansize+esize; -//--- if N=1,generate empty plan and exit - if(n==1) - { - //--- change values - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=-1; - plan.m_plan[entryoffset+2]=-1; - plan.m_plan[entryoffset+3]=m_fftemptyplan; - plan.m_plan[entryoffset+4]=-1; - plan.m_plan[entryoffset+5]=-1; - plan.m_plan[entryoffset+6]=-1; - plan.m_plan[entryoffset+7]=-1; - //--- exit the function - return; - } -//--- generate plans - FtBaseFactorize(n,tasktype,n1,n2); -//--- check - if(tasktype==m_ftbasecffttask || tasktype==m_ftbaserffttask) - { - //--- complex FFT plans - if(n1!=1) - { - //--- Cooley-Tukey plan (real or complex) - //--- Note that child plans are COMPLEX - //--- (whether plan itself is complex or not). - tmpmemsize=MathMax(tmpmemsize,2*n1*n2); - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n1; - plan.m_plan[entryoffset+2]=n2; - //--- check - if(tasktype==m_ftbasecffttask) - plan.m_plan[entryoffset+3]=m_fftcooleytukeyplan; - else - plan.m_plan[entryoffset+3]=m_fftrealcooleytukeyplan; - plan.m_plan[entryoffset+4]=0; - plan.m_plan[entryoffset+5]=plansize; - //--- function call - FtBaseGeneratePlanRec(n1,m_ftbasecffttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); - plan.m_plan[entryoffset+6]=plansize; - //--- function call - FtBaseGeneratePlanRec(n2,m_ftbasecffttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); - plan.m_plan[entryoffset+7]=-1; - //--- exit the function - return; - } - else - { - //--- check - if(((n==2 || n==3) || n==4) || n==5) - { - //--- hard-coded plan - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n1; - plan.m_plan[entryoffset+2]=n2; - plan.m_plan[entryoffset+3]=m_fftcodeletplan; - plan.m_plan[entryoffset+4]=0; - plan.m_plan[entryoffset+5]=-1; - plan.m_plan[entryoffset+6]=-1; - plan.m_plan[entryoffset+7]=precomputedsize; - //--- check - if(n==3) - precomputedsize=precomputedsize+2; - //--- check - if(n==5) - precomputedsize=precomputedsize+5; - //--- exit the function - return; - } - else - { - //--- Bluestein's plan - //--- Select such M that M>=2*N-1,M is composite,and M's - //--- factors are 2,3,5 - k=2*n2-1; - m=FtBaseFindSmooth(k); - tmpmemsize=MathMax(tmpmemsize,2*m); - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n2; - plan.m_plan[entryoffset+2]=-1; - plan.m_plan[entryoffset+3]=m_fftbluesteinplan; - plan.m_plan[entryoffset+4]=m; - plan.m_plan[entryoffset+5]=plansize; - stackptr=stackptr+2*2*m; - stackmemsize=MathMax(stackmemsize,stackptr); - //--- function call - FtBaseGeneratePlanRec(m,m_ftbasecffttask,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); - stackptr=stackptr-2*2*m; - plan.m_plan[entryoffset+6]=-1; - plan.m_plan[entryoffset+7]=precomputedsize; - precomputedsize=precomputedsize+2*m+2*n; - //--- exit the function - return; - } - } - } -//--- check - if(tasktype==m_ftbaserfhttask) - { - //--- real FHT plans - if(n1!=1) - { - //--- Cooley-Tukey plan - tmpmemsize=MathMax(tmpmemsize,2*n1*n2); - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n1; - plan.m_plan[entryoffset+2]=n2; - plan.m_plan[entryoffset+3]=m_fhtcooleytukeyplan; - plan.m_plan[entryoffset+4]=0; - plan.m_plan[entryoffset+5]=plansize; - //--- function call - FtBaseGeneratePlanRec(n1,tasktype,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); - plan.m_plan[entryoffset+6]=plansize; - //--- function call - FtBaseGeneratePlanRec(n2,tasktype,plan,plansize,precomputedsize,planarraysize,tmpmemsize,stackmemsize,stackptr); - plan.m_plan[entryoffset+7]=-1; - //--- exit the function - return; - } - else - { - //--- N2 plan - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n1; - plan.m_plan[entryoffset+2]=n2; - plan.m_plan[entryoffset+3]=m_fhtn2plan; - plan.m_plan[entryoffset+4]=0; - plan.m_plan[entryoffset+5]=-1; - plan.m_plan[entryoffset+6]=-1; - plan.m_plan[entryoffset+7]=-1; - //--- check - if(((n==2 || n==3) || n==4) || n==5) - { - //--- hard-coded plan - plan.m_plan[entryoffset+0]=esize; - plan.m_plan[entryoffset+1]=n1; - plan.m_plan[entryoffset+2]=n2; - plan.m_plan[entryoffset+3]=m_fhtcodeletplan; - plan.m_plan[entryoffset+4]=0; - plan.m_plan[entryoffset+5]=-1; - plan.m_plan[entryoffset+6]=-1; - plan.m_plan[entryoffset+7]=precomputedsize; - //--- check - if(n==3) - precomputedsize=precomputedsize+2; - //--- check - if(n==5) - precomputedsize=precomputedsize+5; - //--- exit the function - return; - } - //--- exit the function - return; - } - } - } -//+------------------------------------------------------------------+ -//| Recurrent subroutine for precomputing FFT plans | -//+------------------------------------------------------------------+ -static void CFtBase::FtBasePrecomputePlanRec(CFtPlan &plan,const int entryoffset, - const int stackptr) - { -//--- create variables - int i=0; - int n1=0; - int n2=0; - int n=0; - int m=0; - int offs=0; - double v=0; - double emptyarray[]; - double bx=0; - double by=0; -//--- check - if((plan.m_plan[entryoffset+3]==m_fftcooleytukeyplan || plan.m_plan[entryoffset+3]==m_fftrealcooleytukeyplan) || plan.m_plan[entryoffset+3]==m_fhtcooleytukeyplan) - { - //--- function call - FtBasePrecomputePlanRec(plan,plan.m_plan[entryoffset+5],stackptr); - //--- function call - FtBasePrecomputePlanRec(plan,plan.m_plan[entryoffset+6],stackptr); - //--- exit the function - return; - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fftcodeletplan || plan.m_plan[entryoffset+3]==m_fhtcodeletplan) - { - n1=plan.m_plan[entryoffset+1]; - n2=plan.m_plan[entryoffset+2]; - n=n1*n2; - //--- check - if(n==3) - { - offs=plan.m_plan[entryoffset+7]; - plan.m_precomputed[offs+0]=MathCos(2*M_PI/3)-1; - plan.m_precomputed[offs+1]=MathSin(2*M_PI/3); - //--- exit the function - return; - } - //--- check - if(n==5) - { - offs=plan.m_plan[entryoffset+7]; - v=2*M_PI/5; - plan.m_precomputed[offs+0]=(MathCos(v)+MathCos(2*v))/2-1; - plan.m_precomputed[offs+1]=(MathCos(v)-MathCos(2*v))/2; - plan.m_precomputed[offs+2]=-MathSin(v); - plan.m_precomputed[offs+3]=-(MathSin(v)+MathSin(2*v)); - plan.m_precomputed[offs+4]=MathSin(v)-MathSin(2*v); - //--- exit the function - return; - } - } -//--- check - if(plan.m_plan[entryoffset+3]==m_fftbluesteinplan) - { - //--- function call - FtBasePrecomputePlanRec(plan,plan.m_plan[entryoffset+5],stackptr); - n=plan.m_plan[entryoffset+1]; - m=plan.m_plan[entryoffset+4]; - offs=plan.m_plan[entryoffset+7]; - for(i=0;i<=2*m-1;i++) - plan.m_precomputed[offs+i]=0; - //--- change values - for(i=0;i<=n-1;i++) - { - bx=MathCos(M_PI*CMath::Sqr(i)/n); - by=MathSin(M_PI*CMath::Sqr(i)/n); - plan.m_precomputed[offs+2*i+0]=bx; - plan.m_precomputed[offs+2*i+1]=by; - plan.m_precomputed[offs+2*m+2*i+0]=bx; - plan.m_precomputed[offs+2*m+2*i+1]=by; - //--- check - if(i>0) - { - plan.m_precomputed[offs+2*(m-i)+0]=bx; - plan.m_precomputed[offs+2*(m-i)+1]=by; - } - } - //--- function call - FtBaseExecutePlanRec(plan.m_precomputed,offs,plan,plan.m_plan[entryoffset+5],stackptr); - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| Twiddle factors calculation | -//+------------------------------------------------------------------+ -static void CFtBase::FFtTwCalc(double &a[],const int aoffset,const int n1, - const int n2) - { -//--- create variables - int i=0; - int j=0; - int n=0; - int idx=0; - int offs=0; - double x=0; - double y=0; - double twxm1=0; - double twy=0; - double twbasexm1=0; - double twbasey=0; - double twrowxm1=0; - double twrowy=0; - double tmpx=0; - double tmpy=0; - double v=0; -//--- initialization - n=n1*n2; - v=-(2*M_PI/n); - twbasexm1=-(2*CMath::Sqr(MathSin(0.5*v))); - twbasey=MathSin(v); - twrowxm1=0; - twrowy=0; -//--- calculation - for(i=0;i<=n2-1;i++) - { - twxm1=0; - twy=0; - for(j=0;j<=n1-1;j++) - { - //--- change values - idx=i*n1+j; - offs=aoffset+2*idx; - x=a[offs+0]; - y=a[offs+1]; - tmpx=x*twxm1-y*twy; - tmpy=x*twy+y*twxm1; - a[offs+0]=x+tmpx; - a[offs+1]=y+tmpy; - //--- update Tw: Tw(new)=Tw(old)*TwRow - if(jm) - { - //--- New partition: - //--- "A^T -> B" becomes "(A1 A2)^T -> ( B1 ) - //--- ( B2 ) - n1=n/2; - //--- check - if(n-n1>=8 && n1%8!=0) - n1=n1+(8-n1%8); - //--- check - if(!CAp::Assert(n-n1>0)) - return; - //--- function call - FFtICLTRec(a,astart,astride,b,bstart,bstride,m,n1); - //--- function call - FFtICLTRec(a,astart+2*n1,astride,b,bstart+2*n1*bstride,bstride,m,n-n1); - } - else - { - //--- New partition: - //--- "A^T -> B" becomes "( A1 )^T -> ( B1 B2 ) - //--- ( A2 ) - m1=m/2; - //--- check - if(m-m1>=8 && m1%8!=0) - m1=m1+(8-m1%8); - //--- check - if(!CAp::Assert(m-m1>0)) - return; - //--- function call - FFtICLTRec(a,astart,astride,b,bstart,bstride,m1,n); - //--- function call - FFtICLTRec(a,astart+2*m1*astride,astride,b,bstart+2*m1,bstride,m-m1,n); - } - } -//+------------------------------------------------------------------+ -//| Recurrent subroutine for a InternalRealLinTranspose | -//+------------------------------------------------------------------+ -static void CFtBase::FFtIRLTRec(double &a[],const int astart,const int astride, - double &b[],const int bstart,const int bstride, - const int m,const int n) - { -//--- create variables - int i=0; - int j=0; - int idx1=0; - int idx2=0; - int m1=0; - int n1=0; -//--- check - if(m==0 || n==0) - return; -//--- check - if(MathMax(m,n)<=8) - { - for(i=0;i<=m-1;i++) - { - //--- calculation - idx1=bstart+i; - idx2=astart+i*astride; - for(j=0;j<=n-1;j++) - { - b[idx1]=a[idx2]; - idx1=idx1+bstride; - idx2=idx2+1; - } - } - //--- exit the function - return; - } -//--- check - if(n>m) - { - //--- New partition: - //--- "A^T -> B" becomes "(A1 A2)^T -> ( B1 ) - //--- ( B2 ) - n1=n/2; - //--- check - if(n-n1>=8 && n1%8!=0) - n1=n1+(8-n1%8); - //--- check - if(!CAp::Assert(n-n1>0)) - return; - //--- function call - FFtIRLTRec(a,astart,astride,b,bstart,bstride,m,n1); - //--- function call - FFtIRLTRec(a,astart+n1,astride,b,bstart+n1*bstride,bstride,m,n-n1); - } - else - { - //--- New partition: - //--- "A^T -> B" becomes "( A1 )^T -> ( B1 B2 ) - //--- ( A2 ) - m1=m/2; - //--- check - if(m-m1>=8 && m1%8!=0) - m1=m1+(8-m1%8); - //--- check - if(!CAp::Assert(m-m1>0)) - return; - //--- function call - FFtIRLTRec(a,astart,astride,b,bstart,bstride,m1,n); - //--- function call - FFtIRLTRec(a,astart+m1*astride,astride,b,bstart+m1,bstride,m-m1,n); - } - } -//+------------------------------------------------------------------+ -//| recurrent subroutine for FFTFindSmoothRec | -//+------------------------------------------------------------------+ -static void CFtBase::FtBaseFindSmoothRec(const int n,const int seed, - const int leastfactor,int &best) - { -//--- check - if(!CAp::Assert(m_ftbasemaxsmoothfactor<=5,__FUNCTION__+": internal error!")) - return; -//--- check - if(seed>=n) - { - best=MathMin(best,seed); - return; - } -//--- check - if(leastfactor<=2) - { - //--- function call - FtBaseFindSmoothRec(n,seed*2,2,best); - } -//--- check - if(leastfactor<=3) - { - //--- function call - FtBaseFindSmoothRec(n,seed*3,3,best); - } -//--- check - if(leastfactor<=5) - { - //--- function call - FtBaseFindSmoothRec(n,seed*5,5,best); - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine: array resize | -//+------------------------------------------------------------------+ -static void CFtBase::FFtArrayResize(int &a[],int &asize,const int newasize) - { -//--- create variables - int tmp[]; - int i=0; -//--- allocation - ArrayResizeAL(tmp,asize); - for(i=0;i<=asize-1;i++) - tmp[i]=a[i]; -//--- allocation - ArrayResizeAL(a,newasize); - for(i=0;i<=asize-1;i++) - a[i]=tmp[i]; -//--- get result - asize=newasize; - } -//+------------------------------------------------------------------+ -//| Reference FHT stub | -//+------------------------------------------------------------------+ -static void CFtBase::ReFFHt(double &a[],const int n,const int offs) - { -//--- create array - double buf[]; -//--- create variables - int i=0; - int j=0; - double v=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- allocation - ArrayResizeAL(buf,n); -//--- calculation - for(i=0;i<=n-1;i++) - { - v=0; - for(j=0;j<=n-1;j++) - v=v+a[offs+j]*(MathCos(2*M_PI*i*j/n)+MathSin(2*M_PI*i*j/n)); - buf[i]=v; - } -//--- get result - for(i=0;i<=n-1;i++) - a[offs+i]=buf[i]; - } -//+------------------------------------------------------------------+ -//| Auxiliary class for calculation mathematical functions | -//+------------------------------------------------------------------+ -class CNearUnitYUnit - { -public: - //--- constructor, destructor - CNearUnitYUnit(void); - ~CNearUnitYUnit(void); - //--- methods - static double NULog1p(const double x); - static double NUExp1m(const double x); - static double NUCos1m(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNearUnitYUnit::CNearUnitYUnit(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNearUnitYUnit::~CNearUnitYUnit(void) - { - - } -//+------------------------------------------------------------------+ -//| Log | -//+------------------------------------------------------------------+ -static double CNearUnitYUnit::NULog1p(const double x) - { -//--- create variables - double z=1.0+x; - double lp=0; - double lq=0; -//--- check - if(z<0.70710678118654752440 || z>1.41421356237309504880) - return(MathLog(z)); -//--- calculation result - z=x*x; - lp=4.5270000862445199635215E-5; - lp=lp*x+4.9854102823193375972212E-1; - lp=lp*x+6.5787325942061044846969E0; - lp=lp*x+2.9911919328553073277375E1; - lp=lp*x+6.0949667980987787057556E1; - lp=lp*x+5.7112963590585538103336E1; - lp=lp*x+2.0039553499201281259648E1; - lq=1.0000000000000000000000E0; - lq=lq*x+1.5062909083469192043167E1; - lq=lq*x+8.3047565967967209469434E1; - lq=lq*x+2.2176239823732856465394E2; - lq=lq*x+3.0909872225312059774938E2; - lq=lq*x+2.1642788614495947685003E2; - lq=lq*x+6.0118660497603843919306E1; - z=-(0.5*z)+x*(z*lp/lq); -//--- return result - return(x+z); - } -//+------------------------------------------------------------------+ -//| Exp | -//+------------------------------------------------------------------+ -static double CNearUnitYUnit::NUExp1m(const double x) - { -//--- create variables - double r; - double xx; - double ep; - double eq; -//--- check - if(x<-0.5 || x>0.5) - return(MathExp(x)-1.0); -//--- calculation result - xx=x*x; - ep=1.2617719307481059087798E-4; - ep=ep*xx+3.0299440770744196129956E-2; - ep=ep*xx+9.9999999999999999991025E-1; - eq=3.0019850513866445504159E-6; - eq=eq*xx+2.5244834034968410419224E-3; - eq=eq*xx+2.2726554820815502876593E-1; - eq=eq*xx+2.0000000000000000000897E0; - r=x*ep; - r=r/(eq-r); -//--- return result - return(r+r); - } -//+------------------------------------------------------------------+ -//| Cos | -//+------------------------------------------------------------------+ -static double CNearUnitYUnit::NUCos1m(const double x) - { -//--- create variables - double xx; - double c; -//--- check - if(x<-0.25*M_PI || x>0.25*M_PI) - return(MathCos(x)-1); -//--- get result - xx=x*x; - c=4.7377507964246204691685E-14; - c=c*xx-1.1470284843425359765671E-11; - c=c*xx+2.0876754287081521758361E-9; - c=c*xx-2.7557319214999787979814E-7; - c=c*xx+2.4801587301570552304991E-5; - c=c*xx-1.3888888888888872993737E-3; - c=c*xx+4.1666666666666666609054E-2; -//--- return result - return(-(0.5*xx)+xx*xx*c); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/alglibmisc.mqh b/Include/Math/Alglib/alglibmisc.mqh deleted file mode 100644 index 3d7bf4a..0000000 --- a/Include/Math/Alglib/alglibmisc.mqh +++ /dev/null @@ -1,1493 +0,0 @@ -//+------------------------------------------------------------------+ -//| alglibmisc.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "ap.mqh" -#include "alglibinternal.mqh" -//+------------------------------------------------------------------+ -//| KD-trees | -//+------------------------------------------------------------------+ -class CKDTree - { -public: - int m_n; - int m_nx; - int m_ny; - int m_normtype; - int m_kneeded; - double m_rneeded; - bool m_selfmatch; - double m_approxf; - int m_kcur; - double m_curdist; - int m_debugcounter; - //--- arrays - int m_tags[]; - double m_boxmin[]; - double m_boxmax[]; - int m_nodes[]; - double m_splits[]; - double m_x[]; - int m_idx[]; - double m_r[]; - double m_buf[]; - double m_curboxmin[]; - double m_curboxmax[]; - //--- matrix - CMatrixDouble m_xy; - //--- constructor, destructor - CKDTree(void); - ~CKDTree(void); - //--- copy - void Copy(CKDTree &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CKDTree::CKDTree(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CKDTree::~CKDTree(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CKDTree::Copy(CKDTree &obj) - { -//--- copy variables - m_n=obj.m_n; - m_nx=obj.m_nx; - m_ny=obj.m_ny; - m_normtype=obj.m_normtype; - m_kneeded=obj.m_kneeded; - m_rneeded=obj.m_rneeded; - m_selfmatch=obj.m_selfmatch; - m_approxf=obj.m_approxf; - m_kcur=obj.m_kcur; - m_curdist=obj.m_curdist; - m_debugcounter=obj.m_debugcounter; -//--- copy arrays - ArrayCopy(m_tags,obj.m_tags); - ArrayCopy(m_boxmin,obj.m_boxmin); - ArrayCopy(m_boxmax,obj.m_boxmax); - ArrayCopy(m_nodes,obj.m_nodes); - ArrayCopy(m_splits,obj.m_splits); - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_idx,obj.m_idx); - ArrayCopy(m_r,obj.m_r); - ArrayCopy(m_buf,obj.m_buf); - ArrayCopy(m_curboxmin,obj.m_curboxmin); - ArrayCopy(m_curboxmax,obj.m_curboxmax); -//--- copy matrix - m_xy=obj.m_xy; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CKDTree | -//+------------------------------------------------------------------+ -class CKDTreeShell - { -private: - CKDTree m_innerobj; -public: - //--- constructors, destructor - CKDTreeShell(void); - CKDTreeShell(CKDTree &obj); - ~CKDTreeShell(void); - //--- method - CKDTree *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CKDTreeShell::CKDTreeShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -CKDTreeShell::CKDTreeShell(CKDTree &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CKDTreeShell::~CKDTreeShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of CKDTree | -//+------------------------------------------------------------------+ -CKDTree *CKDTreeShell::GetInnerObj(void) - { - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Build KD-trees | -//+------------------------------------------------------------------+ -class CNearestNeighbor - { -public: - //--- class constants - static const int m_splitnodesize; - static const int m_kdtreefirstversion; - //--- constructor, destructor - CNearestNeighbor(void); - ~CNearestNeighbor(void); - //--- build - static void KDTreeBuild(CMatrixDouble &xy,const int n,const int nx,const int ny,const int normtype,CKDTree &kdt); - static void KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],const int n,const int nx,const int ny,const int normtype,CKDTree &kdt); - static int KDTreeQueryKNN(CKDTree &kdt,double &x[],const int k,const bool selfmatch); - static int KDTreeQueryRNN(CKDTree &kdt,double &x[],const double r,const bool selfmatch); - static int KDTreeQueryAKNN(CKDTree &kdt,double &x[],int k,const bool selfmatch,const double eps); - static void KDTreeQueryResultsX(CKDTree &kdt,CMatrixDouble &x); - static void KDTreeQueryResultsXY(CKDTree &kdt,CMatrixDouble &xy); - static void KDTreeQueryResultsTags(CKDTree &kdt,int &tags[]); - static void KDTreeQueryResultsDistances(CKDTree &kdt,double &r[]); - static void KDTreeQueryResultsXI(CKDTree &kdt,CMatrixDouble &x); - static void KDTreeQueryResultsXYI(CKDTree &kdt,CMatrixDouble &xy); - static void KDTreeQueryResultsTagsI(CKDTree &kdt,int &tags[]); - static void KDTreeQueryResultsDistancesI(CKDTree &kdt,double &r[]); - //--- serialize - static void KDTreeAlloc(CSerializer &s,CKDTree &tree); - static void KDTreeSerialize(CSerializer &s,CKDTree &tree); - static void KDTreeUnserialize(CSerializer &s,CKDTree &tree); -private: - //--- private methods - static void KDTreeSplit(CKDTree &kdt,const int i1,const int i2,const int d,const double s,int &i3); - static void KDTreeGenerateTreeRec(CKDTree &kdt,int &nodesoffs,int &splitsoffs,const int i1,const int i2,const int maxleafsize); - static void KDTreeQueryNNRec(CKDTree &kdt,const int offs); - static void KDTreeInitBox(CKDTree &kdt,double &x[]); - static void KDTreeAllocDataSetIndependent(CKDTree &kdt,const int nx,const int ny); - static void KDTreeAllocDataSetDependent(CKDTree &kdt,const int n,const int nx,const int ny); - static void KDTreeAllocTemporaries(CKDTree &kdt,const int n,const int nx,const int ny); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CNearestNeighbor::m_splitnodesize=6; -const int CNearestNeighbor::m_kdtreefirstversion=0; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNearestNeighbor::CNearestNeighbor(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNearestNeighbor::~CNearestNeighbor(void) - { - - } -//+------------------------------------------------------------------+ -//| KD-tree creation | -//| This subroutine creates KD-tree from set of X-values and optional| -//| Y-values | -//| INPUT PARAMETERS | -//| XY - dataset, array[0..N-1,0..NX+NY-1]. | -//| one row corresponds to one point. | -//| first NX columns contain X-values, next NY (NY | -//| may be zero) | -//| columns may contain associated Y-values | -//| N - number of points, N>=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because | -//| simple binary search (without additional structures) is | -//| much more efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeBuild(CMatrixDouble &xy,const int n, - const int nx,const int ny, - const int normtype,CKDTree &kdt) - { -//--- create a variable - int i=0; -//--- creating array - int tags[]; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(nx>=1,__FUNCTION__+": NX<1!")) - return; -//--- check - if(!CAp::Assert(ny>=0,__FUNCTION__+": NY<0!")) - return; -//--- check - if(!CAp::Assert(normtype>=0&&normtype<=2,__FUNCTION__+": incorrect NormType!")) - return; -//--- check - if(!CAp::Assert(CAp::Rows(xy)>=n,__FUNCTION__+": rows(X)=nx+ny,__FUNCTION__+": cols(X)=1 | -//| NX - space dimension, NX>=1. | -//| NY - number of optional Y-values, NY>=0. | -//| NormType- norm type: | -//| * 0 denotes infinity-norm | -//| * 1 denotes 1-norm | -//| * 2 denotes 2-norm (Euclidean norm) | -//| OUTPUT PARAMETERS | -//| KDT - KD-tree | -//| NOTES | -//| 1. KD-tree creation have O(N*logN) complexity and | -//| O(N*(2*NX+NY)) memory requirements. | -//| 2. Although KD-trees may be used with any combination of N and | -//| NX, they are more efficient than brute-force search only when | -//| N >> 4^NX. So they are most useful in low-dimensional tasks | -//| (NX=2, NX=3). NX=1 is another inefficient case, because simple| -//| binary search (without additional structures) is much more | -//| efficient in such tasks than KD-trees. | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeBuildTagged(CMatrixDouble &xy,int &tags[], - const int n,const int nx, - const int ny, - const int normtype,CKDTree &kdt) - { -//--- create variables - int i=0; - int j=0; - int maxnodes=0; - int nodesoffs=0; - int splitsoffs=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(nx>=1,__FUNCTION__+": NX<1!")) - return; -//--- check - if(!CAp::Assert(ny>=0,__FUNCTION__+": NY<0!")) - return; -//--- check - if(!CAp::Assert(normtype>=0&&normtype<=2,__FUNCTION__+": incorrect NormType!")) - return; -//--- check - if(!CAp::Assert(CAp::Rows(xy)>=n,__FUNCTION__+": rows(X)=nx+ny,__FUNCTION__+": cols(X)=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain these results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CNearestNeighbor::KDTreeQueryKNN(CKDTree &kdt,double &x[], - const int k,const bool selfmatch) - { -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return(-1); -//--- check - if(!CAp::Assert(CAp::Len(x)>=kdt.m_nx,__FUNCTION__+": Length(X)0| -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| RESULT | -//| number of neighbors found, >=0 | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| subroutines to obtain actual results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CNearestNeighbor::KDTreeQueryRNN(CKDTree &kdt,double &x[], - const double r,const bool selfmatch) - { -//--- create variables - int result=0; - int i=0; - int j=0; -//--- check - if(!CAp::Assert((double)(r)>0.0,__FUNCTION__+": incorrect R!")) - return(-1); -//--- check - if(!CAp::Assert(CAp::Len(x)>=kdt.m_nx,__FUNCTION__+": Length(X)=2;i--) - CTSort::TagHeapPopI(kdt.m_r,kdt.m_idx,j); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| K-NN query: approximate K nearest neighbors | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - point, array[0..NX-1]. | -//| K - number of neighbors to return, K>=1 | -//| SelfMatch - whether self-matches are allowed: | -//| * if True, nearest neighbor may be the point | -//| itself (if it exists in original dataset) | -//| * if False, then only points with non-zero | -//| distance are returned | -//| * if not given, considered True | -//| Eps - approximation factor, Eps>=0. eps-approximate| -//| nearest neighbor is a neighbor whose distance| -//| from X is at most (1+eps) times distance of | -//| true nearest neighbor. | -//| RESULT | -//| number of actual neighbors found (either K or N, if K>N). | -//| NOTES | -//| significant performance gain may be achieved only when Eps is| -//| on the order of magnitude of 1 or larger. | -//| This subroutine performs query and stores its result in the | -//| internal structures of the KD-tree. You can use following | -//| these subroutines to obtain results: | -//| * KDTreeQueryResultsX() to get X-values | -//| * KDTreeQueryResultsXY() to get X- and Y-values | -//| * KDTreeQueryResultsTags() to get tag values | -//| * KDTreeQueryResultsDistances() to get distances | -//+------------------------------------------------------------------+ -static int CNearestNeighbor::KDTreeQueryAKNN(CKDTree &kdt,double &x[], - int k,const bool selfmatch, - const double eps) - { -//--- create variables - int result=0; - int i=0; - int j=0; -//--- check - if(!CAp::Assert(k>0,__FUNCTION__+": incorrect K!")) - return(-1); -//--- check - if(!CAp::Assert(eps>=0.0,__FUNCTION__+": incorrect Eps!")) - return(-1); -//--- check - if(!CAp::Assert(CAp::Len(x)>=kdt.m_nx,__FUNCTION__+": Length(X)=2;i--) - CTSort::TagHeapPopI(kdt.m_r,kdt.m_idx,j); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| X-values from last query | -//| INPUT PARAMETERS | -//| KDT - KD-tree | -//| X - possibly pre-allocated buffer. If X is too small | -//| to store result, it is resized. If size(X) is | -//| enough to store result, it is left unchanged. | -//| OUTPUT PARAMETERS | -//| X - rows are filled with X-values | -//| NOTES | -//| 1. points are ordered by distance from the query point (first = | -//| closest) | -//| 2. if XY is larger than required to store result, only leading | -//| part will be overwritten; trailing part will be left | -//| unchanged. So if on input XY = [[A,B],[C,D]], and result is | -//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is | -//| done purposely to increase performance; if you want function | -//| to resize array according to result size, use function with | -//| same name and suffix 'I'. | -//| SEE ALSO | -//| * KDTreeQueryResultsXY() X- and Y-values | -//| * KDTreeQueryResultsTags() tag values | -//| * KDTreeQueryResultsDistances() distances | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeQueryResultsX(CKDTree &kdt,CMatrixDouble &x) - { -//--- create variables - int i=0; - int k=0; - int i_=0; - int i1_=0; -//--- check - if(kdt.m_kcur==0) - return; -//--- check - if(CAp::Rows(x)i1,__FUNCTION__+": internal error")) - return; -//--- Generate leaf if needed - if(i2-i1<=maxleafsize) - { - kdt.m_nodes[nodesoffs+0]=i2-i1; - kdt.m_nodes[nodesoffs+1]=i1; - nodesoffs=nodesoffs+2; - //--- exit the function - return; - } -//--- Load values for easier access - nx=kdt.m_nx; - ny=kdt.m_ny; -//--- select dimension to split: -//--- * D is a dimension number - d=0; - ds=kdt.m_curboxmax[0]-kdt.m_curboxmin[0]; - for(i=1;i<=nx-1;i++) - { - v=kdt.m_curboxmax[i]-kdt.m_curboxmin[i]; - //--- check - if(v>ds) - { - ds=v; - d=i; - } - } -//--- Select split position S using sliding midpoint rule, -//--- rearrange points into [I1,I3) and [I3,I2) - s=kdt.m_curboxmin[d]+0.5*ds; - i1_=(i1) -(0); - for(i_=0;i_<=i2-i1-1;i_++) - kdt.m_buf[i_]=kdt.m_xy[i_+i1_][d]; -//--- change values - n=i2-i1; - cntless=0; - cntgreater=0; - minv=kdt.m_buf[0]; - maxv=kdt.m_buf[0]; - minidx=i1; - maxidx=i1; - for(i=0;i<=n-1;i++) - { - v=kdt.m_buf[i]; - //--- check - if(vmaxv) - { - maxv=v; - maxidx=i1+i; - } - //--- check - if(vs) - cntgreater=cntgreater+1; - } -//--- check - if(cntless>0&&cntgreater>0) - { - //--- normal midpoint split - KDTreeSplit(kdt,i1,i2,d,s,i3); - } - else - { - //--- sliding midpoint - if(cntless==0) - { - //--- 1. move split to MinV, - //--- 2. place one point to the left bin (move to I1), - //--- others - to the right bin - s=minv; - //--- check - if(minidx!=i1) - { - for(i=0;i<=2*kdt.m_nx+kdt.m_ny-1;i++) - { - v=kdt.m_xy[minidx][i]; - kdt.m_xy[minidx].Set(i,kdt.m_xy[i1][i]); - kdt.m_xy[i1].Set(i,v); - } - //--- change values - j=kdt.m_tags[minidx]; - kdt.m_tags[minidx]=kdt.m_tags[i1]; - kdt.m_tags[i1]=j; - } - i3=i1+1; - } - else - { - //--- 1. move split to MaxV, - //--- 2. place one point to the right bin (move to I2-1), - //--- others - to the left bin - s=maxv; - //--- check - if(maxidx!=i2-1) - { - for(i=0;i<=2*kdt.m_nx+kdt.m_ny-1;i++) - { - v=kdt.m_xy[maxidx][i]; - kdt.m_xy[maxidx].Set(i,kdt.m_xy[i2-1][i]); - kdt.m_xy[i2-1].Set(i,v); - } - //--- change values - j=kdt.m_tags[maxidx]; - kdt.m_tags[maxidx]=kdt.m_tags[i2-1]; - kdt.m_tags[i2-1]=j; - } - i3=i2-1; - } - } -//--- Generate 'split' node - kdt.m_nodes[nodesoffs+0]=0; - kdt.m_nodes[nodesoffs+1]=d; - kdt.m_nodes[nodesoffs+2]=splitsoffs; - kdt.m_splits[splitsoffs+0]=s; - oldoffs=nodesoffs; - nodesoffs=nodesoffs+m_splitnodesize; - splitsoffs=splitsoffs+1; -//--- Recirsive generation: -//--- * update CurBox -//--- * call subroutine -//--- * restore CurBox - kdt.m_nodes[oldoffs+3]=nodesoffs; - v=kdt.m_curboxmax[d]; - kdt.m_curboxmax[d]=s; -//--- function call - KDTreeGenerateTreeRec(kdt,nodesoffs,splitsoffs,i1,i3,maxleafsize); - kdt.m_curboxmax[d]=v; - kdt.m_nodes[oldoffs+4]=nodesoffs; - v=kdt.m_curboxmin[d]; - kdt.m_curboxmin[d]=s; -//--- function call - KDTreeGenerateTreeRec(kdt,nodesoffs,splitsoffs,i3,i2,maxleafsize); - kdt.m_curboxmin[d]=v; - } -//+------------------------------------------------------------------+ -//| Recursive subroutine for NN queries. | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeQueryNNRec(CKDTree &kdt,const int offs) - { -//--- create variables - double ptdist=0; - int i=0; - int j=0; - int nx=0; - int i1=0; - int i2=0; - int d=0; - double s=0; - double v=0; - double t1=0; - int childbestoffs=0; - int childworstoffs=0; - int childoffs=0; - double prevdist=0; - bool todive; - bool bestisleft; - bool updatemin; -//--- Leaf node. -//--- Process points. - if(kdt.m_nodes[offs]>0) - { - i1=kdt.m_nodes[offs+1]; - i2=i1+kdt.m_nodes[offs]; - for(i=i1;i<=i2-1;i++) - { - //--- Calculate distance - ptdist=0; - nx=kdt.m_nx; - //--- check - if(kdt.m_normtype==0) - { - for(j=0;j<=nx-1;j++) - ptdist=MathMax(ptdist,MathAbs(kdt.m_xy[i][j]-kdt.m_x[j])); - } - //--- check - if(kdt.m_normtype==1) - { - for(j=0;j<=nx-1;j++) - ptdist=ptdist+MathAbs(kdt.m_xy[i][j]-kdt.m_x[j]); - } - //--- check - if(kdt.m_normtype==2) - { - for(j=0;j<=nx-1;j++) - ptdist=ptdist+CMath::Sqr(kdt.m_xy[i][j]-kdt.m_x[j]); - } - //--- Skip points with zero distance if self-matches are turned off - if(ptdist==0.0 && !kdt.m_selfmatch) - continue; - //--- We CAN'T process point if R-criterion isn't satisfied, - //--- i.e. (RNeeded<>0) AND (PtDist>R). - if(kdt.m_rneeded==0.0 || ptdist<=kdt.m_rneeded) - { - //--- R-criterion is satisfied, we must either: - //--- * replace worst point, if (KNeeded<>0) AND (KCur=KNeeded) - //--- (or skip, if worst point is better) - //--- * add point without replacement otherwise - if(kdt.m_kcur=s) - { - //--- check - if(kdt.m_normtype==0) - kdt.m_curdist=MathMax(kdt.m_curdist,t1-s); - //--- check - if(kdt.m_normtype==1) - kdt.m_curdist=kdt.m_curdist-MathMax(t1-v,0)+t1-s; - //--- check - if(kdt.m_normtype==2) - kdt.m_curdist=kdt.m_curdist-CMath::Sqr(MathMax(t1-v,0))+CMath::Sqr(t1-s); - } - kdt.m_curboxmax[d]=s; - } - //--- Decide: to dive into cell or not to dive - if(kdt.m_rneeded!=0.0 && kdt.m_curdist>kdt.m_rneeded) - todive=false; - else - { - //--- check - if(kdt.m_kcurvmax) - kdt.m_curdist=MathMax(kdt.m_curdist,vx-vmax); - } - } - } -//--- check - if(kdt.m_normtype==1) - { - for(i=0;i<=kdt.m_nx-1;i++) - { - vx=x[i]; - vmin=kdt.m_boxmin[i]; - vmax=kdt.m_boxmax[i]; - kdt.m_x[i]=vx; - kdt.m_curboxmin[i]=vmin; - kdt.m_curboxmax[i]=vmax; - //--- check - if(vxvmax) - kdt.m_curdist=kdt.m_curdist+vx-vmax; - } - } - } -//--- check - if(kdt.m_normtype==2) - { - for(i=0;i<=kdt.m_nx-1;i++) - { - vx=x[i]; - vmin=kdt.m_boxmin[i]; - vmax=kdt.m_boxmax[i]; - kdt.m_x[i]=vx; - kdt.m_curboxmin[i]=vmin; - kdt.m_curboxmax[i]=vmax; - //--- check - if(vxvmax) - kdt.m_curdist=kdt.m_curdist+CMath::Sqr(vx-vmax); - } - } - } - } -//+------------------------------------------------------------------+ -//| This function allocates all dataset-independent array fields of | -//| KDTree, i.e. such array fields that their dimensions do not | -//| depend on dataset size. | -//| This function do not sets KDT.NX or KDT.NY - it just allocates | -//| arrays | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeAllocDataSetIndependent(CKDTree &kdt, - const int nx, - const int ny) - { -//--- allocation - ArrayResizeAL(kdt.m_x,nx); - ArrayResizeAL(kdt.m_boxmin,nx); - ArrayResizeAL(kdt.m_boxmax,nx); - ArrayResizeAL(kdt.m_curboxmin,nx); - ArrayResizeAL(kdt.m_curboxmax,nx); - } -//+------------------------------------------------------------------+ -//| This function allocates all dataset-dependent array fields of | -//| KDTree, i.e. such array fields that their dimensions depend on | -//| dataset size. | -//| This function do not sets KDT.N, KDT.NX or KDT.NY - | -//| it just allocates arrays. | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeAllocDataSetDependent(CKDTree &kdt, - const int n, - const int nx, - const int ny) - { -//--- allocation - kdt.m_xy.Resize(n,2*nx+ny); - ArrayResizeAL(kdt.m_tags,n); - ArrayResizeAL(kdt.m_idx,n); - ArrayResizeAL(kdt.m_r,n); - ArrayResizeAL(kdt.m_x,nx); - ArrayResizeAL(kdt.m_buf,MathMax(n,nx)); - ArrayResizeAL(kdt.m_nodes,m_splitnodesize*2*n); - ArrayResizeAL(kdt.m_splits,2*n); - } -//+------------------------------------------------------------------+ -//| This function allocates temporaries. | -//| This function do not sets KDT.N,KDT.NX or KDT.NY - | -//| it just allocates arrays. | -//+------------------------------------------------------------------+ -static void CNearestNeighbor::KDTreeAllocTemporaries(CKDTree &kdt,const int n, - const int nx,const int ny) - { -//--- allocation - ArrayResizeAL(kdt.m_x,nx); - ArrayResizeAL(kdt.m_idx,n); - ArrayResizeAL(kdt.m_r,n); - ArrayResizeAL(kdt.m_buf,MathMax(n,nx)); - ArrayResizeAL(kdt.m_curboxmin,nx); - ArrayResizeAL(kdt.m_curboxmax,nx); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/ap.mqh b/Include/Math/Alglib/ap.mqh deleted file mode 100644 index fcd5711..0000000 --- a/Include/Math/Alglib/ap.mqh +++ /dev/null @@ -1,2175 +0,0 @@ -//+------------------------------------------------------------------+ -//| ap.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "complex.mqh" -#include "matrix.mqh" -#include "bitconvert.mqh" -//+------------------------------------------------------------------+ -//| Reverse communication structure | -//+------------------------------------------------------------------+ -struct RCommState - { -public: - int stage; - int ia[]; - bool ba[]; - double ra[]; - al_complex ca[]; - - RCommState(void) { stage=-1; } - ~RCommState(void) { }; - void Copy(RCommState &obj); - }; -//+------------------------------------------------------------------+ -//| Create a copy | -//+------------------------------------------------------------------+ -void RCommState::Copy(RCommState &obj) - { -//--- copy a variable - stage=obj.stage; -//--- copy arrays - ArrayCopy(ia,obj.ia); - ArrayCopy(ba,obj.ba); - ArrayCopy(ra,obj.ra); - ArrayCopy(ca,obj.ca); - } -//+------------------------------------------------------------------+ -//| Internal functions | -//+------------------------------------------------------------------+ -class CAp - { -public: - //--- variable that determines whether an exception happened - static bool exception_happened; - //--- constructor, destructor - CAp(void); - ~CAp(void); - //--- len - static int Len(const int &a[]); - static int Len(const bool &a[]); - static int Len(const double &a[]); - static int Len(const al_complex &a[]); - //--- rows count - static int Rows(const CMatrixInt &a); - static int Rows(const CMatrixDouble &a); - static int Rows(const CMatrixComplex &a); - //--- cols count - static int Cols(const CMatrixInt &a); - static int Cols(const CMatrixDouble &a); - static int Cols(const CMatrixComplex &a); - //--- swap - static void Swap(int &a,int &b); - static void Swap(double &a,double &b); - static void Swap(al_complex &a,al_complex &b); - static void Swap(bool &a[],bool &b[]); - static void Swap(int &a[],int &b[]); - static void Swap(double &a[],double &b[]); - static void Swap(al_complex &a[],al_complex &b[]); - static void Swap(CMatrixInt &a,CMatrixInt &b); - static void Swap(CMatrixDouble &a,CMatrixDouble &b); - static void Swap(CMatrixComplex &a,CMatrixComplex &b); - //--- check assertions - static bool Assert(const bool cond); - static bool Assert(const bool cond,const string s); - //--- determination of accuracy - static int ThresHoldToDPS(const double threshold); - //--- join string - static string StringJoin(const string sep,const string &a[]); - //--- convert to string - static string Format(const al_complex &a,const int dps); - static string Format(const bool &a[]); - static string Format(const int &a[]); - static string Format(const double &a[],const int dps); - static string Format(const al_complex &a[],const int dps); - static string FormatB(const CMatrixInt &a); - static string Format(const CMatrixInt &a); - static string Format(const CMatrixDouble &a,const int dps); - static string Format(const CMatrixComplex &a,const int dps); - //--- work with matrix - static bool IsSymmetric(const CMatrixDouble &a); - static bool IsHermitian(const CMatrixComplex &a); - static bool ForceSymmetric(CMatrixDouble &a); - static bool ForceHermitian(CMatrixComplex &a); - }; -//+------------------------------------------------------------------+ -//| Initialize variable | -//+------------------------------------------------------------------+ -bool CAp::exception_happened=false; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CAp::CAp(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CAp::~CAp(void) - { - - } -//+------------------------------------------------------------------+ -//| Get array lenght | -//+------------------------------------------------------------------+ -static int CAp::Len(const int &a[]) - { - return(ArraySize(a)); - } -//+------------------------------------------------------------------+ -//| Get array lenght | -//+------------------------------------------------------------------+ -static int CAp::Len(const bool &a[]) - { - return(ArraySize(a)); - } -//+------------------------------------------------------------------+ -//| Get array lenght | -//+------------------------------------------------------------------+ -static int CAp::Len(const double &a[]) - { - return(ArraySize(a)); - } -//+------------------------------------------------------------------+ -//| Get array lenght | -//+------------------------------------------------------------------+ -static int CAp::Len(const al_complex &a[]) - { - return(ArraySize(a)); - } -//+------------------------------------------------------------------+ -//| Get rows count | -//+------------------------------------------------------------------+ -static int CAp::Rows(const CMatrixInt &a) - { - return(a.Size()); - } -//+------------------------------------------------------------------+ -//| Get rows count | -//+------------------------------------------------------------------+ -static int CAp::Rows(const CMatrixDouble &a) - { - return(a.Size()); - } -//+------------------------------------------------------------------+ -//| Get rows count | -//+------------------------------------------------------------------+ -static int CAp::Rows(const CMatrixComplex &a) - { - return(a.Size()); - } -//+------------------------------------------------------------------+ -//| Get cols count | -//+------------------------------------------------------------------+ -static int CAp::Cols(const CMatrixInt &a) - { -//--- check - if(a.Size()==0) - return(0); -//--- return result - return(a[0].Size()); - } -//+------------------------------------------------------------------+ -//| Get rows count | -//+------------------------------------------------------------------+ -static int CAp::Cols(const CMatrixDouble &a) - { -//--- check - if(a.Size()==0) - return(0); -//--- return result - return(a[0].Size()); - } -//+------------------------------------------------------------------+ -//| Get rows count | -//+------------------------------------------------------------------+ -static int CAp::Cols(const CMatrixComplex &a) - { -//--- check - if(a.Size()==0) - return(0); -//--- return result - return(a[0].Size()); - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(int &a,int &b) - { - int t=a; - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(double &a,double &b) - { - double t=a; - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(al_complex &a,al_complex &b) - { - al_complex t(a.re,a.im); - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(bool &a[],bool &b[]) - { -//--- calculation - int na=ArraySize(a); - int nb=ArraySize(b); -//--- create array - bool t[]; - ArrayResizeAL(t,na); -//--- swap - ArrayCopy(t,a); - ArrayResizeAL(a,nb); - ArrayCopy(a,b); - ArrayResizeAL(b,na); - ArrayCopy(b,t); - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(int &a[],int &b[]) - { -//--- calculation - int na=ArraySize(a); - int nb=ArraySize(b); -//--- create array - int t[]; - ArrayResizeAL(t,na); -//--- swap - ArrayCopy(t,a); - ArrayResizeAL(a,nb); - ArrayCopy(a,b); - ArrayResizeAL(b,na); - ArrayCopy(b,t); - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(double &a[],double &b[]) - { -//--- calculation - int na=ArraySize(a); - int nb=ArraySize(b); -//--- create array - double t[]; - ArrayResizeAL(t,na); -//--- swap - ArrayCopy(t,a); - ArrayResizeAL(a,nb); - ArrayCopy(a,b); - ArrayResizeAL(b,na); - ArrayCopy(b,t); - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(al_complex &a[],al_complex &b[]) - { -//--- calculation - int na=ArraySize(a); - int nb=ArraySize(b); -//--- create array - al_complex t[]; - ArrayResizeAL(t,na); -//--- swap - ArrayCopy(t,a); - ArrayResizeAL(a,nb); - ArrayCopy(a,b); - ArrayResizeAL(b,na); - ArrayCopy(b,t); - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(CMatrixInt &a,CMatrixInt &b) - { -//--- create matrix - CMatrixInt t; -//--- swap - t=a; - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(CMatrixDouble &a,CMatrixDouble &b) - { -//--- create matrix - CMatrixDouble t; -//--- swap - t=a; - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Swap | -//+------------------------------------------------------------------+ -static void CAp::Swap(CMatrixComplex &a,CMatrixComplex &b) - { -//--- create matrix - CMatrixComplex t; -//--- swap - t=a; - a=b; - b=t; - } -//+------------------------------------------------------------------+ -//| Check assertions | -//+------------------------------------------------------------------+ -static bool CAp::Assert(const bool cond) - { - return(Assert(cond,"ALGLIB: assertion failed")); - } -//+------------------------------------------------------------------+ -//| Check assertions | -//+------------------------------------------------------------------+ -static bool CAp::Assert(const bool cond,const string s) - { -//--- check - if(cond==0) - { - Print(__FUNCTION__+" "+s); - exception_happened=true; - return(false); - } -//--- the assertion is true - return(true); - } -//+------------------------------------------------------------------+ -//| returns dps (digits-of-precision) value corresponding to | -//| threshold. | -//| dps(0.9) = dps(0.5) = dps(0.1) = 0 | -//| dps(0.09) = dps(0.05) = dps(0.01) = 1 | -//| and so on | -//+------------------------------------------------------------------+ -static int CAp::ThresHoldToDPS(const double threshold) - { -//--- initialization - int res=0; - double t=1.0; - for(res=0;t/10>threshold*(1+1E-10);res++) - t/=10; -//--- return result - return(res); - } -//+------------------------------------------------------------------+ -//| Concatenation | -//+------------------------------------------------------------------+ -static string CAp::StringJoin(const string sep,const string &a[]) - { - int size=ArraySize(a); -//--- check - if(size==0) - { - Print(__FUNCTION__+": array size error"); - return(NULL); - } -//--- concatenation - string res=""; - for(int i=0;i=0) fmt="f"; - else fmt="e"; -//--- get sign of the imaginary part - string sign; - if(a.im>=0) sign="+"; - else sign="-"; -//--- converting - int d=(int)MathAbs(dps); - string fmtx=StringFormat(".%d"+fmt,d); - string fmty=StringFormat(".%d"+fmt,d); -//--- get result - string res=StringFormat("%"+fmtx,a.re)+sign+ - StringFormat("%"+fmty,MathAbs(a.im))+"i"; - StringReplace(res,",","."); -//--- return result - return(res); - } -//+------------------------------------------------------------------+ -//| Prints formatted array | -//+------------------------------------------------------------------+ -static string CAp::Format(const bool &a[]) - { - int size=ArraySize(a); -//--- check - if(size==0) - { - Print(__FUNCTION__+": array size error"); - return(NULL); - } -//--- converting - string result[]; - ArrayResizeAL(result,size); - for(int i=0;i=0) sfmt="f"; - else sfmt="e"; -//--- converting - int d=(int)MathAbs(dps); - string fmt=StringFormat(".%d"+sfmt,d); - for(int i=0;i=0) fmt="f"; - else fmt="e"; -//--- converting - int d=(int)MathAbs(dps); - string fmtx=StringFormat(".%d"+fmt,d); - string fmty=StringFormat(".%d"+fmt,d); - string sign; - for(int i=0;i=0) sign="+"; - else sign="-"; - //--- fill result - result[i]=StringFormat("%"+fmtx,a[i].re)+sign+ - StringFormat("%"+fmty,MathAbs(a[i].im))+"i"; - StringReplace(result[i],",","."); - } -//--- return result - return("{"+StringJoin(",",result)+"}"); - } -//+------------------------------------------------------------------+ -//| Prints formatted matrix | -//+------------------------------------------------------------------+ -static string CAp::FormatB(const CMatrixInt &a) - { - int m=a.Size(); -//--- check - if(m==0) - { - Print(__FUNCTION__+": array size error"); - return(NULL); - } - int n=a[0].Size(); -//--- check - if(n==0) - { - Print(__FUNCTION__+": array size error"); - return(NULL); - } -//--- prepare arrays - bool line[]; - string result[]; - ArrayResizeAL(line,n); - ArrayResizeAL(result,m); -//--- converting - for(int i=0;iK*N) - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return(-1); -//--- check - if(!CAp::Assert(n=RNDBaseMax-1!")) - return(-1); -//--- initialization - mx=m_HQRndMax-1-(m_HQRndMax-1)%n; - do - result=HQRndIntegerBase(state)-1; - while(result>=mx); -//--- get result - result=result%n; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Random number generator: normal numbers | -//| This function generates one random number from normal | -//| distribution. | -//| Its performance is equal to that of HQRNDNormal2() | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static double CHighQualityRand::HQRndNormal(CHighQualityRandState &state) - { -//--- create variables - double v1=0; - double v2=0; -//--- function call - HQRndNormal2(state,v1,v2); -//--- return result - return(v1); - } -//+------------------------------------------------------------------+ -//| Random number generator: random X and Y such that X^2+Y^2=1 | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static void CHighQualityRand::HQRndUnit2(CHighQualityRandState &state, - double &x,double &y) - { -//--- create variables - double v=0; - double mx=0; - double mn=0; -//--- initialization - x=0; - y=0; -//--- function call - do - HQRndNormal2(state,x,y); - while(!(x!=0.0 || y!=0.0)); -//--- change values - mx=MathMax(MathAbs(x),MathAbs(y)); - mn=MathMin(MathAbs(x),MathAbs(y)); - v=mx*MathSqrt(1+CMath::Sqr(mn/mx)); -//--- get result - x=x/v; - y=y/v; - } -//+------------------------------------------------------------------+ -//| Random number generator: normal numbers | -//| This function generates two independent random numbers from | -//| normal distribution. Its performance is equal to that of | -//| HQRNDNormal() | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static void CHighQualityRand::HQRndNormal2(CHighQualityRandState &state, - double &x1,double &x2) - { -//--- create variables - double u=0; - double v=0; - double s=0; -//--- initialization - x1=0; - x2=0; -//--- cycle - while(true) - { - u=2*HQRndUniformR(state)-1; - v=2*HQRndUniformR(state)-1; - s=CMath::Sqr(u)+CMath::Sqr(v); - //--- check - if(s>0.0 && s<1.0) - { - //--- two Sqrt's instead of one to - //--- avoid overflow when S is too small - s=MathSqrt(-(2*MathLog(s)))/MathSqrt(s); - x1=u*s; - x2=v*s; - //--- exit the function - return; - } - } - } -//+------------------------------------------------------------------+ -//| Random number generator: exponential distribution | -//| State structure must be initialized with HQRNDRandomize() or | -//| HQRNDSeed(). | -//+------------------------------------------------------------------+ -static double CHighQualityRand::HQRndExponential(CHighQualityRandState &state, - const double lambdav) - { -//--- check - if(!CAp::Assert(lambdav>0.0,__FUNCTION__+": LambdaV<=0!")) - return(EMPTY_VALUE); -//--- return result - return(-(MathLog(HQRndUniformR(state))/lambdav)); - } -//+------------------------------------------------------------------+ -//| L'Ecuyer, Efficient and portable combined random number | -//| generators | -//+------------------------------------------------------------------+ -static int CHighQualityRand::HQRndIntegerBase(CHighQualityRandState &state) - { -//--- create variables - int result=0; - int k=0; -//--- check - if(!CAp::Assert(state.m_magicv==m_HQRndMagic,__FUNCTION__+": State is not correctly initialized!")) - return(-1); -//--- initialization - k=state.m_s1/53668; - state.m_s1=40014*(state.m_s1-k*53668)-k*12211; -//--- check - if(state.m_s1<0) - state.m_s1=state.m_s1+2147483563; -//--- change values - k=state.m_s2/52774; - state.m_s2=40692*(state.m_s2-k*52774)-k*3791; -//--- check - if(state.m_s2<0) - state.m_s2=state.m_s2+2147483399; -//--- Result - result=state.m_s1-state.m_s2; -//--- check - if(result<1) - result=result+2147483562; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Math functions | -//+------------------------------------------------------------------+ -class CMath - { -public: - //--- class variables - static bool m_first_call; - static double m_last; - static CHighQualityRandState m_state; - //--- machine constants - static const double m_machineepsilon; - static const double m_maxrealnumber; - static const double m_minrealnumber; - //--- constructor, destructor - CMath(void); - ~CMath(void); - //--- methods - static bool IsFinite(const double d); - static double RandomReal(void); - static int RandomInteger(const int n); - static double Sqr(const double x) { return(x*x); } - static double AbsComplex(const al_complex &z); - static double AbsComplex(const double r); - static al_complex Conj(const al_complex &z); - static al_complex Csqr(const al_complex &z); - }; -//+------------------------------------------------------------------+ -//| Initialize class constants | -//+------------------------------------------------------------------+ -const double CMath::m_machineepsilon=5E-16; -const double CMath::m_maxrealnumber=1E300; -const double CMath::m_minrealnumber=1E-300; -bool CMath::m_first_call=true; -double CMath::m_last=0.0; -CHighQualityRandState CMath::m_state; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMath::CMath(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMath::~CMath(void) - { - - } -//+------------------------------------------------------------------+ -//| Check on +-inf | -//+------------------------------------------------------------------+ -static bool CMath::IsFinite(const double d) - { -//--- return result - return(MathIsValidNumber(d)); - } -//+------------------------------------------------------------------+ -//| Random real value [0,1) | -//+------------------------------------------------------------------+ -static double CMath::RandomReal(void) - { -//--- create variable - double result; -//--- check - if(m_first_call) - { - CHighQualityRand::HQRndSeed(1+MathRand(),1+MathRand(),m_state); - m_first_call=false; - } -//--- get value - result=CHighQualityRand::HQRndUniformR(m_state); -//--- check - if(result==m_last) - { - m_first_call=true; - return(RandomReal()); - } -//--- change value - m_last=result; -//--- return result - return(CHighQualityRand::HQRndUniformR(m_state)); - } -//+------------------------------------------------------------------+ -//| Random integer value | -//+------------------------------------------------------------------+ -static int CMath::RandomInteger(const int n) - { -//--- check - if(m_first_call) - { - CHighQualityRand::HQRndSeed(1+MathRand(),1+MathRand(),m_state); - m_first_call=false; - } -//--- check and return result - if(n>=CHighQualityRand::m_HQRndM1-1) - return(CHighQualityRand::HQRndUniformI(m_state,CHighQualityRand::m_HQRndM1-2)); - else - return(CHighQualityRand::HQRndUniformI(m_state,n)); - } -//+------------------------------------------------------------------+ -//| The absolute value of a complex number | -//+------------------------------------------------------------------+ -static double CMath::AbsComplex(const al_complex &z) - { -//--- initialization - double w=0.0; - double v=0.0; - double xabs=MathAbs(z.re); - double yabs=MathAbs(z.im); -//--- check - if(xabs>yabs) w=xabs; - else w=yabs; -//--- check - if(xabsyabs) w=xabs; - else w=yabs; -//--- check - if(xabs63) - return('?'); -//--- return result - return(_sixbits2char_tbl[v]); - } -//+------------------------------------------------------------------+ -//| This function converts character to six-bit value (from 0 to 63).| -//| This function is inverse of ae_sixbits2char() | -//| If c is not correct character, this function returns -1. | -//+------------------------------------------------------------------+ -static int CSerializer::Char2SixBits(const char c) - { -//--- check - if(c>=0 && c<127) - return(_char2sixbits_tbl[c]); -//--- return result - return(-1); - } -//+------------------------------------------------------------------+ -//| This function converts three bytes (24 bits) to four six-bit | -//| values (24 bits again). | -//| src array | -//| src_offs offset of three-bytes chunk | -//| dst array for ints | -//| dst_offs offset of four-ints chunk | -//+------------------------------------------------------------------+ -static void CSerializer::ThreeBytes2FourSixBits(uchar &src[],const int src_offs, - int &dst[],const int dst_offs) - { -//--- get bits - dst[dst_offs+0]=src[src_offs+0] & 0x3F; - dst[dst_offs+1]=(src[src_offs+0]>>6) | ((src[src_offs+1]&0x0F)<<2); - dst[dst_offs+2]=(src[src_offs+1]>>4) | ((src[src_offs+2]&0x03)<<4); - dst[dst_offs+3]=src[src_offs+2]>>2; - } -//+------------------------------------------------------------------+ -//| This function converts four six-bit values (24 bits) to three | -//| bytes (24 bits again). | -//| src pointer to four ints | -//| src_offs offset of the chunk | -//| dst pointer to three bytes | -//| dst_offs offset of the chunk | -//+------------------------------------------------------------------+ -static void CSerializer::FourSixBits2ThreeBytes(int &src[],const int src_offs, - uchar &dst[],const int dst_offs) - { -//--- get bytes - dst[dst_offs+0]=(uchar)(src[src_offs+0] | ((src[src_offs+1]&0x03)<<6)); - dst[dst_offs+1]=(uchar)((src[src_offs+1]>>2) | ((src[src_offs+2]&0x0F)<<4)); - dst[dst_offs+2]=(uchar)((src[src_offs+2]>>4) | (src[src_offs+3]<<2)); - } -//+------------------------------------------------------------------+ -//| This function serializes boolean value into buffer | -//| v boolean value to be serialized | -//| buf buffer, at least 11 characters wide | -//| offs offset in the buffer | -//| after return(from this function, offs points to the char's past | -//| the value being read. | -//+------------------------------------------------------------------+ -static void CSerializer::Bool2Str(const bool v,char &buf[],int &offs) - { -//--- create variables - char c; - int i; -//--- check - if(v) - c='1'; - else - c='0'; -//--- copy c - for(i=0;i=m_ser_entry_length) - { - Print(__FUNCTION__+" "+emsg); - //--- return result - return(-1); - } - sixbits[sixbitsread]=d; - sixbitsread++; - offs++; - } -//--- check - if(sixbitsread==0) - { - Print(__FUNCTION__+" "+emsg); - //--- return result - return(-1); - } - for(i=sixbitsread;i<12;i++) - sixbits[i]=0; -//--- function call - FourSixBits2ThreeBytes(sixbits,0,bytes,0); -//--- function call - FourSixBits2ThreeBytes(sixbits,4,bytes,3); -//--- function call - FourSixBits2ThreeBytes(sixbits,8,bytes,6); -//--- check - if((bytes[sizeof(int)-1]&0x80)!=0) - c=(uchar)0xFF; - else - c=(uchar)0x00; - for(i=sizeof(int);i<8;i++) - //--- check - if(bytes[i]!=c) - { - Print(__FUNCTION__+" "+emsg3264); - //--- return result - return(-1); - } -//--- copy - for(i=0;i=m_ser_entry_length) - { - Print(__FUNCTION__+"emsg"); - //--- return result - return(EMPTY_VALUE); - } - sixbits[sixbitsread]=d; - sixbitsread++; - offs++; - } -//--- check - if(sixbitsread!=m_ser_entry_length) - { - Print(__FUNCTION__+"emsg"); - //--- return result - return(EMPTY_VALUE); - } - sixbits[m_ser_entry_length]=0; -//--- function call - FourSixBits2ThreeBytes(sixbits,0,bytes,0); -//--- function call - FourSixBits2ThreeBytes(sixbits,4,bytes,3); -//--- function call - FourSixBits2ThreeBytes(sixbits,8,bytes,6); -//--- copy - for(i=0;i0 && old0 && old0 && old0 && old0 && old0 && old=0) - bytes[i]=0; - else - bytes[i]=255; - } -//--- initialization - q=-1; - r=-1; - i=3; - div=256*256*256; -//--- check - if(d<0) - x=~d; - else - x=d; -//--- converting number - while(i!=-1) - { - //--- quotient - q=x/div; - //--- remainder of division - r=x%div; - //--- get byte - if(d>=0) - bytes[i]+=(uchar)q; - else - bytes[i]-=(uchar)q; - //--- the next iteration is reduced divisor - x=r; - div=div/256; - i--; - } - } -//+------------------------------------------------------------------+ -//| Converting double to a byte array | -//+------------------------------------------------------------------+ -static void BitConverter::GetBytes(const double d,uchar &bytes[]) - { -//--- module - double abs_d=MathAbs(d); -//--- number without its fractional - double floor_d=MathFloor(abs_d); -//--- fractional part - double fractional_d=abs_d-floor_d; -//--- variable will store the degree - int power; -//--- exponent shift - double exp_shift; -//--- create variables - int k; - int j; - uchar u; - double step; - double f; -//--- abs_d as bits - bool abs_d_to_bitArray[]; -//--- d as bits in format IEEE 754 - bool d_to_bitArray[]; -//--- allocation - ArrayResizeAL(d_to_bitArray,64); - ArrayResizeAL(bytes,8); -//--- initialization - power=0; -//--- for integer part - while(1) - { - //--- if the number is less than or equal floor_d, we increase the degree - //--- if 2^power > floor_d, then maximal number < floor_d - it 2^(power-1) - if(floor_d>=MathPow(2,power)) - power++; - else - break; - } -//--- get power-1 - power--; -//--- if power=-1, then floor_d=0 -//--- find a negative power for the fractional part - if(power==-1) - { - power=0; - while(1) - { - //--- the same principle as above - if(fractional_dabs_d) - { - //--- if abs_d < f - this bit is zero - ArrayResizeAL(abs_d_to_bitArray,j+1); - abs_d_to_bitArray[j]=0; - j++; - step-=1; - } - else - { - //--- if abs_d >= f, then this bit is equal one - //--- reduction abs_d - abs_d-=f; - ArrayResizeAL(abs_d_to_bitArray,j+1); - abs_d_to_bitArray[j]=1; - j++; - step-=1; - } - } -//--- according to IEEE 754, -//--- zero bit determines sign of the number, 0 -> '+', 1 -> '-'. - if(d>=0) - d_to_bitArray[0]=0; - else - d_to_bitArray[0]=1; -//--- offset input - exp_shift=1023+power; -//--- bits from the first and 11 are reserved for the shifted exponential - j=1; - for(int i=10;i>=0;i--) - { - if(MathPow(2,i)>exp_shift) - d_to_bitArray[j]=0; - else - { - d_to_bitArray[j]=1; - //--- reduction - exp_shift-=MathPow(2,i); - } - j++; - } -//--- Get the length of the array of the binary representation of abs_d - k=ArraySize(abs_d_to_bitArray); - j=1; -//--- Bits from 12 to 63 are filled with binary representation of abs_b -//--- the first element abs_d_to_bitArray is always 1 - for(int i=12;i<64;i++) - { - if(j=0;i--) - { - d+=bytes[i]*mul; - mul=mul/256; - } -//--- return result - return(d); - } -//+------------------------------------------------------------------+ -//| Converting byte array to a double | -//+------------------------------------------------------------------+ -static double BitConverter::ToDouble(uchar &bytes[]) - { -//--- create variables - int s; -//--- exponent shift - int e=0; -//--- mantissa - double m=0; -//--- array of bits in IEEE 754 - bool bits[]; - ArrayResizeAL(bits,64); -//--- get array of bits from array of bytes - for(int i=0;i<8;i++) - { - for(int j=7;j>=0;j--) - { - //--- if 2 in power >, bits[i*8+j]=0, else bits[i*8+j]=0 - if(MathPow(2,j)>bytes[i]) - bits[i*8+j]=0; - else - { - bits[i*8+j]=1; - //--- reduction - bytes[i]-=(uchar)MathPow(2,j); - } - } - } -//--- search bits with 1 - bool allzero=true; - for(int i=0;i<64;i++) - if(bits[i]==1) - allzero=false; -//--- if all bits are 0, then number is 0 - if(allzero==true) - return(0.0); -//--- reverse array - ArrayReverse(bits); -//--- s-the first bit, determines sign of the number - s=bits[0]; -//--- calculation exponent shift - for(int i=10;i>=0;i--) - e+=(int)(bits[11-i]*MathPow(2,i)); -//--- get mantissa - for(int i=0;i<52;i++) - m+=bits[12+i]*MathPow(2,-1-i); -//--- return result - return(MathPow(-1,s)*MathPow(2,e-1023)*(1+m)); - } -//+------------------------------------------------------------------+ -//| Byte ordering (forward, backward) | -//+------------------------------------------------------------------+ -static bool BitConverter::IsLittleEndian(void) - { -//--- forward - return(true); - } -//+------------------------------------------------------------------+ -//| Array reverse (uchar) | -//+------------------------------------------------------------------+ -void ArrayReverse(uchar &array[]) - { -//--- size - int size=ArraySize(array); -//--- half of size - int half=size/2; -//--- create a variable - uchar temp; -//--- reverse - for(int i=0;i0 - if(x>0) - return(1); -//--- if ?==0 - if(x==0) - return(0); -//--- ?<0 - return(-1); - } -#ifndef __MQL5__ -//+------------------------------------------------------------------+ -//| Hyperbolic sine | -//+------------------------------------------------------------------+ -double MathSinh(const double x) - { -//--- return result - return((MathPow(M_E,x)-MathPow(M_E,-x))/2); - } -//+------------------------------------------------------------------+ -//| Hyperbolic cosine | -//+------------------------------------------------------------------+ -double MathCosh(const double x) - { -//--- return result - return((MathPow(M_E,x)+MathPow(M_E,-x))/2); - } -//+------------------------------------------------------------------+ -//| Hyperbolic tangent | -//+------------------------------------------------------------------+ -double MathTanh(const double x) - { -//--- return result - return(MathSinh(x)/MathCosh(x)); - } -#endif -//+------------------------------------------------------------------+ -//| Structure stores a variable of type double | -//+------------------------------------------------------------------+ -union UDoubleValue - { - double value; - long bits; - - UDoubleValue(double dbl):value(dbl) { } - UDoubleValue(long bit_value):bits(bit_value) { } - }; -//+------------------------------------------------------------------+ -//| Work with infinity and NaN | -//+------------------------------------------------------------------+ -class CInfOrNaN - { -public: - //--- constructor, destructor - CInfOrNaN(void); - ~CInfOrNaN(void); - //--- checks - static bool IsPositiveInfinity(const double x); - static bool IsNegativeInfinity(const double x); - static bool IsInfinity(const double x); - static bool IsNaN(const double x); - //--- generation values - static double PositiveInfinity(void); - static double NegativeInfinity(void); - static double NaN(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CInfOrNaN::CInfOrNaN(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CInfOrNaN::~CInfOrNaN(void) - { - - } -//+------------------------------------------------------------------+ -//| Check for +inf | -//+------------------------------------------------------------------+ -static bool CInfOrNaN::IsPositiveInfinity(const double x) - { - UDoubleValue val=x; -//--- check - return(val.bits==0x7FF0000000000000); - } -//+------------------------------------------------------------------+ -//| Check for -inf | -//+------------------------------------------------------------------+ -static bool CInfOrNaN::IsNegativeInfinity(const double x) - { - UDoubleValue val=x; -//--- check - return(val.bits==0xFFF0000000000000); - } -//+------------------------------------------------------------------+ -//| Check for +-inf | -//+------------------------------------------------------------------+ -static bool CInfOrNaN::IsInfinity(const double x) - { - UDoubleValue val=x; -//--- check - return(val.bits==0x7FF0000000000000 || val.bits==0xFFF0000000000000); - } -//+------------------------------------------------------------------+ -//| Check for NaN | -//+------------------------------------------------------------------+ -static bool CInfOrNaN::IsNaN(const double x) - { -//--- check - if(MathIsValidNumber(x)) - { - //--- is valid number - return(false); - } -//--- check - if(IsInfinity(x)) - { - //--- +-inf - return(false); - } -//--- is NaN - return(true); - } -//+------------------------------------------------------------------+ -//| Return +inf | -//+------------------------------------------------------------------+ -static double CInfOrNaN::PositiveInfinity(void) - { - UDoubleValue val(0x7FF0000000000000); - return(val.value); - } -//+------------------------------------------------------------------+ -//| Return -inf | -//+------------------------------------------------------------------+ -static double CInfOrNaN::NegativeInfinity(void) - { - UDoubleValue val(0xFFF0000000000000); - return(val.value); - } -//+------------------------------------------------------------------+ -//| Return NaN | -//+------------------------------------------------------------------+ -static double CInfOrNaN::NaN(void) - { - UDoubleValue val(0x7FFFFFFFFFFFFFFF); - return(val.value); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/complex.mqh b/Include/Math/Alglib/complex.mqh deleted file mode 100644 index 9d7cd7f..0000000 --- a/Include/Math/Alglib/complex.mqh +++ /dev/null @@ -1,358 +0,0 @@ -//+------------------------------------------------------------------+ -//| complex.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Complex numbers | -//+------------------------------------------------------------------+ -struct al_complex - { -public: - double re; // real part - double im; // imaginary part - -public: - al_complex(void); - al_complex(const double x); - al_complex(const double x,const double y); - ~al_complex(void); - //--- operations - void Copy(const al_complex &rhs); - bool Eq(const al_complex &lhs,const al_complex &rhs); - bool NotEq(const al_complex &lhs,const al_complex &rhs); - al_complex Add(const al_complex &lhs,const al_complex &rhs); - al_complex Sub(const al_complex &lhs,const al_complex &rhs); - al_complex Mul(const al_complex &lhs,const al_complex &rhs); - al_complex Div(const al_complex &lhs,const al_complex &rhs); - al_complex Conjugate(void); - //--- overloading - void operator=(const double rhs); - void operator=(const al_complex &rhs); - void operator+=(const al_complex &rhs); - void operator-=(const al_complex &rhs); - bool operator==(const al_complex &rhs); - bool operator==(const double rhs); - bool operator!=(const al_complex &rhs); - bool operator!=(const double rhs); - al_complex operator+(const al_complex &rhs); - al_complex operator+(const double rhs); - al_complex operator+(void); - al_complex operator-(const al_complex &rhs); - al_complex operator-(const double rhs); - al_complex operator-(void); - al_complex operator*(const al_complex &rhs); - al_complex operator*(const double rhs); - al_complex operator/(const al_complex &rhs); - al_complex operator/(const double rhs); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -al_complex::al_complex(void): re(0),im(0) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with one parameter | -//+------------------------------------------------------------------+ -al_complex::al_complex(const double x): re(x),im(0) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with two parameters | -//+------------------------------------------------------------------+ -al_complex::al_complex(const double x,const double y): re(x),im(y) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -al_complex::~al_complex(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy complex | -//+------------------------------------------------------------------+ -void al_complex::Copy(const al_complex &rhs) - { - re=rhs.re; - im=rhs.im; - } -//+------------------------------------------------------------------+ -//| Comparison (==) | -//+------------------------------------------------------------------+ -bool al_complex::Eq(const al_complex &lhs,const al_complex &rhs) - { -//--- comparison - if(lhs.re==rhs.re && lhs.im==rhs.im) - return(true); -//--- numbers are not equal - return(false); - } -//+------------------------------------------------------------------+ -//| Comparison (!=) | -//+------------------------------------------------------------------+ -bool al_complex::NotEq(const al_complex &lhs,const al_complex &rhs) - { -//--- comparison - if(lhs.re!=rhs.re || lhs.im!=rhs.im) - return(true); -//--- numbers are equal - return(false); - } -//+------------------------------------------------------------------+ -//| Sum | -//+------------------------------------------------------------------+ -al_complex al_complex::Add(const al_complex &lhs,const al_complex &rhs) - { - al_complex res; -//--- sum - res.re=lhs.re+rhs.re; - res.im=lhs.im+rhs.im; -//--- return result - return(res); - } -//+------------------------------------------------------------------+ -//| Subtraction | -//+------------------------------------------------------------------+ -al_complex al_complex::Sub(const al_complex &lhs,const al_complex &rhs) - { - al_complex res; -//--- subtraction - res.re=lhs.re-rhs.re; - res.im=lhs.im-rhs.im; -//--- return result - return(res); - } -//+------------------------------------------------------------------+ -//| Multiplication | -//+------------------------------------------------------------------+ -al_complex al_complex::Mul(const al_complex &lhs,const al_complex &rhs) - { - al_complex res; -//--- multiplication - res.re=lhs.re*rhs.re-lhs.im*rhs.im; - res.im=lhs.re*rhs.im+lhs.im*rhs.re; -//--- return result - return(res); - } -//+------------------------------------------------------------------+ -//| Division | -//+------------------------------------------------------------------+ -al_complex al_complex::Div(const al_complex &lhs,const al_complex &rhs) - { -//--- empty complex value - al_complex res(EMPTY_VALUE,EMPTY_VALUE); -//--- check - if(rhs.re==0 && rhs.im==0) - { - Print(__FUNCTION__+": number is zero"); - return(res); - } -//--- create variables - double e; - double f; -//--- division - if(MathAbs(rhs.im)0" means that we have classification task. | -//| "NClasses<0" means regression task with -NClasses real | -//| outputs. | -//| NOTES(2): | -//| rms. avg, avg.rel errors for classification tasks are | -//| interpreted as errors in posterior probabilities with | -//| respect to probabilities given by training/test set. | -//+------------------------------------------------------------------+ -static void CBdSS::DSErrAllocate(const int nclasses,double &buf[]) - { -//--- allocation - ArrayResizeAL(buf,8); -//--- initialization - buf[0]=0; - buf[1]=0; - buf[2]=0; - buf[3]=0; - buf[4]=0; - buf[5]=nclasses; - buf[6]=0; - buf[7]=0; - } -//+------------------------------------------------------------------+ -//| See DSErrAllocate for comments on this routine. | -//+------------------------------------------------------------------+ -static void CBdSS::DSErrAccumulate(double &buf[],double &y[],double &desiredy[]) - { -//--- create variables - int nclasses=0; - int nout=0; - int offs=0; - int mmax=0; - int rmax=0; - int j=0; - double v=0; - double ev=0; -//--- initialization - offs=5; - nclasses=(int)MathRound(buf[offs]); -//--- check - if(nclasses>0) - { - //--- Classification - rmax=(int)MathRound(desiredy[0]); - mmax=0; - //--- initialization - for(j=1;j<=nclasses-1;j++) - { - //--- check - if(y[j]>y[mmax]) - mmax=j; - } - //--- check - if(mmax!=rmax) - buf[0]=buf[0]+1; - //--- check - if(y[rmax]>0.0) - buf[1]=buf[1]-MathLog(y[rmax]); - else - buf[1]=buf[1]+MathLog(CMath::m_maxrealnumber); - //--- calculation - for(j=0;j<=nclasses-1;j++) - { - v=y[j]; - //--- check - if(j==rmax) - ev=1; - else - ev=0; - //--- change values - buf[2]=buf[2]+CMath::Sqr(v-ev); - buf[3]=buf[3]+MathAbs(v-ev); - //--- check - if(ev!=0.0) - { - buf[4]=buf[4]+MathAbs((v-ev)/ev); - buf[offs+2]=buf[offs+2]+1; - } - } - //--- change value - buf[offs+1]=buf[offs+1]+1; - } - else - { - //--- Regression - nout=-nclasses; - rmax=0; - //--- initialization - for(j=1;j<=nout-1;j++) - { - //--- check - if(desiredy[j]>desiredy[rmax]) - rmax=j; - } - //--- initialization - mmax=0; - for(j=1;j<=nout-1;j++) - { - //--- check - if(y[j]>y[mmax]) - mmax=j; - } - //--- check - if(mmax!=rmax) - buf[0]=buf[0]+1; - //--- calculation - for(j=0;j<=nout-1;j++) - { - //--- change values - v=y[j]; - ev=desiredy[j]; - buf[2]=buf[2]+CMath::Sqr(v-ev); - buf[3]=buf[3]+MathAbs(v-ev); - //--- check - if(ev!=0.0) - { - buf[4]=buf[4]+MathAbs((v-ev)/ev); - buf[offs+2]=buf[offs+2]+1; - } - } - //--- change value - buf[offs+1]=buf[offs+1]+1; - } - } -//+------------------------------------------------------------------+ -//| See DSErrAllocate for comments on this routine. | -//+------------------------------------------------------------------+ -static void CBdSS::DSErrFinish(double &buf[]) - { -//--- create variables - int nout=0; - int offs=0; -//--- initialization - offs=5; - nout=(int)(MathAbs((int)MathRound(buf[offs]))); -//--- check - if(buf[offs+1]!=0.0) - { - //--- change values - buf[0]=buf[0]/buf[offs+1]; - buf[1]=buf[1]/buf[offs+1]; - buf[2]=MathSqrt(buf[2]/(nout*buf[offs+1])); - buf[3]=buf[3]/(nout*buf[offs+1]); - } -//--- check - if(buf[offs+2]!=0.0) - buf[4]=buf[4]/buf[offs+2]; - } -//+------------------------------------------------------------------+ -//| Normalize | -//+------------------------------------------------------------------+ -static void CBdSS::DSNormalize(CMatrixDouble &xy,const int npoints, - const int nvars,int &info,double &means[], - double &sigmas[]) - { -//--- create variables - int i=0; - int j=0; - double mean=0; - double variance=0; - double skewness=0; - double kurtosis=0; - int i_=0; -//--- create array - double tmp[]; -//--- initialization - info=0; -//--- Test parameters - if(npoints<=0 || nvars<1) - { - info=-1; - return; - } -//--- change value - info=1; -//--- Standartization - ArrayResizeAL(means,nvars); - ArrayResizeAL(sigmas,nvars); - ArrayResizeAL(tmp,npoints); -//--- calculation - for(j=0;j<=nvars-1;j++) - { - //--- copy - for(i_=0;i_<=npoints-1;i_++) - tmp[i_]=xy[i_][j]; - //--- function call - CBaseStat::SampleMoments(tmp,npoints,mean,variance,skewness,kurtosis); - //--- change values - means[j]=mean; - sigmas[j]=MathSqrt(variance); - //--- check - if(sigmas[j]==0.0) - sigmas[j]=1; - //--- change values - for(i=0;i<=npoints-1;i++) - xy[i].Set(j,(xy[i][j]-means[j])/sigmas[j]); - } - } -//+------------------------------------------------------------------+ -//| Normalize | -//+------------------------------------------------------------------+ -static void CBdSS::DSNormalizeC(CMatrixDouble &xy,const int npoints, - const int nvars,int &info,double &means[], - double &sigmas[]) - { -//--- create variables - int j=0; - double mean=0; - double variance=0; - double skewness=0; - double kurtosis=0; - int i_=0; -//--- create array - double tmp[]; -//--- initialization - info=0; -//--- Test parameters - if(npoints<=0 || nvars<1) - { - info=-1; - return; - } -//--- change value - info=1; -//--- Standartization - ArrayResizeAL(means,nvars); - ArrayResizeAL(sigmas,nvars); - ArrayResizeAL(tmp,npoints); - for(j=0;j<=nvars-1;j++) - { - //--- copy - for(i_=0;i_<=npoints-1;i_++) - tmp[i_]=xy[i_][j]; - //--- function call - CBaseStat::SampleMoments(tmp,npoints,mean,variance,skewness,kurtosis); - //--- change values - means[j]=mean; - sigmas[j]=MathSqrt(variance); - //--- check - if(sigmas[j]==0.0) - sigmas[j]=1; - } - } -//+------------------------------------------------------------------+ -//| Method | -//+------------------------------------------------------------------+ -static double CBdSS::DSGetMeanMindIstance(CMatrixDouble &xy,const int npoints, - const int nvars) - { -//--- create variables - double result=0; - int i=0; - int j=0; - double v=0; - int i_=0; -//--- creating arrays - double tmp[]; - double tmp2[]; -//--- Test parameters - if(npoints<=0 || nvars<1) - return(0); -//--- Process - ArrayResizeAL(tmp,npoints); - for(i=0;i<=npoints-1;i++) - tmp[i]=CMath::m_maxrealnumber; -//--- allocation - ArrayResizeAL(tmp2,nvars); - for(i=0;i<=npoints-1;i++) - { - for(j=i+1;j<=npoints-1;j++) - { - //--- calculation - for(i_=0;i_<=nvars-1;i_++) - tmp2[i_]=xy[i][i_]; - for(i_=0;i_<=nvars-1;i_++) - tmp2[i_]=tmp2[i_]-xy[j][i_]; - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=tmp2[i_]*tmp2[i_]; - //--- change values - v=MathSqrt(v); - tmp[i]=MathMin(tmp[i],v); - tmp[j]=MathMin(tmp[j],v); - } - } -//--- get result - result=0; - for(i=0;i<=npoints-1;i++) - result=result+tmp[i]/npoints; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Method | -//+------------------------------------------------------------------+ -static void CBdSS::DSTie(double &a[],const int n,int &ties[],int &tiecount, - int &p1[],int &p2[]) - { -//--- create variables - int i=0; - int k=0; -//--- create array - int tmp[]; -//--- initialization - tiecount=0; -//--- Special case - if(n<=0) - { - tiecount=0; - return; - } -//--- Sort A - CTSort::TagSort(a,n,p1,p2); -//--- Process ties - tiecount=1; - for(i=1;i<=n-1;i++) - { - //--- check - if(a[i]!=a[i-1]) - tiecount=tiecount+1; - } -//--- allocation - ArrayResizeAL(ties,tiecount+1); -//--- change values - ties[0]=0; - k=1; -//--- calculation - for(i=1;i<=n-1;i++) - { - //--- check - if(a[i]!=a[i-1]) - { - ties[k]=i; - k=k+1; - } - } -//--- change value - ties[tiecount]=n; - } -//+------------------------------------------------------------------+ -//| Method | -//+------------------------------------------------------------------+ -static void CBdSS::DSTieFastI(double &a[],int &b[],const int n,int &ties[], - int &tiecount,double &bufr[],int &bufi[]) - { -//--- create variables - int i=0; - int k=0; -//--- create array - int tmp[]; -//--- initialization - tiecount=0; -//--- Special case - if(n<=0) - { - tiecount=0; - return; - } -//--- Sort A - CTSort::TagSortFastI(a,b,bufr,bufi,n); -//--- Process ties - ties[0]=0; - k=1; -//--- calculation - for(i=1;i<=n-1;i++) - { - //--- check - if(a[i]!=a[i-1]) - { - ties[k]=i; - k=k+1; - } - } -//--- change values - ties[k]=n; - tiecount=k; - } -//+------------------------------------------------------------------+ -//| Optimal binary classification | -//| Algorithms finds optimal (=with minimal cross-entropy) binary | -//| partition. | -//| Internal subroutine. | -//| INPUT PARAMETERS: | -//| A - array[0..N-1], variable | -//| C - array[0..N-1], class numbers (0 or 1). | -//| N - array size | -//| OUTPUT PARAMETERS: | -//| Info - completetion code: | -//| * -3, all values of A[] are same (partition is | -//| impossible) | -//| * -2, one of C[] is incorrect (<0, >1) | -//| * -1, incorrect pararemets were passed (N<=0). | -//| * 1, OK | -//| Threshold- partiton boundary. Left part contains values | -//| which are strictly less than Threshold. Right | -//| part contains values which are greater than or | -//| equal to Threshold. | -//| PAL, PBL- probabilities P(0|v=Threshold) and | -//| P(1|v>=Threshold) | -//| CVE - cross-validation estimate of cross-entropy | -//+------------------------------------------------------------------+ -static void CBdSS::DSOptimalSplit2(double &ca[],int &cc[],const int n, - int &info,double &threshold,double &pal, - double &pbl,double &par,double &pbr, - double &cve) - { -//--- create variables - int i=0; - int t=0; - double s=0; - int tiecount=0; - int k=0; - int koptimal=0; - double pak=0; - double pbk=0; - double cvoptimal=0; - double cv=0; -//--- creating arrays - int ties[]; - int p1[]; - int p2[]; - double a[]; - int c[]; -//--- copy - ArrayCopy(a,ca); - ArrayCopy(c,cc); -//--- initialization - info=0; - threshold=0; - pal=0; - pbl=0; - par=0; - pbr=0; - cve=0; -//--- Test for errors in inputs - if(n<=0) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(c[i]!=0 && c[i]!=1) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Tie - DSTie(a,n,ties,tiecount,p1,p2); -//--- swap - for(i=0;i<=n-1;i++) - { - //--- check - if(p2[i]!=i) - { - t=c[i]; - c[i]=c[p2[i]]; - c[p2[i]]=t; - } - } -//--- Special case: number of ties is 1. -//--- NOTE: we assume that P[i][j] equals to 0 or 1, -//--- intermediate values are not allowed. - if(tiecount==1) - { - info=-3; - return; - } -//--- General case,number of ties > 1 -//--- NOTE: we assume that P[i][j] equals to 0 or 1, -//--- intermediate values are not allowed. - pal=0; - pbl=0; - par=0; - pbr=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(c[i]==0) - par=par+1; - //--- check - if(c[i]==1) - pbr=pbr+1; - } -//--- change values - koptimal=-1; - cvoptimal=CMath::m_maxrealnumber; - for(k=0;k<=tiecount-2;k++) - { - //--- first,obtain information about K-th tie which is - //--- moved from R-part to L-part - pak=0; - pbk=0; - for(i=ties[k];i<=ties[k+1]-1;i++) - { - //--- check - if(c[i]==0) - pak=pak+1; - //--- check - if(c[i]==1) - pbk=pbk+1; - } - //--- Calculate cross-validation CE - cv=0; - cv=cv-XLnY(pal+pak,(pal+pak)/(pal+pak+pbl+pbk+1)); - cv=cv-XLnY(pbl+pbk,(pbl+pbk)/(pal+pak+1+pbl+pbk)); - cv=cv-XLnY(par-pak,(par-pak)/(par-pak+pbr-pbk+1)); - cv=cv-XLnY(pbr-pbk,(pbr-pbk)/(par-pak+1+pbr-pbk)); - //--- Compare with best - if(cv0"=OK, "<0"=bad) | -//| RMS training set RMS error | -//| CVRMS leave-one-out RMS error | -//| Note: | -//| content of all arrays is changed by subroutine; | -//| it doesn't allocate temporaries. | -//+------------------------------------------------------------------+ -static void CBdSS::DSOptimalSplit2Fast(double &a[],int &c[],int &tiesbuf[], - int &cntbuf[],double &bufr[],int &bufi[], - const int n,const int nc,double alpha, - int &info,double &threshold, - double &rms,double &cvrms) - { -//--- create variables - int i=0; - int k=0; - int cl=0; - int tiecount=0; - double cbest=0; - double cc=0; - int koptimal=0; - int sl=0; - int sr=0; - double v=0; - double w=0; - double x=0; -//--- initialization - info=0; - threshold=0; - rms=0; - cvrms=0; -//--- Test for errors in inputs - if(n<=0 || nc<2) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(c[i]<0 || c[i]>=nc) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Tie - DSTieFastI(a,c,n,tiesbuf,tiecount,bufr,bufi); -//--- Special case: number of ties is 1. - if(tiecount==1) - { - info=-3; - return; - } -//--- General case,number of ties > 1 - for(i=0;i<=2*nc-1;i++) - cntbuf[i]=0; - for(i=0;i<=n-1;i++) - cntbuf[nc+c[i]]=cntbuf[nc+c[i]]+1; -//--- change values - koptimal=-1; - threshold=a[n-1]; - cbest=CMath::m_maxrealnumber; - sl=0; - sr=n; -//--- calculation - for(k=0;k<=tiecount-2;k++) - { - //--- first,move Kth tie from right to left - for(i=tiesbuf[k];i<=tiesbuf[k+1]-1;i++) - { - cl=c[i]; - cntbuf[cl]=cntbuf[cl]+1; - cntbuf[nc+cl]=cntbuf[nc+cl]-1; - } - sl=sl+(tiesbuf[k+1]-tiesbuf[k]); - sr=sr-(tiesbuf[k+1]-tiesbuf[k]); - //--- Calculate RMS error - v=0; - for(i=0;i<=nc-1;i++) - { - w=cntbuf[i]; - v=v+w*CMath::Sqr(w/sl-1); - v=v+(sl-w)*CMath::Sqr(w/sl); - w=cntbuf[nc+i]; - v=v+w*CMath::Sqr(w/sr-1); - v=v+(sr-w)*CMath::Sqr(w/sr); - } - //--- change value - v=MathSqrt(v/(nc*n)); - //--- Compare with best - x=(double)(2*sl)/(double)(sl+sr)-1; - cc=v*(1-alpha+alpha*CMath::Sqr(x)); - //--- check - if(cc1) - { - w=cntbuf[i]; - cvrms=cvrms+w*CMath::Sqr((w-1)/(sl-1)-1); - cvrms=cvrms+(sl-w)*CMath::Sqr(w/(sl-1)); - } - else - { - w=cntbuf[i]; - cvrms=cvrms+w*CMath::Sqr(1.0/(double)nc-1); - cvrms=cvrms+(sl-w)*CMath::Sqr(1.0/(double)nc); - } - //--- check - if(sr>1) - { - w=cntbuf[nc+i]; - cvrms=cvrms+w*CMath::Sqr((w-1)/(sr-1)-1); - cvrms=cvrms+(sr-w)*CMath::Sqr(w/(sr-1)); - } - else - { - w=cntbuf[nc+i]; - cvrms=cvrms+w*CMath::Sqr(1.0/(double)nc-1); - cvrms=cvrms+(sr-w)*CMath::Sqr(1.0/(double)nc); - } - } - //--- change value - cvrms=MathSqrt(cvrms/(nc*n)); - } - } -//--- Calculate threshold. -//--- Code is a bit complicated because there can be such -//--- numbers that 0.5(A+B) equals to A or B (if A-B=epsilon) - threshold=0.5*(a[tiesbuf[koptimal]]+a[tiesbuf[koptimal+1]]); -//--- check - if(threshold<=a[tiesbuf[koptimal]]) - threshold=a[tiesbuf[koptimal+1]]; - } -//+------------------------------------------------------------------+ -//| Automatic non-optimal discretization, internal subroutine. | -//+------------------------------------------------------------------+ -static void CBdSS::DSSplitK(double &ca[],int &cc[],const int n,const int nc, - int kmax,int &info,double &thresholds[],int &ni, - double &cve) - { -//--- create variables - int i=0; - int j=0; - int j1=0; - int k=0; - int tiecount=0; - double v2=0; - int bestk=0; - double bestcve=0; - double curcve=0; -//--- creating arrays - int ties[]; - int p1[]; - int p2[]; - int cnt[]; - int bestsizes[]; - int cursizes[]; - double a[]; - int c[]; -//--- copy - ArrayCopy(a,ca); - ArrayCopy(c,cc); -//--- initialization - info=0; - ni=0; - cve=0; -//--- Test for errors in inputs - if((n<=0 || nc<2) || kmax<2) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(c[i]<0 || c[i]>=nc) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Tie - DSTie(a,n,ties,tiecount,p1,p2); -//--- swap - for(i=0;i<=n-1;i++) - { - //--- check - if(p2[i]!=i) - { - k=c[i]; - c[i]=c[p2[i]]; - c[p2[i]]=k; - } - } -//--- Special cases - if(tiecount==1) - { - info=-3; - return; - } -//--- General case: -//--- 0. allocate arrays - kmax=MathMin(kmax,tiecount); -//--- allocation - ArrayResizeAL(bestsizes,kmax); - ArrayResizeAL(cursizes,kmax); - ArrayResizeAL(cnt,nc); -//--- General case: -//--- 1. prepare "weak" solution (two subintervals,divided at median) - v2=CMath::m_maxrealnumber; - j=-1; - for(i=1;i<=tiecount-1;i++) - { - //--- check - if(MathAbs(ties[i]-0.5*(n-1))0,__FUNCTION__+": internal error #1!")) - return; -//--- change values - bestk=2; - bestsizes[0]=ties[j]; - bestsizes[1]=n-j; - bestcve=0; -//--- calculation - for(i=0;i<=nc-1;i++) - cnt[i]=0; - for(i=0;i<=j-1;i++) - TieAddC(c,ties,i,nc,cnt); - bestcve=bestcve+GetCV(cnt,nc); -//--- calculation - for(i=0;i<=nc-1;i++) - cnt[i]=0; - for(i=j;i<=tiecount-1;i++) - TieAddC(c,ties,i,nc,cnt); - bestcve=bestcve+GetCV(cnt,nc); -//--- General case: -//--- 2. Use greedy algorithm to find sub-optimal split in O(KMax*N) time - for(k=2;k<=kmax;k++) - { - //--- Prepare greedy K-interval split - for(i=0;i<=k-1;i++) - cursizes[i]=0; - //--- change values - i=0; - j=0; - //--- cycle - while(j<=tiecount-1 && i<=k-1) - { - //--- Rule: I-th bin is empty,fill it - if(cursizes[i]==0) - { - cursizes[i]=ties[j+1]-ties[j]; - j=j+1; - continue; - } - //--- Rule: (K-1-I) bins left,(K-1-I) ties left (1 tie per bin);next bin - if(tiecount-j==k-1-i) - { - i=i+1; - continue; - } - //--- Rule: last bin,always place in current - if(i==k-1) - { - cursizes[i]=cursizes[i]+ties[j+1]-ties[j]; - j=j+1; - continue; - } - //--- Place J-th tie in I-th bin,or leave for I+1-th bin. - if(MathAbs(cursizes[i]+ties[j+1]-ties[j]-(double)n/(double)k)=nc) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Tie - DSTie(a,n,ties,tiecount,p1,p2); -//--- swap - for(i=0;i<=n-1;i++) - { - //--- check - if(p2[i]!=i) - { - k=c[i]; - c[i]=c[p2[i]]; - c[p2[i]]=k; - } - } -//--- Special cases - if(tiecount==1) - { - info=-3; - return; - } -//--- General case -//--- Use dynamic programming to find best split in O(KMax*NC*TieCount^2) time - kmax=MathMin(kmax,tiecount); -//--- allocation - cv.Resize(kmax,tiecount); - splits.Resize(kmax,tiecount); - ArrayResizeAL(cnt,nc); - ArrayResizeAL(cnt2,nc); -//--- calculation - for(j=0;j<=nc-1;j++) - cnt[j]=0; - for(j=0;j<=tiecount-1;j++) - { - TieAddC(c,ties,j,nc,cnt); - splits[0].Set(j,0); - cv[0].Set(j,GetCV(cnt,nc)); - } - for(k=1;k<=kmax-1;k++) - { - for(j=0;j<=nc-1;j++) - cnt[j]=0; - //--- Subtask size J in [K..TieCount-1]: - //--- optimal K-splitting on ties from 0-th to J-th. - for(j=k;j<=tiecount-1;j++) - { - //--- Update Cnt - let it contain classes of ties from K-th to J-th - TieAddC(c,ties,j,nc,cnt); - //--- Search for optimal split point S in [K..J] - for(i=0;i<=nc-1;i++) - cnt2[i]=cnt[i]; - cv[k].Set(j,cv[k-1][j-1]+GetCV(cnt2,nc)); - splits[k].Set(j,j); - //--- calculation - for(s=k+1;s<=j;s++) - { - //--- Update Cnt2 - let it contain classes of ties from S-th to J-th - TieSubC(c,ties,s-1,nc,cnt2); - //--- Calculate CVE - cvtemp=cv[k-1][s-1]+GetCV(cnt2,nc); - //--- check - if(cvtemp=0,__FUNCTION__+": internal error #1!")) - return; -//--- check - if(koptimal==0) - { - //--- Special case: best partition is one big interval. - //--- Even 2-partition is not better. - //--- This is possible when dealing with "weak" predictor variables. - //--- Make binary split as close to the median as possible. - v2=CMath::m_maxrealnumber; - j=-1; - for(i=1;i<=tiecount-1;i++) - { - //--- check - if(MathAbs(ties[i]-0.5*(n-1))0,__FUNCTION__+": internal error #2!")) - return; - //--- allocation - ArrayResizeAL(thresholds,1); - //--- change values - thresholds[0]=0.5*(a[ties[j-1]]+a[ties[j]]); - ni=2; - cve=0; - //--- calculation - for(i=0;i<=nc-1;i++) - cnt[i]=0; - for(i=0;i<=j-1;i++) - TieAddC(c,ties,i,nc,cnt); - cve=cve+GetCV(cnt,nc); - for(i=0;i<=nc-1;i++) - cnt[i]=0; - for(i=j;i<=tiecount-1;i++) - TieAddC(c,ties,i,nc,cnt); - cve=cve+GetCV(cnt,nc); - } - else - { - //--- General case: 2 or more intervals - ArrayResizeAL(thresholds,koptimal); - ni=koptimal+1; - cve=cv[koptimal][tiecount-1]; - jl=splits[koptimal][tiecount-1]; - jr=tiecount-1; - //--- calculation - for(k=koptimal;k>=1;k--) - { - thresholds[k-1]=0.5*(a[ties[jl-1]]+a[ties[jl]]); - jr=jl-1; - jl=splits[k-1][jl-1]; - } - } - } -//+------------------------------------------------------------------+ -//| Internal function | -//+------------------------------------------------------------------+ -static double CBdSS::XLnY(const double x,const double y) - { -//--- check - if(x==0.0) - return(0); -//--- return result - return(x*MathLog(y)); - } -//+------------------------------------------------------------------+ -//| Internal function, | -//| returns number of samples of class I in Cnt[I] | -//+------------------------------------------------------------------+ -static double CBdSS::GetCV(int &cnt[],const int nc) - { -//--- create variables - double result=0; - int i=0; - double s=0; -//--- calculation - s=0; - for(i=0;i<=nc-1;i++) - s=s+cnt[i]; -//--- get result - result=0; - for(i=0;i<=nc-1;i++) - result=result-XLnY(cnt[i],cnt[i]/(s+nc-1)); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal function,adds number of samples of class I in tie NTie | -//| to Cnt[I] | -//+------------------------------------------------------------------+ -static void CBdSS::TieAddC(int &c[],int &ties[],const int ntie,const int nc, - int &cnt[]) - { -//--- create a variable - int i=0; -//--- calculation - for(i=ties[ntie];i<=ties[ntie+1]-1;i++) - cnt[c[i]]=cnt[c[i]]+1; - } -//+------------------------------------------------------------------+ -//| Internal function,subtracts number of samples of class I in tie | -//| NTie to Cnt[I] | -//+------------------------------------------------------------------+ -static void CBdSS::TieSubC(int &c[],int &ties[],const int ntie,const int nc, - int &cnt[]) - { -//--- create a variable - int i=0; -//--- calculation - for(i=ties[ntie];i<=ties[ntie+1]-1;i++) - cnt[c[i]]=cnt[c[i]]-1; - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CDForest | -//+------------------------------------------------------------------+ -class CDecisionForest - { -public: - int m_nvars; - int m_nclasses; - int m_ntrees; - int m_bufsize; - double m_trees[]; - //--- constructor, destructor - CDecisionForest(void); - ~CDecisionForest(void); - //--- copy - void Copy(CDecisionForest &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDecisionForest::CDecisionForest(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDecisionForest::~CDecisionForest(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CDecisionForest::Copy(CDecisionForest &obj) - { -//--- copy variables - m_nvars=obj.m_nvars; - m_nclasses=obj.m_nclasses; - m_ntrees=obj.m_ntrees; - m_bufsize=obj.m_bufsize; -//--- copy array - ArrayCopy(m_trees,obj.m_trees); - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CDecisionForest | -//+------------------------------------------------------------------+ -class CDecisionForestShell - { -private: - CDecisionForest m_innerobj; -public: - //--- constructors, destructor - CDecisionForestShell(void); - CDecisionForestShell(CDecisionForest &obj); - ~CDecisionForestShell(void); - //--- method - CDecisionForest *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDecisionForestShell::CDecisionForestShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CDecisionForestShell::CDecisionForestShell(CDecisionForest &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDecisionForestShell::~CDecisionForestShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CDecisionForest *CDecisionForestShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CDForest | -//+------------------------------------------------------------------+ -class CDFReport - { -public: - //--- variables - double m_relclserror; - double m_avgce; - double m_rmserror; - double m_avgerror; - double m_avgrelerror; - double m_oobrelclserror; - double m_oobavgce; - double m_oobrmserror; - double m_oobavgerror; - double m_oobavgrelerror; - //--- constructor, destructor - CDFReport(void); - ~CDFReport(void); - //--- copy - void Copy(CDFReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDFReport::CDFReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDFReport::~CDFReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CDFReport::Copy(CDFReport &obj) - { -//--- copy variables - m_relclserror=obj.m_relclserror; - m_avgce=obj.m_avgce; - m_rmserror=obj.m_rmserror; - m_avgerror=obj.m_avgerror; - m_avgrelerror=obj.m_avgrelerror; - m_oobrelclserror=obj.m_oobrelclserror; - m_oobavgce=obj.m_oobavgce; - m_oobrmserror=obj.m_oobrmserror; - m_oobavgerror=obj.m_oobavgerror; - m_oobavgrelerror=obj.m_oobavgrelerror; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CDFReport | -//+------------------------------------------------------------------+ -class CDFReportShell - { -private: - CDFReport m_innerobj; -public: - //--- constructors, destructor - CDFReportShell(void); - CDFReportShell(CDFReport &obj); - ~CDFReportShell(void); - //--- methods - double GetRelClsError(void); - void SetRelClsError(const double d); - double GetAvgCE(void); - void SetAvgCE(const double d); - double GetRMSError(void); - void SetRMSError(const double d); - double GetAvgError(void); - void SetAvgError(const double d); - double GetAvgRelError(void); - void SetAvgRelError(const double d); - double GetOOBRelClsError(void); - void SetOOBRelClsError(const double d); - double GetOOBAvgCE(void); - void SetOOBAvgCE(const double d); - double GetOOBRMSError(void); - void SetOOBRMSError(const double d); - double GetOOBAvgError(void); - void SetOOBAvgError(const double d); - double GetOOBAvgRelError(void); - void SetOOBAvgRelError(const double d); - CDFReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDFReportShell::CDFReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CDFReportShell::CDFReportShell(CDFReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDFReportShell::~CDFReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable relclserror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetRelClsError(void) - { -//--- return result - return(m_innerobj.m_relclserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable relclserror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetRelClsError(const double d) - { -//--- change value - m_innerobj.m_relclserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgce | -//+------------------------------------------------------------------+ -double CDFReportShell::GetAvgCE(void) - { -//--- return result - return(m_innerobj.m_avgce); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgce | -//+------------------------------------------------------------------+ -void CDFReportShell::SetAvgCE(const double d) - { -//--- change value - m_innerobj.m_avgce=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable rmserror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetRMSError(void) - { -//--- return result - return(m_innerobj.m_rmserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable rmserror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetRMSError(const double d) - { -//--- change value - m_innerobj.m_rmserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgerror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetAvgError(void) - { -//--- return result - return(m_innerobj.m_avgerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgerror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetAvgError(const double d) - { -//--- change value - m_innerobj.m_avgerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetAvgRelError(void) - { -//--- return result - return(m_innerobj.m_avgrelerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetAvgRelError(const double d) - { -//--- change value - m_innerobj.m_avgrelerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable oobrelclserror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetOOBRelClsError(void) - { -//--- return result - return(m_innerobj.m_oobrelclserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable oobrelclserror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetOOBRelClsError(const double d) - { -//--- change value - m_innerobj.m_oobrelclserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable oobavgce | -//+------------------------------------------------------------------+ -double CDFReportShell::GetOOBAvgCE(void) - { -//--- return result - return(m_innerobj.m_oobavgce); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable oobavgce | -//+------------------------------------------------------------------+ -void CDFReportShell::SetOOBAvgCE(const double d) - { -//--- change value - m_innerobj.m_oobavgce=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable oobrmserror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetOOBRMSError(void) - { -//--- return result - return(m_innerobj.m_oobrmserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable oobrmserror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetOOBRMSError(const double d) - { -//--- change value - m_innerobj.m_oobrmserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable oobavgerror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetOOBAvgError(void) - { -//--- return result - return(m_innerobj.m_oobavgerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable oobavgerror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetOOBAvgError(const double d) - { -//--- change value - m_innerobj.m_oobavgerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable oobavgrelerror | -//+------------------------------------------------------------------+ -double CDFReportShell::GetOOBAvgRelError(void) - { -//--- return result - return(m_innerobj.m_oobavgrelerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable oobavgrelerror | -//+------------------------------------------------------------------+ -void CDFReportShell::SetOOBAvgRelError(const double d) - { -//--- change value - m_innerobj.m_oobavgrelerror=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CDFReport *CDFReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CDForest | -//+------------------------------------------------------------------+ -class CDFInternalBuffers - { -public: - //--- arrays - double m_treebuf[]; - int m_idxbuf[]; - double m_tmpbufr[]; - double m_tmpbufr2[]; - int m_tmpbufi[]; - int m_classibuf[]; - double m_sortrbuf[]; - double m_sortrbuf2[]; - int m_sortibuf[]; - int m_varpool[]; - bool m_evsbin[]; - double m_evssplits[]; - //--- constructor, destructor - CDFInternalBuffers(void); - ~CDFInternalBuffers(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDFInternalBuffers::CDFInternalBuffers(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDFInternalBuffers::~CDFInternalBuffers(void) - { - - } -//+------------------------------------------------------------------+ -//| Decision forest class | -//+------------------------------------------------------------------+ -class CDForest - { -private: - //--- private methods - static int DFClsError(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static void DFProcessInternal(CDecisionForest &df,const int offs,double &x[],double &y[]); - static void DFBuildTree(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int nfeatures,const int nvarsinpool,const int flags,CDFInternalBuffers &bufs); - static void DFBuildTreeRec(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int nfeatures,int nvarsinpool,const int flags,int &numprocessed,const int idx1,const int idx2,CDFInternalBuffers &bufs); - static void DFSplitC(double &x[],int &c[],int &cntbuf[],const int n,const int nc,const int flags,int &info,double &threshold,double &e,double &sortrbuf[],int &sortibuf[]); - static void DFSplitR(double &x[],double &y[],const int n,const int flags,int &info,double &threshold,double &e,double &sortrbuf[],double &sortrbuf2[]); -public: - //--- class constants - static const int m_innernodewidth; - static const int m_leafnodewidth; - static const int m_dfusestrongsplits; - static const int m_dfuseevs; - static const int m_dffirstversion; - //--- constructor, destructor - CDForest(void); - ~CDForest(void); - //--- public methods - static void DFBuildRandomDecisionForest(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,const double r,int &info,CDecisionForest &df,CDFReport &rep); - static void DFBuildRandomDecisionForestX1(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,const int nrndvars,const double r,int &info,CDecisionForest &df,CDFReport &rep); - static void DFBuildInternal(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,const int samplesize,const int nfeatures,const int flags,int &info,CDecisionForest &df,CDFReport &rep); - static void DFProcess(CDecisionForest &df,double &x[],double &y[]); - static void DFProcessI(CDecisionForest &df,double &x[],double &y[]); - static double DFRelClsError(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static double DFAvgCE(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static double DFRMSError(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static double DFAvgError(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static double DFAvgRelError(CDecisionForest &df,CMatrixDouble &xy,const int npoints); - static void DFCopy(CDecisionForest &df1,CDecisionForest &df2); - static void DFAlloc(CSerializer &s,CDecisionForest &forest); - static void DFSerialize(CSerializer &s,CDecisionForest &forest); - static void DFUnserialize(CSerializer &s,CDecisionForest &forest); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CDForest::m_innernodewidth=3; -const int CDForest::m_leafnodewidth=2; -const int CDForest::m_dfusestrongsplits=1; -const int CDForest::m_dfuseevs=2; -const int CDForest::m_dffirstversion=0; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDForest::CDForest(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDForest::~CDForest(void) - { - - } -//+------------------------------------------------------------------+ -//| This subroutine builds random decision forest. | -//| INPUT PARAMETERS: | -//| XY - training set | -//| NPoints - training set size, NPoints>=1 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - task type: | -//| * NClasses=1 - regression task with one | -//| dependent variable | -//| * NClasses>1 - classification task with | -//| NClasses classes. | -//| NTrees - number of trees in a forest, NTrees>=1. | -//| recommended values: 50-100. | -//| R - percent of a training set used to build | -//| individual trees. 01). | -//| * 1, if task has been solved | -//| DF - model built | -//| Rep - training report, contains error on a training| -//| set and out-of-bag estimates of | -//| generalization error. | -//+------------------------------------------------------------------+ -static void CDForest::DFBuildRandomDecisionForest(CMatrixDouble &xy, - const int npoints, - const int nvars, - const int nclasses, - const int ntrees, - const double r,int &info, - CDecisionForest &df, - CDFReport &rep) - { -//--- create a variable - int samplesize=0; -//--- initialization - info=0; -//--- check - if(r<=0.0 || r>1.0) - { - info=-1; - return; - } -//--- calculation - samplesize=(int)(MathMax((int)MathRound(r*npoints),1)); -//--- function call - DFBuildInternal(xy,npoints,nvars,nclasses,ntrees,samplesize,(int)(MathMax(nvars/2,1)),m_dfusestrongsplits+m_dfuseevs,info,df,rep); - } -//+------------------------------------------------------------------+ -//| This subroutine builds random decision forest. | -//| This function gives ability to tune number of variables used when| -//| choosing best split. | -//| INPUT PARAMETERS: | -//| XY - training set | -//| NPoints - training set size, NPoints>=1 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - task type: | -//| * NClasses=1 - regression task with one | -//| dependent variable | -//| * NClasses>1 - classification task with | -//| NClasses classes. | -//| NTrees - number of trees in a forest, NTrees>=1. | -//| recommended values: 50-100. | -//| NRndVars - number of variables used when choosing best | -//| split | -//| R - percent of a training set used to build | -//| individual trees. 01). | -//| * 1, if task has been solved | -//| DF - model built | -//| Rep - training report, contains error on a training| -//| set and out-of-bag estimates of | -//| generalization error. | -//+------------------------------------------------------------------+ -static void CDForest::DFBuildRandomDecisionForestX1(CMatrixDouble &xy, - const int npoints, - const int nvars, - const int nclasses, - const int ntrees, - const int nrndvars, - const double r,int &info, - CDecisionForest &df, - CDFReport &rep) - { -//--- create a variable - int samplesize=0; -//--- initialization - info=0; -//--- check - if(r<=0.0 || r>1.0) - { - info=-1; - return; - } -//--- check - if(nrndvars<=0 || nrndvars>nvars) - { - info=-1; - return; - } -//--- calculation - samplesize=(int)(MathMax((int)MathRound(r*npoints),1)); -//--- function call - DFBuildInternal(xy,npoints,nvars,nclasses,ntrees,samplesize,nrndvars,m_dfusestrongsplits+m_dfuseevs,info,df,rep); - } -//+------------------------------------------------------------------+ -//| Class method | -//+------------------------------------------------------------------+ -static void CDForest::DFBuildInternal(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - const int ntrees,const int samplesize, - const int nfeatures,const int flags, - int &info,CDecisionForest &df, - CDFReport &rep) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int tmpi=0; - int lasttreeoffs=0; - int offs=0; - int ooboffs=0; - int treesize=0; - int nvarsinpool=0; - bool useevs; - int oobcnt=0; - int oobrelcnt=0; - double v=0; - double vmin=0; - double vmax=0; - bool bflag; - int i_=0; - int i1_=0; -//--- creating arrays - int permbuf[]; - double oobbuf[]; - int oobcntbuf[]; - double x[]; - double y[]; -//--- create matrix - CMatrixDouble xys; -//--- create object of class - CDFInternalBuffers bufs; -//--- initialization - info=0; -//--- Test for inputs - if(npoints<1 || samplesize<1 || samplesize>npoints || nvars<1 || nclasses<1 || ntrees<1 || nfeatures<1) - { - info=-1; - return; - } -//--- check - if(nclasses>1) - { - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][nvars])<0 || (int)MathRound(xy[i][nvars])>=nclasses) - { - info=-2; - return; - } - } - } -//--- change value - info=1; -//--- Flags - useevs=flags/m_dfuseevs%2!=0; -//--- Allocate data,prepare header - treesize=1+m_innernodewidth*(samplesize-1)+m_leafnodewidth*samplesize; -//--- allocation - ArrayResizeAL(permbuf,npoints); - ArrayResizeAL(bufs.m_treebuf,treesize); - ArrayResizeAL(bufs.m_idxbuf,npoints); - ArrayResizeAL(bufs.m_tmpbufr,npoints); - ArrayResizeAL(bufs.m_tmpbufr2,npoints); - ArrayResizeAL(bufs.m_tmpbufi,npoints); - ArrayResizeAL(bufs.m_sortrbuf,npoints); - ArrayResizeAL(bufs.m_sortrbuf2,npoints); - ArrayResizeAL(bufs.m_sortibuf,npoints); - ArrayResizeAL(bufs.m_varpool,nvars); - ArrayResizeAL(bufs.m_evsbin,nvars); - ArrayResizeAL(bufs.m_evssplits,nvars); - ArrayResizeAL(bufs.m_classibuf,2*nclasses); - ArrayResizeAL(oobbuf,nclasses*npoints); - ArrayResizeAL(oobcntbuf,npoints); - ArrayResizeAL(df.m_trees,ntrees*treesize); - xys.Resize(samplesize,nvars+1); - ArrayResizeAL(x,nvars); - ArrayResizeAL(y,nclasses); -//--- initialization - for(i=0;i<=npoints-1;i++) - permbuf[i]=i; - for(i=0;i<=npoints*nclasses-1;i++) - oobbuf[i]=0; - for(i=0;i<=npoints-1;i++) - oobcntbuf[i]=0; -//--- Prepare variable pool and EVS (extended variable selection/splitting) buffers -//--- (whether EVS is turned on or not): -//--- 1. detect binary variables and pre-calculate splits for them -//--- 2. detect variables with non-distinct values and exclude them from pool - for(i=0;i<=nvars-1;i++) - bufs.m_varpool[i]=i; - nvarsinpool=nvars; -//--- check - if(useevs) - { - for(j=0;j<=nvars-1;j++) - { - vmin=xy[0][j]; - vmax=vmin; - //--- calculation - for(i=0;i<=npoints-1;i++) - { - v=xy[i][j]; - vmin=MathMin(vmin,v); - vmax=MathMax(vmax,v); - } - //--- check - if(vmin==vmax) - { - //--- exclude variable from pool - bufs.m_varpool[j]=bufs.m_varpool[nvarsinpool-1]; - bufs.m_varpool[nvarsinpool-1]=-1; - nvarsinpool=nvarsinpool-1; - continue; - } - //--- change value - bflag=false; - for(i=0;i<=npoints-1;i++) - { - v=xy[i][j]; - //--- check - if(v!=vmin&&v!=vmax) - { - bflag=true; - break; - } - } - //--- check - if(bflag) - { - //--- non-binary variable - bufs.m_evsbin[j]=false; - } - else - { - //--- Prepare - bufs.m_evsbin[j]=true; - bufs.m_evssplits[j]=0.5*(vmin+vmax); - //--- check - if(bufs.m_evssplits[j]<=vmin) - bufs.m_evssplits[j]=vmax; - } - } - } -//--- RANDOM FOREST FORMAT -//--- W[0] - size of array -//--- W[1] - version number -//--- W[2] - NVars -//--- W[3] - NClasses (1 for regression) -//--- W[4] - NTrees -//--- W[5] - trees offset -//--- TREE FORMAT -//--- W[Offs] - size of sub-array -//--- node info: -//--- W[K+0] - variable number (-1 for leaf mode) -//--- W[K+1] - threshold (class/value for leaf node) -//--- W[K+2] - ">=" branch index (absent for leaf node) - df.m_nvars=nvars; - df.m_nclasses=nclasses; - df.m_ntrees=ntrees; -//--- Build forest - offs=0; - for(i=0;i<=ntrees-1;i++) - { - //--- Prepare sample - for(k=0;k<=samplesize-1;k++) - { - //--- calculation - j=k+CMath::RandomInteger(npoints-k); - tmpi=permbuf[k]; - permbuf[k]=permbuf[j]; - permbuf[j]=tmpi; - j=permbuf[k]; - for(i_=0;i_<=nvars;i_++) - xys[k].Set(i_,xy[j][i_]); - } - //--- build tree,copy - DFBuildTree(xys,samplesize,nvars,nclasses,nfeatures,nvarsinpool,flags,bufs); - //--- calculation - j=(int)MathRound(bufs.m_treebuf[0]); - i1_=-offs; - for(i_=offs;i_<=offs+j-1;i_++) - df.m_trees[i_]=bufs.m_treebuf[i_+i1_]; - lasttreeoffs=offs; - offs=offs+j; - //--- OOB estimates - for(k=samplesize;k<=npoints-1;k++) - { - for(j=0;j<=nclasses-1;j++) - y[j]=0; - j=permbuf[k]; - for(i_=0;i_<=nvars-1;i_++) - x[i_]=xy[j][i_]; - //--- function call - DFProcessInternal(df,lasttreeoffs,x,y); - //--- calculation - i1_=-j*nclasses; - for(i_=j*nclasses;i_<=(j+1)*nclasses-1;i_++) - oobbuf[i_]=oobbuf[i_]+y[i_+i1_]; - oobcntbuf[j]=oobcntbuf[j]+1; - } - } - df.m_bufsize=offs; -//--- Normalize OOB results - for(i=0;i<=npoints-1;i++) - { - //--- check - if(oobcntbuf[i]!=0) - { - v=1.0/(double)oobcntbuf[i]; - for(i_=i*nclasses;i_<=i*nclasses+nclasses-1;i_++) - oobbuf[i_]=v*oobbuf[i_]; - } - } -//--- Calculate training set estimates - rep.m_relclserror=DFRelClsError(df,xy,npoints); - rep.m_avgce=DFAvgCE(df,xy,npoints); - rep.m_rmserror=DFRMSError(df,xy,npoints); - rep.m_avgerror=DFAvgError(df,xy,npoints); - rep.m_avgrelerror=DFAvgRelError(df,xy,npoints); -//--- Calculate OOB estimates. - rep.m_oobrelclserror=0; - rep.m_oobavgce=0; - rep.m_oobrmserror=0; - rep.m_oobavgerror=0; - rep.m_oobavgrelerror=0; - oobcnt=0; - oobrelcnt=0; - for(i=0;i<=npoints-1;i++) - { - //--- check - if(oobcntbuf[i]!=0) - { - ooboffs=i*nclasses; - //--- check - if(nclasses>1) - { - //--- classification-specific code - k=(int)MathRound(xy[i][nvars]); - tmpi=0; - for(j=1;j<=nclasses-1;j++) - { - //--- check - if(oobbuf[ooboffs+j]>oobbuf[ooboffs+tmpi]) - tmpi=j; - } - //--- check - if(tmpi!=k) - rep.m_oobrelclserror=rep.m_oobrelclserror+1; - //--- check - if(oobbuf[ooboffs+k]!=0.0) - rep.m_oobavgce=rep.m_oobavgce-MathLog(oobbuf[ooboffs+k]); - else - rep.m_oobavgce=rep.m_oobavgce-MathLog(CMath::m_minrealnumber); - //--- calculation - for(j=0;j<=nclasses-1;j++) - { - //--- check - if(j==k) - { - rep.m_oobrmserror=rep.m_oobrmserror+CMath::Sqr(oobbuf[ooboffs+j]-1); - rep.m_oobavgerror=rep.m_oobavgerror+MathAbs(oobbuf[ooboffs+j]-1); - rep.m_oobavgrelerror=rep.m_oobavgrelerror+MathAbs(oobbuf[ooboffs+j]-1); - oobrelcnt=oobrelcnt+1; - } - else - { - rep.m_oobrmserror=rep.m_oobrmserror+CMath::Sqr(oobbuf[ooboffs+j]); - rep.m_oobavgerror=rep.m_oobavgerror+MathAbs(oobbuf[ooboffs+j]); - } - } - } - else - { - //--- regression-specific code - rep.m_oobrmserror=rep.m_oobrmserror+CMath::Sqr(oobbuf[ooboffs]-xy[i][nvars]); - rep.m_oobavgerror=rep.m_oobavgerror+MathAbs(oobbuf[ooboffs]-xy[i][nvars]); - //--- check - if(xy[i][nvars]!=0.0) - { - rep.m_oobavgrelerror=rep.m_oobavgrelerror+MathAbs((oobbuf[ooboffs]-xy[i][nvars])/xy[i][nvars]); - oobrelcnt=oobrelcnt+1; - } - } - //--- update OOB estimates count. - oobcnt=oobcnt+1; - } - } -//--- check - if(oobcnt>0) - { - //--- change values - rep.m_oobrelclserror=rep.m_oobrelclserror/oobcnt; - rep.m_oobavgce=rep.m_oobavgce/oobcnt; - rep.m_oobrmserror=MathSqrt(rep.m_oobrmserror/(oobcnt*nclasses)); - rep.m_oobavgerror=rep.m_oobavgerror/(oobcnt*nclasses); - //--- check - if(oobrelcnt>0) - rep.m_oobavgrelerror=rep.m_oobavgrelerror/oobrelcnt; - } - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| X - input vector, array[0..NVars-1]. | -//| OUTPUT PARAMETERS: | -//| Y - result. Regression estimate when solving | -//| regression task, vector of posterior | -//| probabilities for classification task. | -//| See also DFProcessI. | -//+------------------------------------------------------------------+ -static void CDForest::DFProcess(CDecisionForest &df,double &x[],double &y[]) - { -//--- create variables - int offs=0; - int i=0; - double v=0; - int i_=0; -//--- Proceed - if(CAp::Len(y)1) - { - //--- classification-specific code - k=(int)MathRound(xy[i][df.m_nvars]); - tmpi=0; - for(j=1;j<=df.m_nclasses-1;j++) - { - //--- check - if(y[j]>(double)(y[tmpi])) - tmpi=j; - } - //--- check - if(y[k]!=0.0) - result=result-MathLog(y[k]); - else - result=result-MathLog(CMath::m_minrealnumber); - } - } -//--- return result - return(result/npoints); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| root mean square error. | -//| Its meaning for regression task is obvious. As for | -//| classification task,RMS error means error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CDForest::DFRMSError(CDecisionForest &df,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int i=0; - int j=0; - int k=0; - int tmpi=0; - int i_=0; -//--- creating arrays - double x[]; - double y[]; -//--- allocation - ArrayResizeAL(x,df.m_nvars); - ArrayResizeAL(y,df.m_nclasses); -//--- initialization - result=0; - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=df.m_nvars-1;i_++) - x[i_]=xy[i][i_]; - //--- function call - DFProcess(df,x,y); - //--- check - if(df.m_nclasses>1) - { - //--- classification-specific code - k=(int)MathRound(xy[i][df.m_nvars]); - tmpi=0; - for(j=1;j<=df.m_nclasses-1;j++) - { - //--- check - if(y[j]>y[tmpi]) - tmpi=j; - } - for(j=0;j<=df.m_nclasses-1;j++) - { - //--- check - if(j==k) - result=result+CMath::Sqr(y[j]-1); - else - result=result+CMath::Sqr(y[j]); - } - } - else - { - //--- regression-specific code - result=result+CMath::Sqr(y[0]-xy[i][df.m_nvars]); - } - } -//--- return result - return(MathSqrt(result/(npoints*df.m_nclasses))); - } -//+------------------------------------------------------------------+ -//| Average error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task, it means average error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CDForest::DFAvgError(CDecisionForest &df,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int i=0; - int j=0; - int k=0; - int i_=0; -//--- creating arrays - double x[]; - double y[]; -//--- allocation - ArrayResizeAL(x,df.m_nvars); - ArrayResizeAL(y,df.m_nclasses); -//--- initialization - result=0; - for(i=0;i<=npoints-1;i++) - { - //--- copy - for(i_=0;i_<=df.m_nvars-1;i_++) - x[i_]=xy[i][i_]; - //--- function call - DFProcess(df,x,y); - //--- check - if(df.m_nclasses>1) - { - //--- classification-specific code - k=(int)MathRound(xy[i][df.m_nvars]); - for(j=0;j<=df.m_nclasses-1;j++) - { - //--- check - if(j==k) - result=result+MathAbs(y[j]-1); - else - result=result+MathAbs(y[j]); - } - } - else - { - //--- regression-specific code - result=result+MathAbs(y[0]-xy[i][df.m_nvars]); - } - } -//--- return result - return(result/(npoints*df.m_nclasses)); - } -//+------------------------------------------------------------------+ -//| Average relative error on the test set | -//| INPUT PARAMETERS: | -//| DF - decision forest model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task, it means average relative error when | -//| estimating posterior probability of belonging to the correct | -//| class. | -//+------------------------------------------------------------------+ -static double CDForest::DFAvgRelError(CDecisionForest &df,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int relcnt=0; - int i=0; - int j=0; - int k=0; - int i_=0; -//--- creating arrays - double x[]; - double y[]; -//--- allocation - ArrayResizeAL(x,df.m_nvars); - ArrayResizeAL(y,df.m_nclasses); -//--- initialization - result=0; - relcnt=0; - for(i=0;i<=npoints-1;i++) - { - //--- copy - for(i_=0;i_<=df.m_nvars-1;i_++) - x[i_]=xy[i][i_]; - //--- function call - DFProcess(df,x,y); - //--- check - if(df.m_nclasses>1) - { - //--- classification-specific code - k=(int)MathRound(xy[i][df.m_nvars]); - for(j=0;j<=df.m_nclasses-1;j++) - { - //--- check - if(j==k) - { - result=result+MathAbs(y[j]-1); - relcnt=relcnt+1; - } - } - } - else - { - //--- regression-specific code - if(xy[i][df.m_nvars]!=0.0) - { - result=result+MathAbs((y[0]-xy[i][df.m_nvars])/xy[i][df.m_nvars]); - relcnt=relcnt+1; - } - } - } -//--- check - if(relcnt>0) - result=result/relcnt; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Copying of DecisionForest strucure | -//| INPUT PARAMETERS: | -//| DF1 - original | -//| OUTPUT PARAMETERS: | -//| DF2 - copy | -//+------------------------------------------------------------------+ -static void CDForest::DFCopy(CDecisionForest &df1,CDecisionForest &df2) - { -//--- create a variable - int i_=0; -//--- change values - df2.m_nvars=df1.m_nvars; - df2.m_nclasses=df1.m_nclasses; - df2.m_ntrees=df1.m_ntrees; - df2.m_bufsize=df1.m_bufsize; -//--- allocation - ArrayResizeAL(df2.m_trees,df1.m_bufsize); -//--- copy - for(i_=0;i_<=df1.m_bufsize-1;i_++) - df2.m_trees[i_]=df1.m_trees[i_]; - } -//+------------------------------------------------------------------+ -//| Serializer: allocation | -//+------------------------------------------------------------------+ -static void CDForest::DFAlloc(CSerializer &s,CDecisionForest &forest) - { -//--- preparation to serialize - s.Alloc_Entry(); - s.Alloc_Entry(); - s.Alloc_Entry(); - s.Alloc_Entry(); - s.Alloc_Entry(); - s.Alloc_Entry(); -//--- function call - CApServ::AllocRealArray(s,forest.m_trees,forest.m_bufsize); - } -//+------------------------------------------------------------------+ -//| Serializer: serialization | -//+------------------------------------------------------------------+ -static void CDForest::DFSerialize(CSerializer &s,CDecisionForest &forest) - { -//--- serializetion - s.Serialize_Int(CSCodes::GetRDFSerializationCode()); - s.Serialize_Int(m_dffirstversion); - s.Serialize_Int(forest.m_nvars); - s.Serialize_Int(forest.m_nclasses); - s.Serialize_Int(forest.m_ntrees); - s.Serialize_Int(forest.m_bufsize); -//--- function call - CApServ::SerializeRealArray(s,forest.m_trees,forest.m_bufsize); - } -//+------------------------------------------------------------------+ -//| Serializer: unserialization | -//+------------------------------------------------------------------+ -static void CDForest::DFUnserialize(CSerializer &s,CDecisionForest &forest) - { -//--- create variables - int i0=0; - int i1=0; -//--- check correctness of header - i0=s.Unserialize_Int(); -//--- check - if(!CAp::Assert(i0==CSCodes::GetRDFSerializationCode(),__FUNCTION__+": stream header corrupted")) - return; -//--- unserializetion - i1=s.Unserialize_Int(); -//--- check - if(!CAp::Assert(i1==m_dffirstversion,__FUNCTION__+": stream header corrupted")) - return; -//--- Unserialize data - forest.m_nvars=s.Unserialize_Int(); - forest.m_nclasses=s.Unserialize_Int(); - forest.m_ntrees=s.Unserialize_Int(); - forest.m_bufsize=s.Unserialize_Int(); -//--- function call - CApServ::UnserializeRealArray(s,forest.m_trees); - } -//+------------------------------------------------------------------+ -//| Classification error | -//+------------------------------------------------------------------+ -static int CDForest::DFClsError(CDecisionForest &df,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - int result=0; - int i=0; - int j=0; - int k=0; - int tmpi=0; - int i_=0; -//--- creating arrays - double x[]; - double y[]; -//--- check - if(df.m_nclasses<=1) - return(0); -//--- allocation - ArrayResizeAL(x,df.m_nvars); - ArrayResizeAL(y,df.m_nclasses); -//--- initialization - result=0; - for(i=0;i<=npoints-1;i++) - { - //--- copy - for(i_=0;i_<=df.m_nvars-1;i_++) - x[i_]=xy[i][i_]; - //--- function call - DFProcess(df,x,y); - //--- change values - k=(int)MathRound(xy[i][df.m_nvars]); - tmpi=0; - for(j=1;j<=df.m_nclasses-1;j++) - { - //--- check - if(y[j]>(double)(y[tmpi])) - tmpi=j; - } - //--- check - if(tmpi!=k) - result=result+1; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine for processing one decision tree starting at | -//| Offs | -//+------------------------------------------------------------------+ -static void CDForest::DFProcessInternal(CDecisionForest &df,const int offs, - double &x[],double &y[]) - { -//--- create variables - int k=0; - int idx=0; -//--- Set pointer to the root - k=offs+1; -//--- Navigate through the tree - while(true) - { - //--- check - if(df.m_trees[k]==-1.0) - { - //--- check - if(df.m_nclasses==1) - y[0]=y[0]+df.m_trees[k+1]; - else - { - idx=(int)MathRound(df.m_trees[k+1]); - y[idx]=y[idx]+1; - } - //--- break the cycle - break; - } - //--- check - if(x[(int)MathRound(df.m_trees[k])]0)) - return; -//--- Prepare IdxBuf. It stores indices of the training set elements. -//--- When training set is being split,contents of IdxBuf is -//--- correspondingly reordered so we can know which elements belong -//--- to which branch of decision tree. - for(i=0;i<=npoints-1;i++) - bufs.m_idxbuf[i]=i; -//--- Recursive procedure - numprocessed=1; -//--- function call - DFBuildTreeRec(xy,npoints,nvars,nclasses,nfeatures,nvarsinpool,flags,numprocessed,0,npoints-1,bufs); -//--- change values - bufs.m_treebuf[0]=numprocessed; - } -//+------------------------------------------------------------------+ -//| Builds one decision tree (internal recursive subroutine) | -//| Parameters: | -//| TreeBuf - large enough array,at least TreeSize | -//| IdxBuf - at least NPoints elements | -//| TmpBufR - at least NPoints | -//| TmpBufR2 - at least NPoints | -//| TmpBufI - at least NPoints | -//| TmpBufI2 - at least NPoints+1 | -//+------------------------------------------------------------------+ -static void CDForest::DFBuildTreeRec(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - const int nfeatures,int nvarsinpool, - const int flags,int &numprocessed, - const int idx1,const int idx2, - CDFInternalBuffers &bufs) - { -//--- create variables - int i=0; - int j=0; - int k=0; - bool bflag; - int i1=0; - int i2=0; - int info=0; - double sl=0; - double sr=0; - double w=0; - int idxbest=0; - double ebest=0; - double tbest=0; - int varcur=0; - double s=0; - double v=0; - double v1=0; - double v2=0; - double threshold=0; - int oldnp=0; - double currms=0; - bool useevs; -//--- these initializers are not really necessary, -//--- but without them compiler complains about uninitialized locals - tbest=0; -//--- Prepare - if(!CAp::Assert(npoints>0)) - return; -//--- check - if(!CAp::Assert(idx2>=idx1)) - return; - useevs=flags/m_dfuseevs%2!=0; -//--- Leaf node - if(idx2==idx1) - { - bufs.m_treebuf[numprocessed]=-1; - bufs.m_treebuf[numprocessed+1]=xy[bufs.m_idxbuf[idx1]][nvars]; - numprocessed=numprocessed+m_leafnodewidth; - //--- exit the function - return; - } -//--- Non-leaf node. -//--- Select random variable,prepare split: -//--- 1. prepare default solution - no splitting,class at random -//--- 2. investigate possible splits,compare with default/best - idxbest=-1; -//--- check - if(nclasses>1) - { - //--- default solution for classification - for(i=0;i<=nclasses-1;i++) - bufs.m_classibuf[i]=0; - s=idx2-idx1+1; - for(i=idx1;i<=idx2;i++) - { - j=(int)MathRound(xy[bufs.m_idxbuf[i]][nvars]); - bufs.m_classibuf[j]=bufs.m_classibuf[j]+1; - } - //--- calculation - ebest=0; - for(i=0;i<=nclasses-1;i++) - ebest=ebest+bufs.m_classibuf[i]*CMath::Sqr(1-bufs.m_classibuf[i]/s)+(s-bufs.m_classibuf[i])*CMath::Sqr(bufs.m_classibuf[i]/s); - ebest=MathSqrt(ebest/(nclasses*(idx2-idx1+1))); - } - else - { - //--- default solution for regression - v=0; - for(i=idx1;i<=idx2;i++) - v=v+xy[bufs.m_idxbuf[i]][nvars]; - v=v/(idx2-idx1+1); - //--- calculation - ebest=0; - for(i=idx1;i<=idx2;i++) - ebest=ebest+CMath::Sqr(xy[bufs.m_idxbuf[i]][nvars]-v); - ebest=MathSqrt(ebest/(idx2-idx1+1)); - } -//--- change value - i=0; -//--- cycle - while(i<=MathMin(nfeatures,nvarsinpool)-1) - { - //--- select variables from pool - j=i+CMath::RandomInteger(nvarsinpool-i); - k=bufs.m_varpool[i]; - bufs.m_varpool[i]=bufs.m_varpool[j]; - bufs.m_varpool[j]=k; - varcur=bufs.m_varpool[i]; - //--- load variable values to working array - //--- apply EVS preprocessing: if all variable values are same, - //--- variable is excluded from pool. - //--- This is necessary for binary pre-splits (see later) to work. - for(j=idx1;j<=idx2;j++) - bufs.m_tmpbufr[j-idx1]=xy[bufs.m_idxbuf[j]][varcur]; - //--- check - if(useevs) - { - bflag=false; - v=bufs.m_tmpbufr[0]; - for(j=0;j<=idx2-idx1;j++) - { - //--- check - if(bufs.m_tmpbufr[j]!=v) - { - bflag=true; - break; - } - } - //--- check - if(!bflag) - { - //--- exclude variable from pool, - //--- go to the next iteration. - //--- I is not increased. - k=bufs.m_varpool[i]; - bufs.m_varpool[i]=bufs.m_varpool[nvarsinpool-1]; - bufs.m_varpool[nvarsinpool-1]=k; - nvarsinpool=nvarsinpool-1; - continue; - } - } - //--- load labels to working array - if(nclasses>1) - { - for(j=idx1;j<=idx2;j++) - bufs.m_tmpbufi[j-idx1]=(int)MathRound(xy[bufs.m_idxbuf[j]][nvars]); - } - else - { - for(j=idx1;j<=idx2;j++) - bufs.m_tmpbufr2[j-idx1]=xy[bufs.m_idxbuf[j]][nvars]; - } - //--- calculate split - if(useevs && bufs.m_evsbin[varcur]) - { - //--- Pre-calculated splits for binary variables. - //--- Threshold is already known,just calculate RMS error - threshold=bufs.m_evssplits[varcur]; - //--- check - if(nclasses>1) - { - //--- classification-specific code - for(j=0;j<=2*nclasses-1;j++) - bufs.m_classibuf[j]=0; - //--- change values - sl=0; - sr=0; - //--- calculation - for(j=0;j<=idx2-idx1;j++) - { - k=bufs.m_tmpbufi[j]; - //--- check - if(bufs.m_tmpbufr[j]1) - DFSplitC(bufs.m_tmpbufr,bufs.m_tmpbufi,bufs.m_classibuf,idx2-idx1+1,nclasses,m_dfusestrongsplits,info,threshold,currms,bufs.m_sortrbuf,bufs.m_sortibuf); - else - DFSplitR(bufs.m_tmpbufr,bufs.m_tmpbufr2,idx2-idx1+1,m_dfusestrongsplits,info,threshold,currms,bufs.m_sortrbuf,bufs.m_sortrbuf2); - } - //--- check - if(info>0) - { - //--- check - if(currms<=ebest) - { - ebest=currms; - idxbest=varcur; - tbest=threshold; - } - } - //--- Next iteration - i=i+1; - } -//--- to split or not to split - if(idxbest<0) - { - //--- All values are same,cannot split. - bufs.m_treebuf[numprocessed]=-1; - //--- check - if(nclasses>1) - { - //--- Select random class label (randomness allows us to - //--- approximate distribution of the classes) - bufs.m_treebuf[numprocessed+1]=(int)MathRound(xy[bufs.m_idxbuf[idx1+CMath::RandomInteger(idx2-idx1+1)]][nvars]); - } - else - { - //--- Select average (for regression task). - v=0; - for(i=idx1;i<=idx2;i++) - v=v+xy[bufs.m_idxbuf[i]][nvars]/(idx2-idx1+1); - bufs.m_treebuf[numprocessed+1]=v; - } - //--- change value - numprocessed=numprocessed+m_leafnodewidth; - } - else - { - //--- we can split - bufs.m_treebuf[numprocessed]=idxbest; - bufs.m_treebuf[numprocessed+1]=tbest; - i1=idx1; - i2=idx2; - //--- cycle - while(i1<=i2) - { - //--- Reorder indices so that left partition is in [Idx1..I1-1], - //--- and right partition is in [I2+1..Idx2] - if(xy[bufs.m_idxbuf[i1]][idxbest]=tbest) - { - i2=i2-1; - continue; - } - //--- change values - j=bufs.m_idxbuf[i1]; - bufs.m_idxbuf[i1]=bufs.m_idxbuf[i2]; - bufs.m_idxbuf[i2]=j; - i1=i1+1; - i2=i2-1; - } - //--- change values - oldnp=numprocessed; - numprocessed=numprocessed+m_innernodewidth; - //--- function call - DFBuildTreeRec(xy,npoints,nvars,nclasses,nfeatures,nvarsinpool,flags,numprocessed,idx1,i1-1,bufs); - bufs.m_treebuf[oldnp+2]=numprocessed; - //--- function call - DFBuildTreeRec(xy,npoints,nvars,nclasses,nfeatures,nvarsinpool,flags,numprocessed,i2+1,idx2,bufs); - } - } -//+------------------------------------------------------------------+ -//| Makes split on attribute | -//+------------------------------------------------------------------+ -static void CDForest::DFSplitC(double &x[],int &c[],int &cntbuf[],const int n, - const int nc,const int flags,int &info, - double &threshold,double &e,double &sortrbuf[], - int &sortibuf[]) - { -//--- create variables - int i=0; - int neq=0; - int nless=0; - int ngreater=0; - int q=0; - int qmin=0; - int qmax=0; - int qcnt=0; - double cursplit=0; - int nleft=0; - double v=0; - double cure=0; - double w=0; - double sl=0; - double sr=0; -//--- initialization - info=0; - threshold=0; - e=0; -//--- function call - CTSort::TagSortFastI(x,c,sortrbuf,sortibuf,n); -//--- change values - e=CMath::m_maxrealnumber; - threshold=0.5*(x[0]+x[n-1]); - info=-3; -//--- check - if(flags/m_dfusestrongsplits%2==0) - { - //--- weak splits,split at half - qcnt=2; - qmin=1; - qmax=1; - } - else - { - //--- strong splits: choose best quartile - qcnt=4; - qmin=1; - qmax=3; - } - for(q=qmin;q<=qmax;q++) - { - //--- change values - cursplit=x[n*q/qcnt]; - neq=0; - nless=0; - ngreater=0; - //--- calculation - for(i=0;i<=n-1;i++) - { - //--- check - if(x[i]cursplit) - ngreater=ngreater+1; - } - //--- check - if(!CAp::Assert(neq!=0,__FUNCTION__+": NEq=0,something strange!!!")) - return; - //--- check - if(nless!=0 || ngreater!=0) - { - //--- set threshold between two partitions, with - //--- some tweaking to avoid problems with floating point - //--- arithmetics. - //--- The problem is that when you calculates C = 0.5*(A+B) there - //--- can be no C which lies strictly between A and B (for example, - //--- there is no floating point number which is - //--- greater than 1 and less than 1+eps). In such situations - //--- we choose right side as theshold (remember that - //--- points which lie on threshold falls to the right side). - if(nlesscursplit) - ngreater=ngreater+1; - } - //--- check - if(!CAp::Assert(neq!=0,__FUNCTION__+": NEq=0,something strange!!!")) - return; - //--- check - if(nless!=0 || ngreater!=0) - { - //--- set threshold between two partitions, with - //--- some tweaking to avoid problems with floating point - //--- arithmetics. - //--- The problem is that when you calculates C = 0.5*(A+B) there - //--- can be no C which lies strictly between A and B (for example, - //--- there is no floating point number which is - //--- greater than 1 and less than 1+eps). In such situations - //--- we choose right side as theshold (remember that - //--- points which lie on threshold falls to the right side). - if(nless=K | -//| NVars - number of variables, NVars>=1 | -//| K - desired number of clusters, K>=1 | -//| Restarts - number of restarts, Restarts>=1 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -3, if task is degenerate (number of | -//| distinct points is less than K) | -//| * -1, if incorrect | -//| NPoints/NFeatures/K/Restarts was passed| -//| * 1, if subroutine finished successfully | -//| C - array[0..NVars-1,0..K-1].matrix whose columns| -//| store cluster's centers | -//| XYC - array[NPoints], which contains cluster | -//| indexes | -//+------------------------------------------------------------------+ -static void CKMeans::KMeansGenerate(CMatrixDouble &xy,const int npoints, - const int nvars,const int k, - const int restarts,int &info, - CMatrixDouble &c,int &xyc[]) - { -//--- create variables - int i=0; - int j=0; - double e=0; - double ebest=0; - double v=0; - int cclosest=0; - bool waschanges; - bool zerosizeclusters; - int pass=0; - int i_=0; - double dclosest=0; -//--- creating arrays - int xycbest[]; - double x[]; - double tmp[]; - double d2[]; - double p[]; - int csizes[]; - bool cbusy[]; - double work[]; -//--- create matrix - CMatrixDouble ct; - CMatrixDouble ctbest; -//--- initialization - info=0; -//--- Test parameters - if(npoints=0 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - number of classes, NClasses>=2 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -4, if internal EVD subroutine hasn't | -//| converged | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, NVars<1, NClasses<2) | -//| * 1, if task has been solved | -//| * 2, if there was a multicollinearity in | -//| training set, but task has been solved.| -//| W - linear combination coefficients, | -//| array[0..NVars-1] | -//+------------------------------------------------------------------+ -static void CLDA::FisherLDA(CMatrixDouble &xy,const int npoints, - const int nvars,const int nclasses, - int &info,double &w[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixDouble w2; -//--- initialization - info=0; -//--- function call - FisherLDAN(xy,npoints,nvars,nclasses,info,w2); -//--- check - if(info>0) - { - //--- allocation - ArrayResizeAL(w,nvars); - //--- copy - for(i_=0;i_<=nvars-1;i_++) - w[i_]=w2[i_][0]; - } - } -//+------------------------------------------------------------------+ -//| N-dimensional multiclass Fisher LDA | -//| Subroutine finds coefficients of linear combinations which | -//| optimally separates | -//| training set on classes. It returns N-dimensional basis whose | -//| vector are sorted | -//| by quality of training set separation (in descending order). | -//| INPUT PARAMETERS: | -//| XY - training set, array[0..NPoints-1,0..NVars]. | -//| First NVars columns store values of | -//| independent variables, next column stores | -//| number of class (from 0 to NClasses-1) which | -//| dataset element belongs to. Fractional values| -//| are rounded to nearest integer. | -//| NPoints - training set size, NPoints>=0 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - number of classes, NClasses>=2 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -4, if internal EVD subroutine hasn't | -//| converged | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, NVars<1, NClasses<2) | -//| * 1, if task has been solved | -//| * 2, if there was a multicollinearity in | -//| training set, but task has been solved.| -//| W - basis, array[0..NVars-1,0..NVars-1] | -//| columns of matrix stores basis vectors, | -//| sorted by quality of training set separation | -//| (in descending order) | -//+------------------------------------------------------------------+ -static void CLDA::FisherLDAN(CMatrixDouble &xy,const int npoints,const int nvars, - const int nclasses,int &info,CMatrixDouble &w) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int m=0; - double v=0; - int i_=0; -//--- creating arrays - int c[]; - double mu[]; - int nc[]; - double tf[]; - double d[]; - double d2[]; - double work[]; -//--- create matrix - CMatrixDouble muc; - CMatrixDouble sw; - CMatrixDouble st; - CMatrixDouble z; - CMatrixDouble z2; - CMatrixDouble tm; - CMatrixDouble sbroot; - CMatrixDouble a; - CMatrixDouble xyproj; - CMatrixDouble wproj; -//--- initialization - info=0; -//--- Test data - if((npoints<0 || nvars<1) || nclasses<2) - { - info=-1; - return; - } - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][nvars])<0 || (int)MathRound(xy[i][nvars])>=nclasses) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Special case: NPoints<=1 -//--- Degenerate task. - if(npoints<=1) - { - info=2; - //--- allocation - w.Resize(nvars,nvars); - //--- initialization - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - { - //--- check - if(i==j) - w[i].Set(j,1); - else - w[i].Set(j,0); - } - } - //--- exit the function - return; - } -//--- Prepare temporaries - ArrayResizeAL(tf,nvars); - ArrayResizeAL(work,MathMax(nvars,npoints)+1); -//--- Convert class labels from reals to integers (just for convenience) - ArrayResizeAL(c,npoints); - for(i=0;i<=npoints-1;i++) - c[i]=(int)MathRound(xy[i][nvars]); -//--- Calculate class sizes and means - ArrayResizeAL(mu,nvars); - muc.Resize(nclasses,nvars); - ArrayResizeAL(nc,nclasses); - for(j=0;j<=nvars-1;j++) - mu[j]=0; - for(i=0;i<=nclasses-1;i++) - { - nc[i]=0; - for(j=0;j<=nvars-1;j++) - muc[i].Set(j,0); - } -//--- calculation - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=nvars-1;i_++) - mu[i_]=mu[i_]+xy[i][i_]; - for(i_=0;i_<=nvars-1;i_++) - muc[c[i]].Set(i_,muc[c[i]][i_]+xy[i][i_]); - nc[c[i]]=nc[c[i]]+1; - } - for(i=0;i<=nclasses-1;i++) - { - v=1.0/(double)nc[i]; - for(i_=0;i_<=nvars-1;i_++) - muc[i].Set(i_,v*muc[i][i_]); - } -//--- change values - v=1.0/(double)npoints; - for(i_=0;i_<=nvars-1;i_++) - mu[i_]=v*mu[i_]; -//--- Create ST matrix - st.Resize(nvars,nvars); - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - st[i].Set(j,0); - } -//--- calculation - for(k=0;k<=npoints-1;k++) - { - for(i_=0;i_<=nvars-1;i_++) - tf[i_]=xy[k][i_]; - for(i_=0;i_<=nvars-1;i_++) - tf[i_]=tf[i_]-mu[i_]; - for(i=0;i<=nvars-1;i++) - { - v=tf[i]; - for(i_=0;i_<=nvars-1;i_++) - st[i].Set(i_,st[i][i_]+v*tf[i_]); - } - } -//--- Create SW matrix - sw.Resize(nvars,nvars); - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - sw[i].Set(j,0); - } -//--- calculation - for(k=0;k<=npoints-1;k++) - { - for(i_=0;i_<=nvars-1;i_++) - tf[i_]=xy[k][i_]; - for(i_=0;i_<=nvars-1;i_++) - tf[i_]=tf[i_]-muc[c[k]][i_]; - for(i=0;i<=nvars-1;i++) - { - v=tf[i]; - for(i_=0;i_<=nvars-1;i_++) - sw[i].Set(i_,sw[i][i_]+v*tf[i_]); - } - } -//--- Maximize ratio J=(w'*ST*w)/(w'*SW*w). -//--- First,make transition from w to v such that w'*ST*w becomes v'*v: -//--- v=root(ST)*w=R*w -//--- R=root(D)*Z' -//--- w=(root(ST)^-1)*v=RI*v -//--- RI=Z*inv(root(D)) -//--- J=(v'*v)/(v'*(RI'*SW*RI)*v) -//--- ST=Z*D*Z' -//--- so we have -//--- J=(v'*v) / (v'*(inv(root(D))*Z'*SW*Z*inv(root(D)))*v)= -//=(v'*v) / (v'*A*v) - if(!CEigenVDetect::SMatrixEVD(st,nvars,1,true,d,z)) - { - info=-4; - return; - } -//--- allocation - w.Resize(nvars,nvars); -//--- check - if(d[nvars-1]<=0.0 || d[0]<=1000*CMath::m_machineepsilon*d[nvars-1]) - { - //--- Special case: D[NVars-1]<=0 - //--- Degenerate task (all variables takes the same value). - if(d[nvars-1]<=0.0) - { - info=2; - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - { - //--- check - if(i==j) - w[i].Set(j,1); - else - w[i].Set(j,0); - } - } - //--- exit the function - return; - } - //--- Special case: degenerate ST matrix,multicollinearity found. - //--- Since we know ST eigenvalues/vectors we can translate task to - //--- non-degenerate form. - //--- Let WG is orthogonal basis of the non zero variance subspace - //--- of the ST and let WZ is orthogonal basis of the zero variance - //--- subspace. - //--- Projection on WG allows us to use LDA on reduced M-dimensional - //--- subspace,N-M vectors of WZ allows us to update reduced LDA - //--- factors to full N-dimensional subspace. - m=0; - for(k=0;k<=nvars-1;k++) - { - //--- check - if(d[k]<=1000*CMath::m_machineepsilon*d[nvars-1]) - m=k+1; - } - //--- check - if(!CAp::Assert(m!=0,__FUNCTION__+": internal error #1")) - return; - //--- allocation - xyproj.Resize(npoints,nvars-m+1); - //--- function call - CBlas::MatrixMatrixMultiply(xy,0,npoints-1,0,nvars-1,false,z,0,nvars-1,m,nvars-1,false,1.0,xyproj,0,npoints-1,0,nvars-m-1,0.0,work); - for(i=0;i<=npoints-1;i++) - xyproj[i].Set(nvars-m,xy[i][nvars]); - //--- function call - FisherLDAN(xyproj,npoints,nvars-m,nclasses,info,wproj); - //--- check - if(info<0) - return; - //--- function call - CBlas::MatrixMatrixMultiply(z,0,nvars-1,m,nvars-1,false,wproj,0,nvars-m-1,0,nvars-m-1,false,1.0,w,0,nvars-1,0,nvars-m-1,0.0,work); - //--- change values - for(k=nvars-m;k<=nvars-1;k++) - { - for(i_=0;i_<=nvars-1;i_++) - w[i_].Set(k,z[i_][k-nvars+m]); - } - info=2; - } - else - { - //--- General case: no multicollinearity - tm.Resize(nvars,nvars); - a.Resize(nvars,nvars); - //--- function call - CBlas::MatrixMatrixMultiply(sw,0,nvars-1,0,nvars-1,false,z,0,nvars-1,0,nvars-1,false,1.0,tm,0,nvars-1,0,nvars-1,0.0,work); - CBlas::MatrixMatrixMultiply(z,0,nvars-1,0,nvars-1,true,tm,0,nvars-1,0,nvars-1,false,1.0,a,0,nvars-1,0,nvars-1,0.0,work); - //--- change values - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - a[i].Set(j,a[i][j]/MathSqrt(d[i]*d[j])); - } - //--- check - if(!CEigenVDetect::SMatrixEVD(a,nvars,1,true,d2,z2)) - { - info=-4; - return; - } - //--- calculation - for(k=0;k<=nvars-1;k++) - { - for(i=0;i<=nvars-1;i++) - tf[i]=z2[i][k]/MathSqrt(d[i]); - for(i=0;i<=nvars-1;i++) - { - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=z[i][i_]*tf[i_]; - w[i].Set(k,v); - } - } - } -//--- Post-processing: -//--- * normalization -//--- * converting to non-negative form,if possible - for(k=0;k<=nvars-1;k++) - { - //--- calculation - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=w[i_][k]*w[i_][k]; - v=1/MathSqrt(v); - for(i_=0;i_<=nvars-1;i_++) - w[i_].Set(k,v*w[i_][k]); - v=0; - for(i=0;i<=nvars-1;i++) - v=v+w[i][k]; - //--- check - if(v<0.0) - { - for(i_=0;i_<=nvars-1;i_++) - w[i_].Set(k,-1*w[i_][k]); - } - } - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CLinReg | -//+------------------------------------------------------------------+ -class CLinearModel - { -public: - double m_w[]; - //--- constructor, destructor - CLinearModel(void); - ~CLinearModel(void); - //--- copy - void Copy(CLinearModel &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLinearModel::CLinearModel(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLinearModel::~CLinearModel(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CLinearModel::Copy(CLinearModel &obj) - { -//--- copy array - ArrayCopy(m_w,obj.m_w); - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CLinearModel | -//+------------------------------------------------------------------+ -class CLinearModelShell - { -private: - CLinearModel m_innerobj; -public: - //--- constructors, destructor - CLinearModelShell(void); - CLinearModelShell(CLinearModel &obj); - ~CLinearModelShell(void); - //--- method - CLinearModel *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLinearModelShell::CLinearModelShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CLinearModelShell::CLinearModelShell(CLinearModel &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLinearModelShell::~CLinearModelShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CLinearModel *CLinearModelShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| LRReport structure contains additional information about linear | -//| model: | -//| * C - covariation matrix, array[0..NVars,0..NVars].| -//| C[i,j] = Cov(A[i],A[j]) | -//| * RMSError - root mean square error on a training set | -//| * AvgError - average error on a training set | -//| * AvgRelError - average relative error on a training set | -//| (excluding observations with zero function | -//| value). | -//| * CVRMSError - leave-one-out cross-validation estimate of | -//| generalization error. Calculated using fast | -//| algorithm with O(NVars*NPoints) complexity. | -//| * CVAvgError - cross-validation estimate of average error | -//| * CVAvgRelError - cross-validation estimate of average relative| -//| error | -//| All other fields of the structure are intended for internal use | -//| and should not be used outside ALGLIB. | -//+------------------------------------------------------------------+ -class CLRReport - { -public: - //--- variables - double m_rmserror; - double m_avgerror; - double m_avgrelerror; - double m_cvrmserror; - double m_cvavgerror; - double m_cvavgrelerror; - int m_ncvdefects; - //--- array - int m_cvdefects[]; - //--- matrix - CMatrixDouble m_c; - //--- constructor, destructor - CLRReport(void); - ~CLRReport(void); - //--- copy - void Copy(CLRReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLRReport::CLRReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLRReport::~CLRReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CLRReport::Copy(CLRReport &obj) - { -//--- copy variables - m_rmserror=obj.m_rmserror; - m_avgerror=obj.m_avgerror; - m_avgrelerror=obj.m_avgrelerror; - m_cvrmserror=obj.m_cvrmserror; - m_cvavgerror=obj.m_cvavgerror; - m_cvavgrelerror=obj.m_cvavgrelerror; - m_ncvdefects=obj.m_ncvdefects; -//--- copy array - ArrayCopy(m_cvdefects,obj.m_cvdefects); -//--- copy matrix - m_c=obj.m_c; - } -//+------------------------------------------------------------------+ -//| LRReport structure contains additional information about linear | -//| model: | -//| * C - covariation matrix, array[0..NVars,0..NVars].| -//| C[i,j]=Cov(A[i],A[j]) | -//| * RMSError - root mean square error on a training set | -//| * AvgError - average error on a training set | -//| * AvgRelError - average relative error on a training set | -//| (excluding observations with zero function | -//| value). | -//| * CVRMSError - leave-one-out cross-validation estimate of | -//| generalization error. Calculated using fast | -//| algorithm with O(NVars*NPoints) complexity. | -//| * CVAvgError - cross-validation estimate of average error | -//| * CVAvgRelError - cross-validation estimate of average relative| -//| error | -//| All other fields of the structure are intended for internal use | -//| and should not be used outside ALGLIB. | -//+------------------------------------------------------------------+ -class CLRReportShell - { -private: - CLRReport m_innerobj; -public: - //--- constructors, destructor - CLRReportShell(void); - CLRReportShell(CLRReport &obj); - ~CLRReportShell(void); - //--- methods - double GetRMSError(void); - void SetRMSError(const double d); - double GetAvgError(void); - void SetAvgError(const double d); - double GetAvgRelError(void); - void SetAvgRelError(const double d); - double GetCVRMSError(void); - void SetCVRMSError(const double d); - double GetCVAvgError(void); - void SetCVAvgError(const double d); - double GetCVAvgRelError(void); - void SetCVAvgRelError(const double d); - int GetNCVDEfects(void); - void SetNCVDEfects(const int i); - CLRReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLRReportShell::CLRReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CLRReportShell::CLRReportShell(CLRReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLRReportShell::~CLRReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable rmserror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetRMSError(void) - { -//--- return result - return(m_innerobj.m_rmserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable rmserror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetRMSError(const double d) - { -//--- change value - m_innerobj.m_rmserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgerror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetAvgError(void) - { -//--- return result - return(m_innerobj.m_avgerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgerror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetAvgError(const double d) - { -//--- change value - m_innerobj.m_avgerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetAvgRelError(void) - { -//--- return result - return(m_innerobj.m_avgrelerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetAvgRelError(const double d) - { -//--- change value - m_innerobj.m_avgrelerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable cvrmserror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetCVRMSError(void) - { -//--- return result - return(m_innerobj.m_cvrmserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable cvrmserror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetCVRMSError(const double d) - { -//--- change value - m_innerobj.m_cvrmserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable cvavgerror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetCVAvgError(void) - { -//--- return result - return(m_innerobj.m_cvavgerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable cvavgerror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetCVAvgError(const double d) - { -//--- change value - m_innerobj.m_cvavgerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable cvavgrelerror | -//+------------------------------------------------------------------+ -double CLRReportShell::GetCVAvgRelError(void) - { -//--- return result - return(m_innerobj.m_cvavgrelerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable cvavgrelerror | -//+------------------------------------------------------------------+ -void CLRReportShell::SetCVAvgRelError(const double d) - { -//--- change value - m_innerobj.m_cvavgrelerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ncvdefects | -//+------------------------------------------------------------------+ -int CLRReportShell::GetNCVDEfects(void) - { -//--- return result - return(m_innerobj.m_ncvdefects); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ncvdefects | -//+------------------------------------------------------------------+ -void CLRReportShell::SetNCVDEfects(const int i) - { -//--- change value - m_innerobj.m_ncvdefects=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CLRReport *CLRReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Linear regression class | -//+------------------------------------------------------------------+ -class CLinReg - { -private: - //--- private method - static void LRInternal(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModel &lm,CLRReport &ar); -public: - //--- constant - static const int m_lrvnum; - //--- constructor, destructor - CLinReg(void); - ~CLinReg(void); - //--- public methods - static void LRBuild(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModel &lm,CLRReport &ar); - static void LRBuildS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModel &lm,CLRReport &ar); - static void LRBuildZS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModel &lm,CLRReport &ar); - static void LRBuildZ(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModel &lm,CLRReport &ar); - static void LRUnpack(CLinearModel &lm,double &v[],int &nvars); - static void LRPack(double &v[],const int nvars,CLinearModel &lm); - static double LRProcess(CLinearModel &lm,double &x[]); - static double LRRMSError(CLinearModel &lm,CMatrixDouble &xy,const int npoints); - static double LRAvgError(CLinearModel &lm,CMatrixDouble &xy,const int npoints); - static double LRAvgRelError(CLinearModel &lm,CMatrixDouble &xy,const int npoints); - static void LRCopy(CLinearModel &lm1,CLinearModel &lm2); - static void LRLines(CMatrixDouble &xy,double &s[],const int n,int &info,double &a,double &b,double &vara,double &varb,double &covab,double &corrab,double &p); - static void LRLine(CMatrixDouble &xy,const int n,int &info,double &a,double &b); - }; -//+------------------------------------------------------------------+ -//| Initialize constant | -//+------------------------------------------------------------------+ -const int CLinReg::m_lrvnum=5; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLinReg::CLinReg(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLinReg::~CLinReg(void) - { - - } -//+------------------------------------------------------------------+ -//| Linear regression | -//| Subroutine builds model: | -//| Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) | -//| and model found in ALGLIB format, covariation matrix, training | -//| set errors (rms, average, average relative) and leave-one-out | -//| cross-validation estimate of the generalization error. CV | -//| estimate calculated using fast algorithm with O(NPoints*NVars) | -//| complexity. | -//| When covariation matrix is calculated standard deviations of| -//| function values are assumed to be equal to RMS error on the | -//| training set. | -//| INPUT PARAMETERS: | -//| XY - training set, array [0..NPoints-1,0..NVars]: | -//| * NVars columns - independent variables | -//| * last column - dependent variable | -//| NPoints - training set size, NPoints>NVars+1 | -//| NVars - number of independent variables | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -255, in case of unknown internal error | -//| * -4, if internal SVD subroutine haven't | -//| converged | -//| * -1, if incorrect parameters was passed | -//| (NPoints0. | -//| NPoints - training set size, NPoints>NVars+1 | -//| NVars - number of independent variables | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -255, in case of unknown internal error | -//| * -4, if internal SVD subroutine haven't | -//| converged | -//| * -1, if incorrect parameters was passed | -//| (NPointsMathSqrt(variance)) - { - //--- variation is relatively small,it is better to - //--- bring mean value to 1 - c[j]=mean; - } - else - { - //--- variation is large,it is better to bring variance to 1 - if(variance==0.0) - variance=1; - c[j]=MathSqrt(variance); - } - for(i=0;i<=npoints-1;i++) - xyi[i].Set(j,xyi[i][j]/c[j]); - } -//--- Internal processing - LRInternal(xyi,s,npoints,nvars+1,info,lm,ar); -//--- check - if(info<0) - return; -//--- Un-standartization - offs=(int)MathRound(lm.m_w[3]); - for(j=0;j<=nvars-1;j++) - { - //--- J-th term is updated - lm.m_w[offs+j]=lm.m_w[offs+j]/c[j]; - v=1/c[j]; - for(i_=0;i_<=nvars;i_++) - ar.m_c[j].Set(i_,v*ar.m_c[j][i_]); - for(i_=0;i_<=nvars;i_++) - ar.m_c[i_].Set(j,v*ar.m_c[i_][j]); - } - } -//+------------------------------------------------------------------+ -//| Like LRBuild but builds model | -//| Y=A(0)*X[0] + ... + A(N-1)*X[N-1] | -//| i.m_e. with zero constant term. | -//+------------------------------------------------------------------+ -static void CLinReg::LRBuildZ(CMatrixDouble &xy,const int npoints,const int nvars, - int &info,CLinearModel &lm,CLRReport &ar) - { -//--- create variables - int i=0; - double sigma2=0; - int i_=0; -//--- create array - double s[]; -//--- initialization - info=0; -//--- check - if(npoints<=nvars+1 || nvars<1) - { - info=-1; - return; - } -//--- allocation - ArrayResizeAL(s,npoints); - for(i=0;i<=npoints-1;i++) - s[i]=1; -//--- function call - LRBuildZS(xy,s,npoints,nvars,info,lm,ar); -//--- check - if(info<0) - return; -//--- calculation - sigma2=CMath::Sqr(ar.m_rmserror)*npoints/(npoints-nvars-1); - for(i=0;i<=nvars;i++) - { - for(i_=0;i_<=nvars;i_++) - ar.m_c[i].Set(i_,sigma2*ar.m_c[i][i_]); - } - } -//+------------------------------------------------------------------+ -//| Unpacks coefficients of linear model. | -//| INPUT PARAMETERS: | -//| LM - linear model in ALGLIB format | -//| OUTPUT PARAMETERS: | -//| V - coefficients,array[0..NVars] | -//| constant term (intercept) is stored in the | -//| V[NVars]. | -//| NVars - number of independent variables (one less | -//| than number of coefficients) | -//+------------------------------------------------------------------+ -static void CLinReg::LRUnpack(CLinearModel &lm,double &v[],int &nvars) - { -//--- create variables - int offs=0; - int i_=0; - int i1_=0; -//--- initialization - nvars=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_lrvnum,__FUNCTION__+": Incorrect LINREG version!")) - return; -//--- change values - nvars=(int)MathRound(lm.m_w[2]); - offs=(int)MathRound(lm.m_w[3]); -//--- allocation - ArrayResizeAL(v,nvars+1); -//--- calculation - i1_=offs; - for(i_=0;i_<=nvars;i_++) - v[i_]=lm.m_w[i_+i1_]; - } -//+------------------------------------------------------------------+ -//| "Packs" coefficients and creates linear model in ALGLIB format | -//| (LRUnpack reversed). | -//| INPUT PARAMETERS: | -//| V - coefficients, array[0..NVars] | -//| NVars - number of independent variables | -//| OUTPUT PAREMETERS: | -//| LM - linear model. | -//+------------------------------------------------------------------+ -static void CLinReg::LRPack(double &v[],const int nvars,CLinearModel &lm) - { -//--- create variables - int offs=0; - int i_=0; - int i1_=0; -//--- allocation - ArrayResizeAL(lm.m_w,5+nvars); -//--- change values - offs=4; - lm.m_w[0]=4+nvars+1; - lm.m_w[1]=m_lrvnum; - lm.m_w[2]=nvars; - lm.m_w[3]=offs; -//--- calculation - i1_=-offs; - for(i_=offs;i_<=offs+nvars;i_++) - lm.m_w[i_]=v[i_+i1_]; - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| LM - linear model | -//| X - input vector, array[0..NVars-1]. | -//| Result: | -//| value of linear model regression estimate | -//+------------------------------------------------------------------+ -static double CLinReg::LRProcess(CLinearModel &lm,double &x[]) - { -//--- create variables - double v=0; - int offs=0; - int nvars=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_lrvnum,__FUNCTION__+": Incorrect LINREG version!")) - return(EMPTY_VALUE); -//--- change values - nvars=(int)MathRound(lm.m_w[2]); - offs=(int)MathRound(lm.m_w[3]); - i1_=offs; - v=0.0; -//--- calculation - for(i_=0;i_<=nvars-1;i_++) - v+=x[i_]*lm.m_w[i_+i1_]; -//--- return result - return(v+lm.m_w[offs+nvars]); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| LM - linear model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| root mean square error. | -//+------------------------------------------------------------------+ -static double CLinReg::LRRMSError(CLinearModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int i=0; - double v=0; - int offs=0; - int nvars=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_lrvnum,__FUNCTION__+": Incorrect LINREG version!")) - return(EMPTY_VALUE); -//--- change values - nvars=(int)MathRound(lm.m_w[2]); - offs=(int)MathRound(lm.m_w[3]); - result=0; -//--- calculation - for(i=0;i<=npoints-1;i++) - { - i1_=offs; - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=xy[i][i_]*lm.m_w[i_+i1_]; - v=v+lm.m_w[offs+nvars]; - result=result+CMath::Sqr(v-xy[i][nvars]); - } -//--- return result - return(MathSqrt(result/npoints)); - } -//+------------------------------------------------------------------+ -//| Average error on the test set | -//| INPUT PARAMETERS: | -//| LM - linear model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| average error. | -//+------------------------------------------------------------------+ -static double CLinReg::LRAvgError(CLinearModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int i=0; - double v=0; - int offs=0; - int nvars=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_lrvnum,__FUNCTION__+": Incorrect LINREG version!")) - return(EMPTY_VALUE); -//--- initialization - nvars=(int)MathRound(lm.m_w[2]); - offs=(int)MathRound(lm.m_w[3]); - result=0; -//--- calculation - for(i=0;i<=npoints-1;i++) - { - i1_=offs; - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=xy[i][i_]*lm.m_w[i_+i1_]; - v=v+lm.m_w[offs+nvars]; - result=result+MathAbs(v-xy[i][nvars]); - } -//--- return result - return(result/npoints); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| LM - linear model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| average relative error. | -//+------------------------------------------------------------------+ -static double CLinReg::LRAvgRelError(CLinearModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int i=0; - int k=0; - double v=0; - int offs=0; - int nvars=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_lrvnum,__FUNCTION__+": Incorrect LINREG version!")) - return(EMPTY_VALUE); -//--- initialization - nvars=(int)MathRound(lm.m_w[2]); - offs=(int)MathRound(lm.m_w[3]); - result=0; - k=0; -//--- calculation - for(i=0;i<=npoints-1;i++) - { - //--- check - if(xy[i][nvars]!=0.0) - { - i1_=offs; - v=0.0; - for(i_=0;i_<=nvars-1;i_++) - v+=xy[i][i_]*lm.m_w[i_+i1_]; - v=v+lm.m_w[offs+nvars]; - //--- get result - result=result+MathAbs((v-xy[i][nvars])/xy[i][nvars]); - k=k+1; - } - } -//--- check - if(k!=0) - result=result/k; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Copying of LinearModel strucure | -//| INPUT PARAMETERS: | -//| LM1 - original | -//| OUTPUT PARAMETERS: | -//| LM2 - copy | -//+------------------------------------------------------------------+ -static void CLinReg::LRCopy(CLinearModel &lm1,CLinearModel &lm2) - { -//--- create variables - int k=0; - int i_=0; -//--- initialization - k=(int)MathRound(lm1.m_w[0]); -//--- allocation - ArrayResizeAL(lm2.m_w,k); -//--- copy - for(i_=0;i_<=k-1;i_++) - lm2.m_w[i_]=lm1.m_w[i_]; - } -//+------------------------------------------------------------------+ -//| Class method | -//+------------------------------------------------------------------+ -static void CLinReg::LRLines(CMatrixDouble &xy,double &s[],const int n, - int &info,double &a,double &b,double &vara, - double &varb,double &covab,double &corrab, - double &p) - { -//--- create variables - int i=0; - double ss=0; - double sx=0; - double sxx=0; - double sy=0; - double stt=0; - double e1=0; - double e2=0; - double t=0; - double chi2=0; -//--- initialization - info=0; - a=0; - b=0; - vara=0; - varb=0; - covab=0; - corrab=0; - p=0; -//--- check - if(n<2) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if((double)(s[i])<=0.0) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Calculate S,SX,SY,SXX - ss=0; - sx=0; - sy=0; - sxx=0; -//--- calculation - for(i=0;i<=n-1;i++) - { - t=CMath::Sqr(s[i]); - ss=ss+1/t; - sx=sx+xy[i][0]/t; - sy=sy+xy[i][1]/t; - sxx=sxx+CMath::Sqr(xy[i][0])/t; - } -//--- Test for condition number - t=MathSqrt(4*CMath::Sqr(sx)+CMath::Sqr(ss-sxx)); - e1=0.5*(ss+sxx+t); - e2=0.5*(ss+sxx-t); -//--- check - if(MathMin(e1,e2)<=1000*CMath::m_machineepsilon*MathMax(e1,e2)) - { - info=-3; - return; - } -//--- Calculate A,B - a=0; - b=0; - stt=0; -//--- calculation - for(i=0;i<=n-1;i++) - { - t=(xy[i][0]-sx/ss)/s[i]; - b=b+t*xy[i][1]/s[i]; - stt=stt+CMath::Sqr(t); - } - b=b/stt; - a=(sy-sx*b)/ss; -//--- Calculate goodness-of-fit - if(n>2) - { - chi2=0; - for(i=0;i<=n-1;i++) - chi2=chi2+CMath::Sqr((xy[i][1]-a-b*xy[i][0])/s[i]); - //--- function call - p=CIncGammaF::IncompleteGammaC((double)(n-2)/(double)2,chi2/2); - } - else - p=1; -//--- Calculate other parameters - vara=(1+CMath::Sqr(sx)/(ss*stt))/ss; - varb=1/stt; - covab=-(sx/(ss*stt)); - corrab=covab/MathSqrt(vara*varb); - } -//+------------------------------------------------------------------+ -//| Class method | -//+------------------------------------------------------------------+ -static void CLinReg::LRLine(CMatrixDouble &xy,const int n,int &info, - double &a,double &b) - { -//--- create variables - int i=0; - double vara=0; - double varb=0; - double covab=0; - double corrab=0; - double p=0; -//--- create array - double s[]; -//--- initialization - info=0; - a=0; - b=0; -//--- check - if(n<2) - { - info=-1; - return; - } -//--- allocation - ArrayResizeAL(s,n); - for(i=0;i<=n-1;i++) - s[i]=1; -//--- function call - LRLines(xy,s,n,info,a,b,vara,varb,covab,corrab,p); - } -//+------------------------------------------------------------------+ -//| Internal linear regression subroutine | -//+------------------------------------------------------------------+ -static void CLinReg::LRInternal(CMatrixDouble &xy,double &s[],const int npoints, - const int nvars,int &info,CLinearModel &lm, - CLRReport &ar) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int ncv=0; - int na=0; - int nacv=0; - double r=0; - double p=0; - double epstol=0; - int offs=0; - int i_=0; - int i1_=0; -//--- creating arrays - double b[]; - double sv[]; - double t[]; - double svi[]; - double work[]; -//--- create matrix - CMatrixDouble a; - CMatrixDouble u; - CMatrixDouble vt; - CMatrixDouble vm; - CMatrixDouble xym; -//--- create objects of classes - CLRReport ar2; - CLinearModel tlm; -//--- initialization - info=0; - epstol=1000; -//--- Check for errors in data - if(npoints=1;k--) - { - //--- check - if(sv[k-1]>epstol*CMath::m_machineepsilon*sv[0]) - { - //--- Reduce - xym.Resize(npoints,k+1); - for(i=0;i<=npoints-1;i++) - { - for(j=0;j<=k-1;j++) - { - //--- calculation - r=0.0; - for(i_=0;i_<=nvars-1;i_++) - r+=xy[i][i_]*vt[j][i_]; - xym[i].Set(j,r); - } - xym[i].Set(k,xy[i][nvars]); - } - //--- Solve - LRInternal(xym,s,npoints,k,info,tlm,ar2); - //--- check - if(info!=1) - return; - //--- Convert back to un-reduced format - for(j=0;j<=nvars-1;j++) - lm.m_w[offs+j]=0; - for(j=0;j<=k-1;j++) - { - r=tlm.m_w[offs+j]; - i1_=-offs; - for(i_=offs;i_<=offs+nvars-1;i_++) - lm.m_w[i_]=lm.m_w[i_]+r*vt[j][i_+i1_]; - } - //--- change values - ar.m_rmserror=ar2.m_rmserror; - ar.m_avgerror=ar2.m_avgerror; - ar.m_avgrelerror=ar2.m_avgrelerror; - ar.m_cvrmserror=ar2.m_cvrmserror; - ar.m_cvavgerror=ar2.m_cvavgerror; - ar.m_cvavgrelerror=ar2.m_cvavgrelerror; - ar.m_ncvdefects=ar2.m_ncvdefects; - //--- allocation - ArrayResizeAL(ar.m_cvdefects,nvars); - for(j=0;j<=ar.m_ncvdefects-1;j++) - ar.m_cvdefects[j]=ar2.m_cvdefects[j]; - //--- allocation - ar.m_c.Resize(nvars,nvars); - ArrayResizeAL(work,nvars+1); - //--- function calls - CBlas::MatrixMatrixMultiply(ar2.m_c,0,k-1,0,k-1,false,vt,0,k-1,0,nvars-1,false,1.0,vm,0,k-1,0,nvars-1,0.0,work); - CBlas::MatrixMatrixMultiply(vt,0,k-1,0,nvars-1,true,vm,0,k-1,0,nvars-1,false,1.0,ar.m_c,0,nvars-1,0,nvars-1,0.0,work); - //--- exit the function - return; - } - } - //--- change value - info=-255; - //--- exit the function - return; - } -//--- change values - for(i=0;i<=nvars-1;i++) - { - //--- check - if(sv[i]>epstol*CMath::m_machineepsilon*sv[0]) - svi[i]=1/sv[i]; - else - svi[i]=0; - } -//--- change values - for(i=0;i<=nvars-1;i++) - t[i]=0; -//--- change values - for(i=0;i<=npoints-1;i++) - { - r=b[i]; - for(i_=0;i_<=nvars-1;i_++) - t[i_]=t[i_]+r*u[i][i_]; - } - for(i=0;i<=nvars-1;i++) - lm.m_w[offs+i]=0; -//--- calculation - for(i=0;i<=nvars-1;i++) - { - r=t[i]*svi[i]; - i1_=-offs; - for(i_=offs;i_<=offs+nvars-1;i_++) - lm.m_w[i_]=lm.m_w[i_]+r*vt[i][i_+i1_]; - } -//--- calculation - for(j=0;j<=nvars-1;j++) - { - r=svi[j]; - for(i_=0;i_<=nvars-1;i_++) - vm[i_].Set(j,r*vt[j][i_]); - } -//--- calculation - for(i=0;i<=nvars-1;i++) - { - for(j=i;j<=nvars-1;j++) - { - r=0.0; - for(i_=0;i_<=nvars-1;i_++) - r+=vm[i][i_]*vm[j][i_]; - ar.m_c[i].Set(j,r); - ar.m_c[j].Set(i,r); - } - } -//--- Leave-1-out cross-validation error. -//--- NOTATIONS: -//--- A design matrix -//--- A*x = b original linear least squares task -//--- U*S*V' SVD of A -//--- ai i-th row of the A -//--- bi i-th element of the b -//--- xf solution of the original LLS task -//--- Cross-validation error of i-th element from a sample is -//--- calculated using following formula: -//--- ERRi = ai*xf - (ai*xf-bi*(ui*ui'))/(1-ui*ui') (1) -//--- This formula can be derived from normal equations of the -//--- original task -//--- (A'*A)x = A'*b (2) -//--- by applying modification (zeroing out i-th row of A) to (2): -//--- (A-ai)'*(A-ai) = (A-ai)'*b -//--- and using Sherman-Morrison formula for updating matrix inverse -//--- NOTE 1: b is not zeroed out since it is much simpler and -//--- does not influence final result. -//--- NOTE 2: some design matrices A have such ui that 1-ui*ui'=0. -//--- Formula (1) can't be applied for such cases and they are skipped -//--- from CV calculation (which distorts resulting CV estimate). -//--- But from the properties of U we can conclude that there can -//--- be no more than NVars such vectors. Usually -//--- NVars << NPoints, so in a normal case it only slightly -//--- influences result. - ncv=0; - na=0; - nacv=0; - ar.m_rmserror=0; - ar.m_avgerror=0; - ar.m_avgrelerror=0; - ar.m_cvrmserror=0; - ar.m_cvavgerror=0; - ar.m_cvavgrelerror=0; - ar.m_ncvdefects=0; -//--- allocation - ArrayResizeAL(ar.m_cvdefects,nvars); - for(i=0;i<=npoints-1;i++) - { - //--- Error on a training set - i1_=offs; - r=0.0; - for(i_=0;i_<=nvars-1;i_++) - r+=xy[i][i_]*lm.m_w[i_+i1_]; - //--- change values - ar.m_rmserror=ar.m_rmserror+CMath::Sqr(r-xy[i][nvars]); - ar.m_avgerror=ar.m_avgerror+MathAbs(r-xy[i][nvars]); - //--- check - if(xy[i][nvars]!=0.0) - { - ar.m_avgrelerror=ar.m_avgrelerror+MathAbs((r-xy[i][nvars])/xy[i][nvars]); - na=na+1; - } - //--- Error using fast leave-one-out cross-validation - p=0.0; - for(i_=0;i_<=nvars-1;i_++) - p+=u[i][i_]*u[i][i_]; - //--- check - if(p>1-epstol*CMath::m_machineepsilon) - { - ar.m_cvdefects[ar.m_ncvdefects]=i; - ar.m_ncvdefects=ar.m_ncvdefects+1; - continue; - } - //--- change values - r=s[i]*(r/s[i]-b[i]*p)/(1-p); - ar.m_cvrmserror=ar.m_cvrmserror+CMath::Sqr(r-xy[i][nvars]); - ar.m_cvavgerror=ar.m_cvavgerror+MathAbs(r-xy[i][nvars]); - //--- check - if(xy[i][nvars]!=0.0) - { - ar.m_cvavgrelerror=ar.m_cvavgrelerror+MathAbs((r-xy[i][nvars])/xy[i][nvars]); - nacv=nacv+1; - } - ncv=ncv+1; - } -//--- check - if(ncv==0) - { - //--- Something strange: ALL ui are degenerate. - //--- Unexpected... - info=-255; - //--- exit the function - return; - } -//--- change values - ar.m_rmserror=MathSqrt(ar.m_rmserror/npoints); - ar.m_avgerror=ar.m_avgerror/npoints; -//--- check - if(na!=0) - ar.m_avgrelerror=ar.m_avgrelerror/na; - ar.m_cvrmserror=MathSqrt(ar.m_cvrmserror/ncv); - ar.m_cvavgerror=ar.m_cvavgerror/ncv; -//--- check - if(nacv!=0) - ar.m_cvavgrelerror=ar.m_cvavgrelerror/nacv; - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CMLPBase | -//+------------------------------------------------------------------+ -class CMultilayerPerceptron - { -public: - //--- variables - int m_hlnetworktype; - int m_hlnormtype; - //--- arrays - int m_hllayersizes[]; - int m_hlconnections[]; - int m_hlneurons[]; - int m_structinfo[]; - double m_weights[]; - double m_columnmeans[]; - double m_columnsigmas[]; - double m_neurons[]; - double m_dfdnet[]; - double m_derror[]; - double m_x[]; - double m_y[]; - double m_nwbuf[]; - int m_integerbuf[]; - //--- matrix - CMatrixDouble m_chunks; - //--- constructor, destructor - CMultilayerPerceptron(void); - ~CMultilayerPerceptron(void); - //--- copy - void Copy(CMultilayerPerceptron &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMultilayerPerceptron::CMultilayerPerceptron(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMultilayerPerceptron::~CMultilayerPerceptron(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMultilayerPerceptron::Copy(CMultilayerPerceptron &obj) - { -//--- copy variables - m_hlnetworktype=obj.m_hlnetworktype; - m_hlnormtype=obj.m_hlnormtype; -//--- copy arrays - ArrayCopy(m_hllayersizes,obj.m_hllayersizes); - ArrayCopy(m_hlconnections,obj.m_hlconnections); - ArrayCopy(m_hlneurons,obj.m_hlneurons); - ArrayCopy(m_structinfo,obj.m_structinfo); - ArrayCopy(m_weights,obj.m_weights); - ArrayCopy(m_columnmeans,obj.m_columnmeans); - ArrayCopy(m_columnsigmas,obj.m_columnsigmas); - ArrayCopy(m_neurons,obj.m_neurons); - ArrayCopy(m_dfdnet,obj.m_dfdnet); - ArrayCopy(m_derror,obj.m_derror); - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_y,obj.m_y); - ArrayCopy(m_nwbuf,obj.m_nwbuf); - ArrayCopy(m_integerbuf,obj.m_integerbuf); -//--- copy matrix - m_chunks=obj.m_chunks; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CMultilayerPerceptron | -//+------------------------------------------------------------------+ -class CMultilayerPerceptronShell - { -private: - CMultilayerPerceptron m_innerobj; -public: - //--- constructors, destructor - CMultilayerPerceptronShell(void); - CMultilayerPerceptronShell(CMultilayerPerceptron &obj); - ~CMultilayerPerceptronShell(void); - //--- method - CMultilayerPerceptron *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMultilayerPerceptronShell::CMultilayerPerceptronShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMultilayerPerceptronShell::CMultilayerPerceptronShell(CMultilayerPerceptron &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMultilayerPerceptronShell::~CMultilayerPerceptronShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMultilayerPerceptron *CMultilayerPerceptronShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Multilayer perceptron class | -//+------------------------------------------------------------------+ -class CMLPBase - { -private: - //--- private methods - static void AddInputLayer(const int ncount,int &lsizes[],int <ypes[],int &lconnfirst[],int &lconnlast[],int &lastproc); - static void AddBiasedSummatorLayer(const int ncount,int &lsizes[],int <ypes[],int &lconnfirst[],int &lconnlast[],int &lastproc); - static void AddActivationLayer(const int functype,int &lsizes[],int <ypes[],int &lconnfirst[],int &lconnlast[],int &lastproc); - static void AddZeroLayer(int &lsizes[],int <ypes[],int &lconnfirst[],int &lconnlast[],int &lastproc); - static void HLAddInputLayer(CMultilayerPerceptron &network,int &connidx,int &neuroidx,int &structinfoidx,int nin); - static void HLAddOutputLayer(CMultilayerPerceptron &network,int &connidx,int &neuroidx,int &structinfoidx,int &weightsidx,const int k,const int nprev,const int nout,const bool iscls,const bool islinearout); - static void HLAddHiddenLayer(CMultilayerPerceptron &network,int &connidx,int &neuroidx,int &structinfoidx,int &weightsidx,const int k,const int nprev,const int ncur); - static void FillHighLevelInformation(CMultilayerPerceptron &network,const int nin,const int nhid1,const int nhid2,const int nout,const bool iscls,const bool islinearout); - static void MLPCreate(const int nin,const int nout,int &lsizes[],int <ypes[],int &lconnfirst[],int &lconnlast[],const int layerscount,const bool isclsnet,CMultilayerPerceptron &network); - static void MLPHessianBatchInternal(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize,const bool naturalerr,double &e,double &grad[],CMatrixDouble &h); - static void MLPInternalCalculateGradient(CMultilayerPerceptron &network,double &neurons[],double &weights[],double &derror[],double &grad[],const bool naturalerrorfunc); - static void MLPChunkedGradient(CMultilayerPerceptron &network,CMatrixDouble &xy,const int cstart,const int csize,double &e,double &grad[],const bool naturalerrorfunc); - static double SafeCrossEntropy(const double t,const double z); -public: - //--- variables - static const int m_mlpvnum; - static const int m_mlpfirstversion; - static const int m_nfieldwidth; - static const int m_hlconm_nfieldwidth; - static const int m_hlm_nfieldwidth; - static const int m_chunksize; - //--- constructor, destructor - CMLPBase(void); - ~CMLPBase(void); - //--- public methods - static void MLPCreate0(const int nin,const int nout,CMultilayerPerceptron &network); - static void MLPCreate1(const int nin,const int nhid,const int nout,CMultilayerPerceptron &network); - static void MLPCreate2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptron &network); - static void MLPCreateB0(const int nin,const int nout,const double b,double d,CMultilayerPerceptron &network); - static void MLPCreateB1(const int nin,const int nhid,const int nout,const double b,double d,CMultilayerPerceptron &network); - static void MLPCreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,double d,CMultilayerPerceptron &network); - static void MLPCreateR0(const int nin,const int nout,const double a,const double b,CMultilayerPerceptron &network); - static void MLPCreateR1(const int nin,const int nhid,const int nout,const double a,const double b,CMultilayerPerceptron &network); - static void MLPCreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,CMultilayerPerceptron &network); - static void MLPCreateC0(const int nin,const int nout,CMultilayerPerceptron &network); - static void MLPCreateC1(const int nin,const int nhid,const int nout,CMultilayerPerceptron &network); - static void MLPCreateC2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptron &network); - static void MLPCopy(CMultilayerPerceptron &network1,CMultilayerPerceptron &network2); - static void MLPSerializeOld(CMultilayerPerceptron &network,double &ra[],int &rlen); - static void MLPUnserializeOld(double &ra[],CMultilayerPerceptron &network); - static void MLPRandomize(CMultilayerPerceptron &network); - static void MLPRandomizeFull(CMultilayerPerceptron &network); - static void MLPInitPreprocessor(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize); - static void MLPProperties(CMultilayerPerceptron &network,int &nin,int &nout,int &wcount); - static bool MLPIsSoftMax(CMultilayerPerceptron &network); - static int MLPGetLayersCount(CMultilayerPerceptron &network); - static int MLPGetLayerSize(CMultilayerPerceptron &network,const int k); - static void MLPGetInputScaling(CMultilayerPerceptron &network,const int i,double &mean,double &sigma); - static void MLPGetOutputScaling(CMultilayerPerceptron &network,const int i,double &mean,double &sigma); - static void MLPGetNeuronInfo(CMultilayerPerceptron &network,const int k,const int i,int &fkind,double &threshold); - static double MLPGetWeight(CMultilayerPerceptron &network,const int k0,const int i0,const int k1,const int i1); - static void MLPSetInputScaling(CMultilayerPerceptron &network,const int i,const double mean,double sigma); - static void MLPSetOutputScaling(CMultilayerPerceptron &network,const int i,const double mean,double sigma); - static void MLPSetNeuronInfo(CMultilayerPerceptron &network,const int k,const int i,const int fkind,const double threshold); - static void MLPSetWeight(CMultilayerPerceptron &network,const int k0,const int i0,const int k1,const int i1,const double w); - static void MLPActivationFunction(double net,const int k,double &f,double &df,double &d2f); - static void MLPProcess(CMultilayerPerceptron &network,double &x[],double &y[]); - static void MLPProcessI(CMultilayerPerceptron &network,double &x[],double &y[]); - static double MLPError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize); - static double MLPErrorN(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize); - static int MLPClsError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize); - static double MLPRelClsError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgCE(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints); - static double MLPRMSError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints); - static double MLPAvgRelError(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints); - static void MLPGrad(CMultilayerPerceptron &network,double &x[],double &desiredy[],double &e,double &grad[]); - static void MLPGradN(CMultilayerPerceptron &network,double &x[],double &desiredy[],double &e,double &grad[]); - static void MLPGradBatch(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]); - static void MLPGradNBatch(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]); - static void MLPHessianNBatch(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h); - static void MLPHessianBatch(CMultilayerPerceptron &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h); - static void MLPInternalProcessVector(int &structinfo[],double &weights[],double &columnmeans[],double &columnsigmas[],double &neurons[],double &dfdnet[],double &x[],double &y[]); - static void MLPAlloc(CSerializer &s,CMultilayerPerceptron &network); - static void MLPSerialize(CSerializer &s,CMultilayerPerceptron &network); - static void MLPUnserialize(CSerializer &s,CMultilayerPerceptron &network); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CMLPBase::m_mlpvnum=7; -const int CMLPBase::m_mlpfirstversion=0; -const int CMLPBase::m_nfieldwidth=4; -const int CMLPBase::m_hlconm_nfieldwidth=5; -const int CMLPBase::m_hlm_nfieldwidth=4; -const int CMLPBase::m_chunksize=32; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPBase::CMLPBase(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPBase::~CMLPBase(void) - { - - } -//+------------------------------------------------------------------+ -//| Creates neural network with NIn inputs, NOut outputs, | -//| without hidden layers, with linear output layer. Network weights | -//| are filled with small random values. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreate0(const int nin,const int nout, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=4; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(-5,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,0,0,nout,false,true); - } -//+------------------------------------------------------------------+ -//| Same as MLPCreate0, but with one hidden layer (NHid neurons) with| -//| non-linear activation function. Output layer is linear. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreate1(const int nin,const int nhid,const int nout, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- create variables - layerscount=7; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(-5,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid,0,nout,false,true); - } -//+------------------------------------------------------------------+ -//| Same as MLPCreate0,but with two hidden layers (NHid1 and NHid2 | -//| neurons) with non-linear activation function. Output layer is | -//| linear. | -//| $ALL | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreate2(const int nin,const int nhid1,const int nhid2, - const int nout,CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=10; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid2,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(-5,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid1,nhid2,nout,false,true); - } -//+------------------------------------------------------------------+ -//| Creates neural network with NIn inputs, NOut outputs, without | -//| hidden layers with non-linear output layer. Network weights are | -//| filled with small random values. | -//| Activation function of the output layer takes values: | -//| (B, +INF), if D>=0 | -//| or | -//| (-INF, B), if D<0. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateB0(const int nin,const int nout,const double b, - double d,CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=4; -//--- check - if(d>=0.0) - d=1; - else - d=-1; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(3,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,0,0,nout,false,false); -//--- Turn on ouputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=b; - network.m_columnsigmas[i]=d; - } - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateB0 but with non-linear hidden layer. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateB1(const int nin,const int nhid,const int nout, - const double b,double d,CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; - layerscount=7; -//--- check - if(d>=0.0) - d=1; - else - d=-1; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(3,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid,0,nout,false,false); -//--- Turn on ouputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=b; - network.m_columnsigmas[i]=d; - } - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateB0 but with two non-linear hidden layers. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateB2(const int nin,const int nhid1,const int nhid2, - const int nout,const double b,double d, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=10; -//--- check - if(d>=0.0) - d=1; - else - d=-1; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid2,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(3,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid1,nhid2,nout,false,false); -//--- Turn on ouputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=b; - network.m_columnsigmas[i]=d; - } - } -//+------------------------------------------------------------------+ -//| Creates neural network with NIn inputs, NOut outputs, | -//| without hidden layers with non-linear output layer. Network | -//| weights are filled with small random values. Activation function | -//| of the output layer takes values [A,B]. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateR0(const int nin,const int nout,const double a, - const double b,CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=1+3; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,0,0,nout,false,false); -//--- Turn on outputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=0.5*(a+b); - network.m_columnsigmas[i]=0.5*(a-b); - } - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateR0,but with non-linear hidden layer. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateR1(const int nin,const int nhid,const int nout, - const double a,const double b, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=7; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid,0,nout,false,false); -//--- Turn on outputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=0.5*(a+b); - network.m_columnsigmas[i]=0.5*(a-b); - } - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateR0,but with two non-linear hidden layers. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateR2(const int nin,const int nhid1,const int nhid2, - const int nout,const double a,const double b, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; - int i=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- initialization - layerscount=10; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid2,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,false,network); -//--- function call - FillHighLevelInformation(network,nin,nhid1,nhid2,nout,false,false); -//--- Turn on outputs shift/scaling. - for(i=nin;i<=nin+nout-1;i++) - { - network.m_columnmeans[i]=0.5*(a+b); - network.m_columnsigmas[i]=0.5*(a-b); - } - } -//+------------------------------------------------------------------+ -//| Creates classifier network with NIn inputs and NOut possible | -//| classes. | -//| Network contains no hidden layers and linear output layer with | -//| SOFTMAX-normalization (so outputs sums up to 1.0 and converge to | -//| posterior probabilities). | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateC0(const int nin,const int nout, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- check - if(!CAp::Assert(nout>=2,__FUNCTION__+": NOut<2!")) - return; -//--- initialization - layerscount=4; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout-1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddZeroLayer(lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,true,network); -//--- function call - FillHighLevelInformation(network,nin,0,0,nout,true,true); - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateC0,but with one non-linear hidden layer. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateC1(const int nin,const int nhid,const int nout, - CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- check - if(!CAp::Assert(nout>=2,__FUNCTION__+": NOut<2!")) - return; -//--- initialization - layerscount=7; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout-1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddZeroLayer(lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,true,network); -//--- function call - FillHighLevelInformation(network,nin,nhid,0,nout,true,true); - } -//+------------------------------------------------------------------+ -//| Same as MLPCreateC0, but with two non-linear hidden layers. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreateC2(const int nin,const int nhid1,const int nhid2, - const int nout,CMultilayerPerceptron &network) - { -//--- create variables - int layerscount=0; - int lastproc=0; -//--- creating arrays - int lsizes[]; - int ltypes[]; - int lconnfirst[]; - int lconnlast[]; -//--- check - if(!CAp::Assert(nout>=2,__FUNCTION__+": NOut<2!")) - return; -//--- initialization - layerscount=10; -//--- Allocate arrays - ArrayResizeAL(lsizes,layerscount); - ArrayResizeAL(ltypes,layerscount); - ArrayResizeAL(lconnfirst,layerscount); - ArrayResizeAL(lconnlast,layerscount); -//--- Layers - AddInputLayer(nin,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nhid2,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddActivationLayer(1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddBiasedSummatorLayer(nout-1,lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- function call - AddZeroLayer(lsizes,ltypes,lconnfirst,lconnlast,lastproc); -//--- Create - MLPCreate(nin,nout,lsizes,ltypes,lconnfirst,lconnlast,layerscount,true,network); -//--- function call - FillHighLevelInformation(network,nin,nhid1,nhid2,nout,true,true); - } -//+------------------------------------------------------------------+ -//| Copying of neural network | -//| INPUT PARAMETERS: | -//| Network1 - original | -//| OUTPUT PARAMETERS: | -//| Network2 - copy | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCopy(CMultilayerPerceptron &network1, - CMultilayerPerceptron &network2) - { -//--- copy - network2.m_hlnetworktype=network1.m_hlnetworktype; - network2.m_hlnormtype=network1.m_hlnormtype; -//--- function calls - CApServ::CopyIntegerArray(network1.m_hllayersizes,network2.m_hllayersizes); - CApServ::CopyIntegerArray(network1.m_hlconnections,network2.m_hlconnections); - CApServ::CopyIntegerArray(network1.m_hlneurons,network2.m_hlneurons); - CApServ::CopyIntegerArray(network1.m_structinfo,network2.m_structinfo); - CApServ::CopyRealArray(network1.m_weights,network2.m_weights); - CApServ::CopyRealArray(network1.m_columnmeans,network2.m_columnmeans); - CApServ::CopyRealArray(network1.m_columnsigmas,network2.m_columnsigmas); - CApServ::CopyRealArray(network1.m_neurons,network2.m_neurons); - CApServ::CopyRealArray(network1.m_dfdnet,network2.m_dfdnet); - CApServ::CopyRealArray(network1.m_derror,network2.m_derror); - CApServ::CopyRealArray(network1.m_x,network2.m_x); - CApServ::CopyRealArray(network1.m_y,network2.m_y); - CApServ::CopyRealMatrix(network1.m_chunks,network2.m_chunks); - CApServ::CopyRealArray(network1.m_nwbuf,network2.m_nwbuf); - CApServ::CopyIntegerArray(network1.m_integerbuf,network2.m_integerbuf); - } -//+------------------------------------------------------------------+ -//| Serialization of MultiLayerPerceptron strucure | -//| INPUT PARAMETERS: | -//| Network - original | -//| OUTPUT PARAMETERS: | -//| RA - array of real numbers which stores network, | -//| array[0..RLen-1] | -//| RLen - RA lenght | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPSerializeOld(CMultilayerPerceptron &network, - double &ra[],int &rlen) - { -//--- create variables - int i=0; - int ssize=0; - int ntotal=0; - int nin=0; - int nout=0; - int wcount=0; - int sigmalen=0; - int offs=0; - int i_=0; - int i1_=0; -//--- initialization - rlen=0; -//--- Unload info - ssize=network.m_structinfo[0]; - nin=network.m_structinfo[1]; - nout=network.m_structinfo[2]; - ntotal=network.m_structinfo[3]; - wcount=network.m_structinfo[4]; -//--- check - if(MLPIsSoftMax(network)) - sigmalen=nin; - else - sigmalen=nin+nout; -//--- RA format: -//--- LEN DESRC. -//--- 1 RLen -//--- 1 version (MLPVNum) -//--- 1 StructInfo size -//--- SSize StructInfo -//--- WCount Weights -//--- SigmaLen ColumnMeans -//--- SigmaLen ColumnSigmas - rlen=3+ssize+wcount+2*sigmalen; -//--- allocation - ArrayResizeAL(ra,rlen); -//--- change values - ra[0]=rlen; - ra[1]=m_mlpvnum; - ra[2]=ssize; -//--- calculation - offs=3; - for(i=0;i<=ssize-1;i++) - ra[offs+i]=network.m_structinfo[i]; -//--- calculation - offs=offs+ssize; - i1_=-offs; - for(i_=offs;i_<=offs+wcount-1;i_++) - ra[i_]=network.m_weights[i_+i1_]; -//--- calculation - offs=offs+wcount; - i1_=-offs; - for(i_=offs;i_<=offs+sigmalen-1;i_++) - ra[i_]=network.m_columnmeans[i_+i1_]; -//--- calculation - offs=offs+sigmalen; - i1_=-offs; - for(i_=offs;i_<=offs+sigmalen-1;i_++) - ra[i_]=network.m_columnsigmas[i_+i1_]; - offs=offs+sigmalen; - } -//+------------------------------------------------------------------+ -//| Unserialization of MultiLayerPerceptron strucure | -//| INPUT PARAMETERS: | -//| RA - real array which stores network | -//| OUTPUT PARAMETERS: | -//| Network - restored network | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPUnserializeOld(double &ra[],CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int ssize=0; - int ntotal=0; - int nin=0; - int nout=0; - int wcount=0; - int sigmalen=0; - int offs=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(ra[1])==m_mlpvnum,__FUNCTION__+": incorrect array!")) - return; -//--- Unload StructInfo from IA - offs=3; - ssize=(int)MathRound(ra[2]); -//--- allocation - ArrayResizeAL(network.m_structinfo,ssize); - for(i=0;i<=ssize-1;i++) - network.m_structinfo[i]=(int)MathRound(ra[offs+i]); - offs=offs+ssize; -//--- Unload info from StructInfo - ssize=network.m_structinfo[0]; - nin=network.m_structinfo[1]; - nout=network.m_structinfo[2]; - ntotal=network.m_structinfo[3]; - wcount=network.m_structinfo[4]; -//--- check - if(network.m_structinfo[6]==0) - sigmalen=nin+nout; - else - sigmalen=nin; -//--- Allocate space for other fields - ArrayResizeAL(network.m_weights,wcount); - ArrayResizeAL(network.m_columnmeans,sigmalen); - ArrayResizeAL(network.m_columnsigmas,sigmalen); - ArrayResizeAL(network.m_neurons,ntotal); - network.m_chunks.Resize(3*ntotal+1,m_chunksize); - ArrayResizeAL(network.m_nwbuf,MathMax(wcount,2*nout)); - ArrayResizeAL(network.m_dfdnet,ntotal); - ArrayResizeAL(network.m_x,nin); - ArrayResizeAL(network.m_y,nout); - ArrayResizeAL(network.m_derror,ntotal); -//--- Copy parameters from RA - i1_=offs; - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=ra[i_+i1_]; -//--- calculation - offs=offs+wcount; - i1_=offs; - for(i_=0;i_<=sigmalen-1;i_++) - network.m_columnmeans[i_]=ra[i_+i1_]; -//--- calculation - offs=offs+sigmalen; - i1_=offs; - for(i_=0;i_<=sigmalen-1;i_++) - network.m_columnsigmas[i_]=ra[i_+i1_]; - offs=offs+sigmalen; - } -//+------------------------------------------------------------------+ -//| Randomization of neural network weights | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPRandomize(CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int nin=0; - int nout=0; - int wcount=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- change values - for(i=0;i<=wcount-1;i++) - network.m_weights[i]=CMath::RandomReal()-0.5; - } -//+------------------------------------------------------------------+ -//| Randomization of neural network weights and standartisator | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPRandomizeFull(CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int nin=0; - int nout=0; - int wcount=0; - int ntotal=0; - int istart=0; - int offs=0; - int ntype=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- initialization - ntotal=network.m_structinfo[3]; - istart=network.m_structinfo[5]; -//--- Process network - for(i=0;i<=wcount-1;i++) - network.m_weights[i]=CMath::RandomReal()-0.5; - for(i=0;i<=nin-1;i++) - { - network.m_columnmeans[i]=2*CMath::RandomReal()-1; - network.m_columnsigmas[i]=1.5*CMath::RandomReal()+0.5; - } -//--- check - if(!MLPIsSoftMax(network)) - { - for(i=0;i<=nout-1;i++) - { - offs=istart+(ntotal-nout+i)*m_nfieldwidth; - ntype=network.m_structinfo[offs+0]; - //--- check - if(ntype==0) - { - //--- Shifts are changed only for linear outputs neurons - network.m_columnmeans[nin+i]=2*CMath::RandomReal()-1; - } - //--- check - if(ntype==0 || ntype==3) - { - //--- Scales are changed only for linear or bounded outputs neurons. - //--- Note that scale randomization preserves sign. - network.m_columnsigmas[nin+i]=MathSign(network.m_columnsigmas[nin+i])*(1.5*CMath::RandomReal()+0.5); - } - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPInitPreprocessor(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int ssize) - { -//--- create variables - int i=0; - int j=0; - int jmax=0; - int nin=0; - int nout=0; - int wcount=0; - int ntotal=0; - int istart=0; - int offs=0; - int ntype=0; - double s=0; -//--- creating arrays - double means[]; - double sigmas[]; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- initialization - ntotal=network.m_structinfo[3]; - istart=network.m_structinfo[5]; -//--- Means/Sigmas - if(MLPIsSoftMax(network)) - jmax=nin-1; - else - jmax=nin+nout-1; -//--- allocation - ArrayResizeAL(means,jmax+1); - ArrayResizeAL(sigmas,jmax+1); -//--- calculation - for(j=0;j<=jmax;j++) - { - //--- means - means[j]=0; - for(i=0;i<=ssize-1;i++) - means[j]=means[j]+xy[i][j]; - means[j]=means[j]/ssize; - //--- sigmas - sigmas[j]=0; - for(i=0;i<=ssize-1;i++) - sigmas[j]=sigmas[j]+CMath::Sqr(xy[i][j]-means[j]); - sigmas[j]=MathSqrt(sigmas[j]/ssize); - } -//--- Inputs - for(i=0;i<=nin-1;i++) - { - network.m_columnmeans[i]=means[i]; - network.m_columnsigmas[i]=sigmas[i]; - //--- check - if(network.m_columnsigmas[i]==0.0) - network.m_columnsigmas[i]=1; - } -//--- Outputs - if(!MLPIsSoftMax(network)) - { - for(i=0;i<=nout-1;i++) - { - offs=istart+(ntotal-nout+i)*m_nfieldwidth; - ntype=network.m_structinfo[offs+0]; - //--- Linear outputs - if(ntype==0) - { - network.m_columnmeans[nin+i]=means[nin+i]; - network.m_columnsigmas[nin+i]=sigmas[nin+i]; - //--- check - if(network.m_columnsigmas[nin+i]==0.0) - network.m_columnsigmas[nin+i]=1; - } - //--- Bounded outputs (half-interval) - if(ntype==3) - { - s=means[nin+i]-network.m_columnmeans[nin+i]; - //--- check - if(s==0.0) - s=MathSign(network.m_columnsigmas[nin+i]); - //--- check - if(s==0.0) - s=1.0; - //--- change value - network.m_columnsigmas[nin+i]=MathSign(network.m_columnsigmas[nin+i])*MathAbs(s); - //--- check - if((double)(network.m_columnsigmas[nin+i])==0.0) - network.m_columnsigmas[nin+i]=1; - } - } - } - } -//+------------------------------------------------------------------+ -//| Returns information about initialized network: number of inputs, | -//| outputs, weights. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPProperties(CMultilayerPerceptron &network,int &nin, - int &nout,int &wcount) - { -//--- change values - nin=network.m_structinfo[1]; - nout=network.m_structinfo[2]; - wcount=network.m_structinfo[4]; - } -//+------------------------------------------------------------------+ -//| Tells whether network is SOFTMAX-normalized (i.m_e. classifier) | -//| or not. | -//+------------------------------------------------------------------+ -static bool CMLPBase::MLPIsSoftMax(CMultilayerPerceptron &network) - { -//--- check - if(network.m_structinfo[6]==1) - return(true); -//--- return result - return(false); - } -//+------------------------------------------------------------------+ -//| This function returns total number of layers (including input, | -//| hidden and output layers). | -//+------------------------------------------------------------------+ -static int CMLPBase::MLPGetLayersCount(CMultilayerPerceptron &network) - { -//--- return result - return(CAp::Len(network.m_hllayersizes)); - } -//+------------------------------------------------------------------+ -//| This function returns size of K-th layer. | -//| K=0 corresponds to input layer, K=CNT-1 corresponds to output | -//| layer. | -//| Size of the output layer is always equal to the number of | -//| outputs, although when we have softmax-normalized network, last | -//| neuron doesn't have any connections - it is just zero. | -//+------------------------------------------------------------------+ -static int CMLPBase::MLPGetLayerSize(CMultilayerPerceptron &network, - const int k) - { -//--- check - if(!CAp::Assert(k>=0 && k=0 && i=0 && i=0,__FUNCTION__+": incorrect (nonexistent) layer or neuron index")) - return; -//--- 1. find offset of the activation function record in the - if(network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+2]>=0) - { - activationoffset=istart+network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+2]*m_nfieldwidth; - fkind=network.m_structinfo[activationoffset+0]; - } - else - fkind=0; -//--- check - if(network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+3]>=0) - threshold=network.m_weights[network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+3]]; - else - threshold=0; - } -//+------------------------------------------------------------------+ -//| This function returns information about connection from I0-th | -//| neuron of K0-th layer to I1-th neuron of K1-th layer. | -//| INPUT PARAMETERS: | -//| Network - network | -//| K0 - layer index | -//| I0 - neuron index (within layer) | -//| K1 - layer index | -//| I1 - neuron index (within layer) | -//| RESULT: | -//| connection weight (zero for non-existent connections) | -//| This function: | -//| 1. throws exception if layer or neuron with given index do not | -//| exists. | -//| 2. returns zero if neurons exist, but there is no connection | -//| between them | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPGetWeight(CMultilayerPerceptron &network, - const int k0,const int i0, - const int k1,const int i1) - { -//--- create variables - double result=0; - int ccnt=0; - int highlevelidx=0; -//--- initialization - ccnt=CAp::Len(network.m_hlconnections)/m_hlconm_nfieldwidth; -//--- check params - if(!CAp::Assert(k0>=0 && k0=0 && i0=0 && k1=0 && i1=0) - result=network.m_weights[network.m_hlconnections[highlevelidx*m_hlconm_nfieldwidth+4]]; - else - result=0; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| This function sets offset/scaling coefficients for I-th input of | -//| the network. | -//| INPUT PARAMETERS: | -//| Network - network | -//| I - input index | -//| Mean - mean term | -//| Sigma - sigma term (if zero,will be replaced by 1.0) | -//| NTE: I-th input is passed through linear transformation | -//| IN[i]=(IN[i]-Mean)/Sigma | -//| before feeding to the network. This function sets Mean and Sigma.| -//+------------------------------------------------------------------+ -static void CMLPBase::MLPSetInputScaling(CMultilayerPerceptron &network, - const int i,const double mean, - double sigma) - { -//--- check - if(!CAp::Assert(i>=0 && i=0 && i=0,__FUNCTION__+": incorrect (nonexistent) layer or neuron index")) - return; -//--- activation function - if(network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+2]>=0) - { - activationoffset=istart+network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+2]*m_nfieldwidth; - network.m_structinfo[activationoffset+0]=fkind; - } - else - { - //--- check - if(!CAp::Assert(fkind==0,__FUNCTION__+": you try to set activation function for neuron which can not have one")) - return; - } -//--- Threshold - if(network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+3]>=0) - network.m_weights[network.m_hlneurons[highlevelidx*m_hlm_nfieldwidth+3]]=threshold; - else - { - //--- check - if(!CAp::Assert(threshold==0.0,__FUNCTION__+": you try to set non-zero threshold for neuron which can not have one")) - return; - } - } -//+------------------------------------------------------------------+ -//| This function modifies information about connection from I0-th | -//| neuron of K0-th layer to I1-th neuron of K1-th layer. | -//| INPUT PARAMETERS: | -//| Network - network | -//| K0 - layer index | -//| I0 - neuron index (within layer) | -//| K1 - layer index | -//| I1 - neuron index (within layer) | -//| W - connection weight (must be zero for | -//| non-existent connections) | -//| This function: | -//| 1. throws exception if layer or neuron with given index do not | -//| exists. | -//| 2. throws exception if you try to set non-zero weight for | -//| non-existent connection | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPSetWeight(CMultilayerPerceptron &network,const int k0, - const int i0,const int k1, - const int i1,const double w) - { -//--- create variables - int ccnt=0; - int highlevelidx=0; -//--- initialization - ccnt=CAp::Len(network.m_hlconnections)/m_hlconm_nfieldwidth; -//--- check params - if(!CAp::Assert(k0>=0 && k0=0 && i0=0 && k1=0 && i1=0) - network.m_weights[network.m_hlconnections[highlevelidx*m_hlconm_nfieldwidth+4]]=w; - else - { - //--- check - if(!CAp::Assert(w==0.0,__FUNCTION__+": you try to set non-zero weight for non-existent connection")) - return; - } - } -//+------------------------------------------------------------------+ -//| Neural network activation function | -//| INPUT PARAMETERS: | -//| NET - neuron input | -//| K - function index (zero for linear function) | -//| OUTPUT PARAMETERS: | -//| F - function | -//| DF - its derivative | -//| D2F - its second derivative | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPActivationFunction(double net,const int k,double &f, - double &df,double &d2f) - { -//--- create variables - double net2=0; - double arg=0; - double root=0; - double r=0; -//--- initialization - f=0; - df=0; - d2f=0; -//--- check - if(k==0 || k==-5) - { - f=net; - df=1; - d2f=0; - //--- exit the function - return; - } -//--- check - if(k==1) - { - //--- TanH activation function - if(MathAbs(net)<100.0) - f=MathTanh(net); - else - f=MathSign(net); - //--- change values - df=1-CMath::Sqr(f); - d2f=-(2*f*df); - //--- exit the function - return; - } -//--- check - if(k==3) - { - //--- EX activation function - if(net>=0.0) - { - //--- change values - net2=net*net; - arg=net2+1; - root=MathSqrt(arg); - f=net+root; - r=net/root; - df=1+r; - d2f=(root-net*r)/arg; - } - else - { - //--- change values - f=MathExp(net); - df=f; - d2f=f; - } - //--- exit the function - return; - } -//--- check - if(k==2) - { - //--- calculation - f=MathExp(-CMath::Sqr(net)); - df=-(2*net*f); - d2f=-(2*(f+df*net)); - //--- exit the function - return; - } -//--- change values - f=0; - df=0; - d2f=0; - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| Network - neural network | -//| X - input vector, array[0..NIn-1]. | -//| OUTPUT PARAMETERS: | -//| Y - result. Regression estimate when solving | -//| regression task, vector of posterior | -//| probabilities for classification task. | -//| See also MLPProcessI | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPProcess(CMultilayerPerceptron &network,double &x[], - double &y[]) - { -//--- check - if(CAp::Len(y)=0 && k=0 && kworky[nmax]) - nmax=j; - } - nn=nmax; - //--- Right answer - if(MLPIsSoftMax(network)) - ns=(int)MathRound(xy[i][nin]); - else - { - nmax=0; - for(j=0;j<=nout-1;j++) - { - //--- check - if(xy[i][nin+j]>xy[i][nin+nmax]) - nmax=j; - } - ns=nmax; - } - //--- compare - if(nn!=ns) - result=result+1; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Relative classification error on the test set | -//| INPUT PARAMETERS: | -//| Network - network | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| percent of incorrectly classified cases. Works both for | -//| classifier networks and general purpose networks used as | -//| classifiers. | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPRelClsError(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints) - { -//--- return result - return((double)MLPClsError(network,xy,npoints)/(double)npoints); - } -//+------------------------------------------------------------------+ -//| Average cross-entropy (in bits per element) on the test set | -//| INPUT PARAMETERS: | -//| Network - neural network | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| CrossEntropy/(NPoints*LN(2)). | -//| Zero if network solves regression task. | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPAvgCE(CMultilayerPerceptron &network,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double result=0; - int nin=0; - int nout=0; - int wcount=0; -//--- check - if(MLPIsSoftMax(network)) - { - //--- function call - MLPProperties(network,nin,nout,wcount); - //--- get result - result=MLPErrorN(network,xy,npoints)/(npoints*MathLog(2)); - } - else - result=0; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| Network - neural network | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| root mean square error. | -//| Its meaning for regression task is obvious. As for | -//| classification task,RMS error means error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPRMSError(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints) - { -//--- create variables - int nin=0; - int nout=0; - int wcount=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- return result - return(MathSqrt(2*MLPError(network,xy,npoints)/(npoints*nout))); - } -//+------------------------------------------------------------------+ -//| Average error on the test set | -//| INPUT PARAMETERS: | -//| Network - neural network | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task,it means average error when estimating | -//| posterior probabilities. | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPAvgError(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints) - { -//--- create variables - double result=0; - int i=0; - int j=0; - int k=0; - int nin=0; - int nout=0; - int wcount=0; - int i_=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- calculation - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=nin-1;i_++) - network.m_x[i_]=xy[i][i_]; - //--- function call - MLPProcess(network,network.m_x,network.m_y); - //--- check - if(MLPIsSoftMax(network)) - { - //--- class labels - k=(int)MathRound(xy[i][nin]); - for(j=0;j<=nout-1;j++) - { - //--- check - if(j==k) - result=result+MathAbs(1-network.m_y[j]); - else - result=result+MathAbs(network.m_y[j]); - } - } - else - { - //--- real outputs - for(j=0;j<=nout-1;j++) - result=result+MathAbs(xy[i][nin+j]-network.m_y[j]); - } - } -//--- return result - return(result/(npoints*nout)); - } -//+------------------------------------------------------------------+ -//| Average relative error on the test set | -//| INPUT PARAMETERS: | -//| Network - neural network | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| Its meaning for regression task is obvious. As for | -//| classification task, it means average relative error when | -//| estimating posterior probability of belonging to the correct | -//| class. | -//+------------------------------------------------------------------+ -static double CMLPBase::MLPAvgRelError(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints) - { -//--- create variables - double result=0; - int i=0; - int j=0; - int k=0; - int lk=0; - int nin=0; - int nout=0; - int wcount=0; - int i_=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- initialization - result=0; - k=0; -//--- calculation - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=nin-1;i_++) - network.m_x[i_]=xy[i][i_]; - //--- function call - MLPProcess(network,network.m_x,network.m_y); - //--- check - if(MLPIsSoftMax(network)) - { - //--- class labels - lk=(int)MathRound(xy[i][nin]); - for(j=0;j<=nout-1;j++) - { - //--- check - if(j==lk) - { - result=result+MathAbs(1-network.m_y[j]); - k=k+1; - } - } - } - else - { - //--- real outputs - for(j=0;j<=nout-1;j++) - { - //--- check - if(xy[i][nin+j]!=0.0) - { - result=result+MathAbs(xy[i][nin+j]-network.m_y[j])/MathAbs(xy[i][nin+j]); - k=k+1; - } - } - } - } -//--- check - if(k!=0) - result=result/k; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Gradient calculation | -//| INPUT PARAMETERS: | -//| Network - network initialized with one of the network | -//| creation funcs | -//| X - input vector, length of array must be at least | -//| NIn | -//| DesiredY- desired outputs, length of array must be at least| -//| NOut | -//| Grad - possibly preallocated array. If size of array is | -//| smaller than WCount, it will be reallocated. It | -//| is recommended to reuse previously allocated | -//| array to reduce allocation overhead. | -//| OUTPUT PARAMETERS: | -//| E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) | -//| Grad - gradient of E with respect to weights of network,| -//| array[WCount] | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPGrad(CMultilayerPerceptron &network,double &x[], - double &desiredy[],double &e,double &grad[]) - { -//--- create variables - int i=0; - int nout=0; - int ntotal=0; -//--- Alloc - if(CAp::Len(grad)0 || structinfo[offs+0]==-5) - { - //--- Activation function - MLPActivationFunction(neurons[structinfo[offs+2]],structinfo[offs+0],f,df,d2f); - //--- change values - neurons[i]=f; - dfdnet[i]=df; - continue; - } - //--- check - if(structinfo[offs+0]==0) - { - //--- Adaptive summator - n1=structinfo[offs+2]; - n2=n1+structinfo[offs+1]-1; - w1=structinfo[offs+3]; - w2=w1+structinfo[offs+1]-1; - i1_=(n1)-(w1); - net=0.0; - //--- calculation - for(i_=w1;i_<=w2;i_++) - net+=weights[i_]*neurons[i_+i1_]; - neurons[i]=net; - dfdnet[i]=1.0; - continue; - } - //--- check - if(structinfo[offs+0]<0) - { - perr=true; - //--- check - if(structinfo[offs+0]==-2) - { - //--- input neuron,left unchanged - perr=false; - } - //--- check - if(structinfo[offs+0]==-3) - { - //--- "-1" neuron - neurons[i]=-1; - perr=false; - } - //--- check - if(structinfo[offs+0]==-4) - { - //--- "0" neuron - neurons[i]=0; - perr=false; - } - //--- check - if(!CAp::Assert(!perr,__FUNCTION__+": internal error - unknown neuron type!")) - return; - continue; - } - } -//--- Extract result - i1_=ntotal-nout; - for(i_=0;i_<=nout-1;i_++) - y[i_]=neurons[i_+i1_]; -//--- Softmax post-processing or standardisation if needed - if(!CAp::Assert(structinfo[6]==0 || structinfo[6]==1,__FUNCTION__+": unknown normalization type!")) - return; -//--- check - if(structinfo[6]==1) - { - //--- Softmax - mx=y[0]; - for(i=1;i<=nout-1;i++) - mx=MathMax(mx,y[i]); - //--- calculation - net=0; - for(i=0;i<=nout-1;i++) - { - y[i]=MathExp(y[i]-mx); - net=net+y[i]; - } - for(i=0;i<=nout-1;i++) - y[i]=y[i]/net; - } - else - { - //--- Standardisation - for(i=0;i<=nout-1;i++) - y[i]=y[i]*columnsigmas[nin+i]+columnmeans[nin+i]; - } - } -//+------------------------------------------------------------------+ -//| Serializer: allocation | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPAlloc(CSerializer &s,CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int fkind=0; - double threshold=0; - double v0=0; - double v1=0; - int nin=0; - int nout=0; -//--- initialization - nin=network.m_hllayersizes[0]; - nout=network.m_hllayersizes[CAp::Len(network.m_hllayersizes)-1]; -//--- preparation to serialize - s.Alloc_Entry(); - s.Alloc_Entry(); - s.Alloc_Entry(); -//--- function call - CApServ::AllocIntegerArray(s,network.m_hllayersizes,-1); - for(i=1;i<=CAp::Len(network.m_hllayersizes)-1;i++) - { - for(j=0;j<=network.m_hllayersizes[i]-1;j++) - { - //--- function call - MLPGetNeuronInfo(network,i,j,fkind,threshold); - //--- preparation to serialize - s.Alloc_Entry(); - s.Alloc_Entry(); - for(k=0;k<=network.m_hllayersizes[i-1]-1;k++) - s.Alloc_Entry(); - } - } - for(j=0;j<=nin-1;j++) - { - //--- function call - MLPGetInputScaling(network,j,v0,v1); - //--- preparation to serialize - s.Alloc_Entry(); - s.Alloc_Entry(); - } - for(j=0;j<=nout-1;j++) - { - //--- function call - MLPGetOutputScaling(network,j,v0,v1); - //--- preparation to serialize - s.Alloc_Entry(); - s.Alloc_Entry(); - } - } -//+------------------------------------------------------------------+ -//| Serializer: serialization | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPSerialize(CSerializer &s,CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int fkind=0; - double threshold=0; - double v0=0; - double v1=0; - int nin=0; - int nout=0; -//--- change values - nin=network.m_hllayersizes[0]; - nout=network.m_hllayersizes[CAp::Len(network.m_hllayersizes)-1]; -//--- serializetion - s.Serialize_Int(CSCodes::GetMLPSerializationCode()); - s.Serialize_Int(m_mlpfirstversion); - s.Serialize_Bool(MLPIsSoftMax(network)); -//--- function call - CApServ::SerializeIntegerArray(s,network.m_hllayersizes,-1); - for(i=1;i<=CAp::Len(network.m_hllayersizes)-1;i++) - { - for(j=0;j<=network.m_hllayersizes[i]-1;j++) - { - //--- function call - MLPGetNeuronInfo(network,i,j,fkind,threshold); - //--- serializetion - s.Serialize_Int(fkind); - s.Serialize_Double(threshold); - for(k=0;k<=network.m_hllayersizes[i-1]-1;k++) - s.Serialize_Double(MLPGetWeight(network,i-1,k,i,j)); - } - } - for(j=0;j<=nin-1;j++) - { - //--- function call - MLPGetInputScaling(network,j,v0,v1); - //--- serializetion - s.Serialize_Double(v0); - s.Serialize_Double(v1); - } - for(j=0;j<=nout-1;j++) - { - //--- function call - MLPGetOutputScaling(network,j,v0,v1); - //--- serializetion - s.Serialize_Double(v0); - s.Serialize_Double(v1); - } - } -//+------------------------------------------------------------------+ -//| Serializer: unserialization | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPUnserialize(CSerializer &s,CMultilayerPerceptron &network) - { -//--- create variables - int i0=0; - int i1=0; - int i=0; - int j=0; - int k=0; - int fkind=0; - double threshold=0; - double v0=0; - double v1=0; - int nin=0; - int nout=0; - bool issoftmax; -//--- create array - int layersizes[]; -//--- check correctness of header - i0=s.Unserialize_Int(); -//--- check - if(!CAp::Assert(i0==CSCodes::GetMLPSerializationCode(),__FUNCTION__+": stream header corrupted")) - return; -//--- unserializetion - i1=s.Unserialize_Int(); -//--- check - if(!CAp::Assert(i1==m_mlpfirstversion,__FUNCTION__+": stream header corrupted")) - return; -//--- Create network - issoftmax=s.Unserialize_Bool(); -//--- function call - CApServ::UnserializeIntegerArray(s,layersizes); -//--- check - if(!CAp::Assert((CAp::Len(layersizes)==2 || CAp::Len(layersizes)==3) || CAp::Len(layersizes)==4,__FUNCTION__+": too many hidden layers!")) - return; -//--- change values - nin=layersizes[0]; - nout=layersizes[CAp::Len(layersizes)-1]; -//--- check - if(CAp::Len(layersizes)==2) - { - //--- check - if(issoftmax) - MLPCreateC0(layersizes[0],layersizes[1],network); - else - MLPCreate0(layersizes[0],layersizes[1],network); - } -//--- check - if(CAp::Len(layersizes)==3) - { - //--- check - if(issoftmax) - MLPCreateC1(layersizes[0],layersizes[1],layersizes[2],network); - else - MLPCreate1(layersizes[0],layersizes[1],layersizes[2],network); - } -//--- check - if(CAp::Len(layersizes)==4) - { - //--- check - if(issoftmax) - MLPCreateC2(layersizes[0],layersizes[1],layersizes[2],layersizes[3],network); - else - MLPCreate2(layersizes[0],layersizes[1],layersizes[2],layersizes[3],network); - } -//--- Load neurons and weights - for(i=1;i<=CAp::Len(layersizes)-1;i++) - { - for(j=0;j<=layersizes[i]-1;j++) - { - //--- unserializetion - fkind=s.Unserialize_Int(); - threshold=s.Unserialize_Double(); - //--- function call - MLPSetNeuronInfo(network,i,j,fkind,threshold); - //--- unserializetion - for(k=0;k<=layersizes[i-1]-1;k++) - { - v0=s.Unserialize_Double(); - //--- function call - MLPSetWeight(network,i-1,k,i,j,v0); - } - } - } - -// -//--- Load standartizator -// - for(j=0;j<=nin-1;j++) - { - //--- unserializetion - v0=s.Unserialize_Double(); - v1=s.Unserialize_Double(); - //--- function call - MLPSetInputScaling(network,j,v0,v1); - } - for(j=0;j<=nout-1;j++) - { - //--- unserializetion - v0=s.Unserialize_Double(); - v1=s.Unserialize_Double(); - //--- function call - MLPSetOutputScaling(network,j,v0,v1); - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine: adding new input layer to network | -//+------------------------------------------------------------------+ -static void CMLPBase::AddInputLayer(const int ncount,int &lsizes[], - int <ypes[],int &lconnfirst[], - int &lconnlast[],int &lastproc) - { -//--- change values - lsizes[0]=ncount; - ltypes[0]=-2; - lconnfirst[0]=0; - lconnlast[0]=0; - lastproc=0; - } -//+------------------------------------------------------------------+ -//| Internal subroutine: adding new summator layer to network | -//+------------------------------------------------------------------+ -static void CMLPBase::AddBiasedSummatorLayer(const int ncount,int &lsizes[], - int <ypes[],int &lconnfirst[], - int &lconnlast[],int &lastproc) - { -//--- change values - lsizes[lastproc+1]=1; - ltypes[lastproc+1]=-3; - lconnfirst[lastproc+1]=0; - lconnlast[lastproc+1]=0; - lsizes[lastproc+2]=ncount; - ltypes[lastproc+2]=0; - lconnfirst[lastproc+2]=lastproc; - lconnlast[lastproc+2]=lastproc+1; - lastproc=lastproc+2; - } -//+------------------------------------------------------------------+ -//| Internal subroutine: adding new summator layer to network | -//+------------------------------------------------------------------+ -static void CMLPBase::AddActivationLayer(const int functype,int &lsizes[], - int <ypes[],int &lconnfirst[], - int &lconnlast[],int &lastproc) - { -//--- check - if(!CAp::Assert(functype>0 || functype==-5,__FUNCTION__+": incorrect function type")) - return; -//--- change values - lsizes[lastproc+1]=lsizes[lastproc]; - ltypes[lastproc+1]=functype; - lconnfirst[lastproc+1]=lastproc; - lconnlast[lastproc+1]=lastproc; - lastproc=lastproc+1; - } -//+------------------------------------------------------------------+ -//| Internal subroutine: adding new zero layer to network | -//+------------------------------------------------------------------+ -static void CMLPBase::AddZeroLayer(int &lsizes[],int <ypes[], - int &lconnfirst[],int &lconnlast[], - int &lastproc) - { -//--- change values - lsizes[lastproc+1]=1; - ltypes[lastproc+1]=-4; - lconnfirst[lastproc+1]=0; - lconnlast[lastproc+1]=0; - lastproc=lastproc+1; - } -//+------------------------------------------------------------------+ -//| This routine adds input layer to the high-level description of | -//| the network. | -//| It modifies Network.HLConnections and Network.HLNeurons and | -//| assumes that these arrays have enough place to store data. | -//| It accepts following parameters: | -//| Network - network | -//| ConnIdx - index of the first free entry in the | -//| HLConnections | -//| NeuroIdx - index of the first free entry in the | -//| HLNeurons | -//| StructInfoIdx- index of the first entry in the low level | -//| description of the current layer (in the | -//| StructInfo array) | -//| NIn - number of inputs | -//| It modified Network and indices. | -//+------------------------------------------------------------------+ -static void CMLPBase::HLAddInputLayer(CMultilayerPerceptron &network, - int &connidx,int &neuroidx, - int &structinfoidx,int nin) - { -//--- create variables - int i=0; - int offs=0; -//--- initialization - offs=m_hlm_nfieldwidth*neuroidx; -//--- change values - for(i=0;i<=nin-1;i++) - { - network.m_hlneurons[offs+0]=0; - network.m_hlneurons[offs+1]=i; - network.m_hlneurons[offs+2]=-1; - network.m_hlneurons[offs+3]=-1; - offs=offs+m_hlm_nfieldwidth; - } -//--- change values - neuroidx=neuroidx+nin; - structinfoidx=structinfoidx+nin; - } -//+------------------------------------------------------------------+ -//| This routine adds output layer to the high-level description of | -//| the network. | -//| It modifies Network.HLConnections and Network. HLNeurons and | -//| assumes that these arrays have enough place to store data. It | -//| accepts following parameters: | -//| Network - network | -//| ConnIdx - index of the first free entry in the | -//| HLConnections | -//| NeuroIdx - index of the first free entry in the | -//| HLNeurons | -//| StructInfoIdx- index of the first entry in the low level | -//| description of the current layer (in the | -//| StructInfo array) | -//| WeightsIdx - index of the first entry in the Weights | -//| array which corresponds to the current layer | -//| K - current layer index | -//| NPrev - number of neurons in the previous layer | -//| NOut - number of outputs | -//| IsCls - is it classifier network? | -//| IsLinear - is it network with linear output? | -//| It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx| -//+------------------------------------------------------------------+ -static void CMLPBase::HLAddOutputLayer(CMultilayerPerceptron &network, - int &connidx,int &neuroidx, - int &structinfoidx,int &weightsidx, - const int k,const int nprev, - const int nout,const bool iscls, - const bool islinearout) - { -//--- create variables - int i=0; - int j=0; - int neurooffs=0; - int connoffs=0; -//--- check - if(!CAp::Assert((iscls && islinearout) || !iscls,__FUNCTION__+": internal error")) - return; -//--- initialization - neurooffs=m_hlm_nfieldwidth*neuroidx; - connoffs=m_hlconm_nfieldwidth*connidx; -//--- check - if(!iscls) - { - //--- Regression network - for(i=0;i<=nout-1;i++) - { - //--- change values - network.m_hlneurons[neurooffs+0]=k; - network.m_hlneurons[neurooffs+1]=i; - network.m_hlneurons[neurooffs+2]=structinfoidx+1+nout+i; - network.m_hlneurons[neurooffs+3]=weightsidx+nprev+(nprev+1)*i; - neurooffs=neurooffs+m_hlm_nfieldwidth; - } - for(i=0;i<=nprev-1;i++) - { - for(j=0;j<=nout-1;j++) - { - //--- change values - network.m_hlconnections[connoffs+0]=k-1; - network.m_hlconnections[connoffs+1]=i; - network.m_hlconnections[connoffs+2]=k; - network.m_hlconnections[connoffs+3]=j; - network.m_hlconnections[connoffs+4]=weightsidx+i+j*(nprev+1); - connoffs=connoffs+m_hlconm_nfieldwidth; - } - } - //--- change values - connidx=connidx+nprev*nout; - neuroidx=neuroidx+nout; - structinfoidx=structinfoidx+2*nout+1; - weightsidx=weightsidx+nout*(nprev+1); - } - else - { - //--- Classification network - for(i=0;i<=nout-2;i++) - { - //--- change values - network.m_hlneurons[neurooffs+0]=k; - network.m_hlneurons[neurooffs+1]=i; - network.m_hlneurons[neurooffs+2]=-1; - network.m_hlneurons[neurooffs+3]=weightsidx+nprev+(nprev+1)*i; - neurooffs=neurooffs+m_hlm_nfieldwidth; - } - //--- change values - network.m_hlneurons[neurooffs+0]=k; - network.m_hlneurons[neurooffs+1]=i; - network.m_hlneurons[neurooffs+2]=-1; - network.m_hlneurons[neurooffs+3]=-1; - for(i=0;i<=nprev-1;i++) - { - for(j=0;j<=nout-2;j++) - { - //--- change values - network.m_hlconnections[connoffs+0]=k-1; - network.m_hlconnections[connoffs+1]=i; - network.m_hlconnections[connoffs+2]=k; - network.m_hlconnections[connoffs+3]=j; - network.m_hlconnections[connoffs+4]=weightsidx+i+j*(nprev+1); - connoffs=connoffs+m_hlconm_nfieldwidth; - } - } - //--- change values - connidx=connidx+nprev*(nout-1); - neuroidx=neuroidx+nout; - structinfoidx=structinfoidx+nout+2; - weightsidx=weightsidx+(nout-1)*(nprev+1); - } - } -//+------------------------------------------------------------------+ -//| This routine adds hidden layer to the high-level description of | -//| the network. | -//| It modifies Network.HLConnections and Network.HLNeurons and | -//| assumes that these arrays have enough place to store data. It | -//| accepts following parameters: | -//| Network - network | -//| ConnIdx - index of the first free entry in the | -//| HLConnections | -//| NeuroIdx - index of the first free entry in the | -//| HLNeurons | -//| StructInfoIdx- index of the first entry in the low level | -//| description of the current layer (in the | -//| StructInfo array) | -//| WeightsIdx - index of the first entry in the Weights | -//| array which corresponds to the current layer | -//| K - current layer index | -//| NPrev - number of neurons in the previous layer | -//| NCur - number of neurons in the current layer | -//| It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx| -//+------------------------------------------------------------------+ -static void CMLPBase::HLAddHiddenLayer(CMultilayerPerceptron &network, - int &connidx,int &neuroidx, - int &structinfoidx,int &weightsidx, - const int k,const int nprev, - const int ncur) - { -//--- create variables - int i=0; - int j=0; - int neurooffs=0; - int connoffs=0; -//--- change values - neurooffs=m_hlm_nfieldwidth*neuroidx; - connoffs=m_hlconm_nfieldwidth*connidx; - for(i=0;i<=ncur-1;i++) - { - //--- change values - network.m_hlneurons[neurooffs+0]=k; - network.m_hlneurons[neurooffs+1]=i; - network.m_hlneurons[neurooffs+2]=structinfoidx+1+ncur+i; - network.m_hlneurons[neurooffs+3]=weightsidx+nprev+(nprev+1)*i; - neurooffs=neurooffs+m_hlm_nfieldwidth; - } - for(i=0;i<=nprev-1;i++) - { - for(j=0;j<=ncur-1;j++) - { - //--- change values - network.m_hlconnections[connoffs+0]=k-1; - network.m_hlconnections[connoffs+1]=i; - network.m_hlconnections[connoffs+2]=k; - network.m_hlconnections[connoffs+3]=j; - network.m_hlconnections[connoffs+4]=weightsidx+i+j*(nprev+1); - connoffs=connoffs+m_hlconm_nfieldwidth; - } - } -//--- change values - connidx=connidx+nprev*ncur; - neuroidx=neuroidx+ncur; - structinfoidx=structinfoidx+2*ncur+1; - weightsidx=weightsidx+ncur*(nprev+1); - } -//+------------------------------------------------------------------+ -//| This function fills high level information about network created | -//| using internal MLPCreate() function. | -//| This function does NOT examine StructInfo for low level | -//| information, it just expects that network has following | -//| structure: | -//| input neuron \ | -//| ... | input layer | -//| input neuron / | -//| "-1" neuron \ | -//| biased summator | | -//| ... | | -//| biased summator | hidden layer(s), if there are | -//| activation function | exists any | -//| ... | | -//| activation function / | -//| "-1" neuron \ | -//| biased summator | output layer: | -//| ... | * we have NOut summators/activators| -//| biased summator | for regression networks | -//| activation function | * we have only NOut-1 summators and| -//| ... | no activators for classifiers | -//| activation function | * we have "0" neuron only when we | -//| "0" neuron / have classifier | -//+------------------------------------------------------------------+ -static void CMLPBase::FillHighLevelInformation(CMultilayerPerceptron &network, - const int nin,const int nhid1, - const int nhid2,const int nout, - const bool iscls,const bool islinearout) - { -//--- create variables - int idxweights=0; - int idxstruct=0; - int idxneuro=0; - int idxconn=0; -//--- check - if(!CAp::Assert((iscls && islinearout) || !iscls,__FUNCTION__+": internal error")) - return; -//--- Preparations common to all types of networks - idxweights=0; - idxneuro=0; - idxstruct=0; - idxconn=0; - network.m_hlnetworktype=0; -//--- network without hidden layers - if(nhid1==0) - { - //--- allocation - ArrayResizeAL(network.m_hllayersizes,2); - //--- change values - network.m_hllayersizes[0]=nin; - network.m_hllayersizes[1]=nout; - //--- check - if(!iscls) - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*nin*nout); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nout)); - network.m_hlnormtype=0; - } - else - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*nin*(nout-1)); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nout)); - network.m_hlnormtype=1; - } - //--- function call - HLAddInputLayer(network,idxconn,idxneuro,idxstruct,nin); - //--- function call - HLAddOutputLayer(network,idxconn,idxneuro,idxstruct,idxweights,1,nin,nout,iscls,islinearout); - //--- exit the function - return; - } -//--- network with one hidden layers - if(nhid2==0) - { - //--- allocation - ArrayResizeAL(network.m_hllayersizes,3); - //--- change values - network.m_hllayersizes[0]=nin; - network.m_hllayersizes[1]=nhid1; - network.m_hllayersizes[2]=nout; - //--- check - if(!iscls) - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*(nin*nhid1+nhid1*nout)); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nhid1+nout)); - network.m_hlnormtype=0; - } - else - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*(nin*nhid1+nhid1*(nout-1))); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nhid1+nout)); - network.m_hlnormtype=1; - } - //--- function call - HLAddInputLayer(network,idxconn,idxneuro,idxstruct,nin); - //--- function call - HLAddHiddenLayer(network,idxconn,idxneuro,idxstruct,idxweights,1,nin,nhid1); - //--- function call - HLAddOutputLayer(network,idxconn,idxneuro,idxstruct,idxweights,2,nhid1,nout,iscls,islinearout); - //--- exit the function - return; - } -//--- Two hidden layers - ArrayResizeAL(network.m_hllayersizes,4); -//--- change values - network.m_hllayersizes[0]=nin; - network.m_hllayersizes[1]=nhid1; - network.m_hllayersizes[2]=nhid2; - network.m_hllayersizes[3]=nout; -//--- check - if(!iscls) - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*nout)); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nhid1+nhid2+nout)); - network.m_hlnormtype=0; - } - else - { - //--- allocation - ArrayResizeAL(network.m_hlconnections,m_hlconm_nfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*(nout-1))); - ArrayResizeAL(network.m_hlneurons,m_hlm_nfieldwidth*(nin+nhid1+nhid2+nout)); - network.m_hlnormtype=1; - } -//--- function call - HLAddInputLayer(network,idxconn,idxneuro,idxstruct,nin); -//--- function call - HLAddHiddenLayer(network,idxconn,idxneuro,idxstruct,idxweights,1,nin,nhid1); -//--- function call - HLAddHiddenLayer(network,idxconn,idxneuro,idxstruct,idxweights,2,nhid1,nhid2); -//--- function call - HLAddOutputLayer(network,idxconn,idxneuro,idxstruct,idxweights,3,nhid2,nout,iscls,islinearout); - } -//+------------------------------------------------------------------+ -//| Internal subroutine. | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPCreate(const int nin,const int nout,int &lsizes[], - int <ypes[],int &lconnfirst[],int &lconnlast[], - const int layerscount,const bool isclsnet, - CMultilayerPerceptron &network) - { -//--- create variables - int i=0; - int j=0; - int ssize=0; - int ntotal=0; - int wcount=0; - int offs=0; - int nprocessed=0; - int wallocated=0; -//--- creating arrays - int localtemp[]; - int lnfirst[]; - int lnsyn[]; -//--- Check - if(!CAp::Assert(layerscount>0,__FUNCTION__+": wrong parameters!")) - return; -//--- check - if(!CAp::Assert(ltypes[0]==-2,__FUNCTION__+": wrong LTypes[0] (must be -2)!")) - return; - for(i=0;i<=layerscount-1;i++) - { - //--- check - if(!CAp::Assert(lsizes[i]>0,__FUNCTION__+": wrong LSizes!")) - return; - //--- check - if(!CAp::Assert(lconnfirst[i]>=0 &&(lconnfirst[i]=lconnfirst[i]&&(lconnlast[i]=0 || ltypes[i]==-5) - { - lnsyn[i]=0; - for(j=lconnfirst[i];j<=lconnlast[i];j++) - lnsyn[i]=lnsyn[i]+lsizes[j]; - } - else - { - //--- check - if((ltypes[i]==-2 || ltypes[i]==-3) || ltypes[i]==-4) - lnsyn[i]=0; - } - //--- check - if(!CAp::Assert(lnsyn[i]>=0,__FUNCTION__+": internal error #0!")) - return; - //--- Other info - lnfirst[i]=ntotal; - ntotal=ntotal+lsizes[i]; - //--- check - if(ltypes[i]==0) - wcount=wcount+lnsyn[i]*lsizes[i]; - } - ssize=7+ntotal*m_nfieldwidth; -//--- Allocate - ArrayResizeAL(network.m_structinfo,ssize); - ArrayResizeAL(network.m_weights,wcount); -//--- check - if(isclsnet) - { - //--- allocation - ArrayResizeAL(network.m_columnmeans,nin); - ArrayResizeAL(network.m_columnsigmas,nin); - } - else - { - //--- allocation - ArrayResizeAL(network.m_columnmeans,nin+nout); - ArrayResizeAL(network.m_columnsigmas,nin+nout); - } -//--- allocation - ArrayResizeAL(network.m_neurons,ntotal); - network.m_chunks.Resize(3*ntotal+1,m_chunksize); - ArrayResizeAL(network.m_nwbuf,MathMax(wcount,2*nout)); - ArrayResizeAL(network.m_integerbuf,4); - ArrayResizeAL(network.m_dfdnet,ntotal); - ArrayResizeAL(network.m_x,nin); - ArrayResizeAL(network.m_y,nout); - ArrayResizeAL(network.m_derror,ntotal); -//--- Fill structure: global info - network.m_structinfo[0]=ssize; - network.m_structinfo[1]=nin; - network.m_structinfo[2]=nout; - network.m_structinfo[3]=ntotal; - network.m_structinfo[4]=wcount; - network.m_structinfo[5]=7; -//--- check - if(isclsnet) - network.m_structinfo[6]=1; - else - network.m_structinfo[6]=0; -//--- Fill structure: neuron connections - nprocessed=0; - wallocated=0; -//--- calculation - for(i=0;i<=layerscount-1;i++) - { - for(j=0;j<=lsizes[i]-1;j++) - { - offs=network.m_structinfo[5]+nprocessed*m_nfieldwidth; - network.m_structinfo[offs+0]=ltypes[i]; - //--- check - if(ltypes[i]==0) - { - //--- Adaptive summator: - //--- * connections with weights to previous neurons - network.m_structinfo[offs+1]=lnsyn[i]; - network.m_structinfo[offs+2]=lnfirst[lconnfirst[i]]; - network.m_structinfo[offs+3]=wallocated; - wallocated=wallocated+lnsyn[i]; - nprocessed=nprocessed+1; - } - //--- check - if(ltypes[i]>0 || ltypes[i]==-5) - { - //--- Activation layer: - //--- * each neuron connected to one (only one) of previous neurons. - //--- * no weights - network.m_structinfo[offs+1]=1; - network.m_structinfo[offs+2]=lnfirst[lconnfirst[i]]+j; - network.m_structinfo[offs+3]=-1; - nprocessed=nprocessed+1; - } - //--- check - if((ltypes[i]==-2 || ltypes[i]==-3) || ltypes[i]==-4) - nprocessed=nprocessed+1; - } - } -//--- check - if(!CAp::Assert(wallocated==wcount,__FUNCTION__+": internal error #1!")) - return; -//--- check - if(!CAp::Assert(nprocessed==ntotal,__FUNCTION__+": internal error #2!")) - return; -//--- Fill weights by small random values -//--- Initialize means and sigmas - for(i=0;i<=wcount-1;i++) - network.m_weights[i]=CMath::RandomReal()-0.5; - for(i=0;i<=nin-1;i++) - { - network.m_columnmeans[i]=0; - network.m_columnsigmas[i]=1; - } -//--- check - if(!isclsnet) - { - for(i=0;i<=nout-1;i++) - { - network.m_columnmeans[nin+i]=0; - network.m_columnsigmas[nin+i]=1; - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine for Hessian calculation. | -//| WARNING!!! Unspeakable math far beyong human capabilities :) | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPHessianBatchInternal(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int ssize, - const bool naturalerr,double &e, - double &grad[],CMatrixDouble &h) - { -//--- create variables - int nin=0; - int nout=0; - int wcount=0; - int ntotal=0; - int istart=0; - int i=0; - int j=0; - int k=0; - int kl=0; - int offs=0; - int n1=0; - int n2=0; - int w1=0; - int w2=0; - double s=0; - double t=0; - double v=0; - double et=0; - bool bflag; - double f=0; - double df=0; - double d2f=0; - double deidyj=0; - double mx=0; - double q=0; - double z=0; - double s2=0; - double expi=0; - double expj=0; - int i_=0; - int i1_=0; -//--- creating arrays - double x[]; - double desiredy[]; - double gt[]; - double zeros[]; -//--- create matrix - CMatrixDouble rx; - CMatrixDouble ry; - CMatrixDouble rdx; - CMatrixDouble rdy; -//--- initialization - e=0; -//--- function call - MLPProperties(network,nin,nout,wcount); -//--- initialization - ntotal=network.m_structinfo[3]; - istart=network.m_structinfo[5]; -//--- Prepare - ArrayResizeAL(x,nin); - ArrayResizeAL(desiredy,nout); - ArrayResizeAL(zeros,wcount); - ArrayResizeAL(gt,wcount); - rx.Resize(ntotal+nout,wcount); - ry.Resize(ntotal+nout,wcount); - rdx.Resize(ntotal+nout,wcount); - rdy.Resize(ntotal+nout,wcount); -//--- initialization - e=0; - for(i=0;i<=wcount-1;i++) - zeros[i]=0; - for(i_=0;i_<=wcount-1;i_++) - grad[i_]=zeros[i_]; - for(i=0;i<=wcount-1;i++) - { - for(i_=0;i_<=wcount-1;i_++) - h[i].Set(i_,zeros[i_]); - } -//--- Process - for(k=0;k<=ssize-1;k++) - { - //--- Process vector with MLPGradN. - //--- Now Neurons,DFDNET and DError contains results of the last run. - for(i_=0;i_<=nin-1;i_++) - x[i_]=xy[k][i_]; - //--- check - if(MLPIsSoftMax(network)) - { - //--- class labels outputs - kl=(int)MathRound(xy[k][nin]); - for(i=0;i<=nout-1;i++) - { - //--- check - if(i==kl) - desiredy[i]=1; - else - desiredy[i]=0; - } - } - else - { - //--- real outputs - i1_=nin; - for(i_=0;i_<=nout-1;i_++) - desiredy[i_]=xy[k][i_+i1_]; - } - //--- check - if(naturalerr) - MLPGradN(network,x,desiredy,et,gt); - else - MLPGrad(network,x,desiredy,et,gt); - //--- grad,error - e=e+et; - for(i_=0;i_<=wcount-1;i_++) - grad[i_]=grad[i_]+gt[i_]; - //--- Hessian. - //--- Forward pass of the R-algorithm - for(i=0;i<=ntotal-1;i++) - { - offs=istart+i*m_nfieldwidth; - for(i_=0;i_<=wcount-1;i_++) - rx[i].Set(i_,zeros[i_]); - for(i_=0;i_<=wcount-1;i_++) - ry[i].Set(i_,zeros[i_]); - //--- check - if(network.m_structinfo[offs+0]>0 || network.m_structinfo[offs+0]==-5) - { - //--- Activation function - n1=network.m_structinfo[offs+2]; - for(i_=0;i_<=wcount-1;i_++) - rx[i].Set(i_,ry[n1][i_]); - //--- calculation - v=network.m_dfdnet[i]; - for(i_=0;i_<=wcount-1;i_++) - ry[i].Set(i_,v*rx[i][i_]); - continue; - } - //--- check - if(network.m_structinfo[offs+0]==0) - { - //--- Adaptive summator - n1=network.m_structinfo[offs+2]; - n2=n1+network.m_structinfo[offs+1]-1; - w1=network.m_structinfo[offs+3]; - w2=w1+network.m_structinfo[offs+1]-1; - //--- calculation - for(j=n1;j<=n2;j++) - { - v=network.m_weights[w1+j-n1]; - for(i_=0;i_<=wcount-1;i_++) - rx[i].Set(i_,rx[i][i_]+v*ry[j][i_]); - rx[i].Set(w1+j-n1,rx[i][w1+j-n1]+network.m_neurons[j]); - } - for(i_=0;i_<=wcount-1;i_++) - ry[i].Set(i_,rx[i][i_]); - continue; - } - //--- check - if(network.m_structinfo[offs+0]<0) - { - bflag=true; - //--- check - if(network.m_structinfo[offs+0]==-2) - { - //--- input neuron,left unchanged - bflag=false; - } - //--- check - if(network.m_structinfo[offs+0]==-3) - { - //--- "-1" neuron,left unchanged - bflag=false; - } - //--- check - if(network.m_structinfo[offs+0]==-4) - { - //--- "0" neuron,left unchanged - bflag=false; - } - //--- check - if(!CAp::Assert(!bflag,__FUNCTION__+": internal error - unknown neuron type!")) - return; - continue; - } - } - //--- Hessian. Backward pass of the R-algorithm. - //--- Stage 1. Initialize RDY - for(i=0;i<=ntotal+nout-1;i++) - { - for(i_=0;i_<=wcount-1;i_++) - rdy[i].Set(i_,zeros[i_]); - } - //--- check - if(network.m_structinfo[6]==0) - { - //--- Standardisation. - //--- In context of the Hessian calculation standardisation - //--- is considered as additional layer with weightless - //--- activation function: - //--- F(NET) :=Sigma*NET - //--- So we add one more layer to forward pass,and - //--- make forward/backward pass through this layer. - for(i=0;i<=nout-1;i++) - { - n1=ntotal-nout+i; - n2=ntotal+i; - //--- Forward pass from N1 to N2 - for(i_=0;i_<=wcount-1;i_++) - rx[n2].Set(i_,ry[n1][i_]); - v=network.m_columnsigmas[nin+i]; - for(i_=0;i_<=wcount-1;i_++) - ry[n2].Set(i_,v*rx[n2][i_]); - //--- Initialization of RDY - for(i_=0;i_<=wcount-1;i_++) - rdy[n2].Set(i_,ry[n2][i_]); - //--- Backward pass from N2 to N1: - //--- 1. Calculate R(dE/dX). - //--- 2. No R(dE/dWij) is needed since weight of activation neuron - //--- is fixed to 1. So we can update R(dE/dY) for - //--- the connected neuron (note that Vij=0,Wij=1) - df=network.m_columnsigmas[nin+i]; - for(i_=0;i_<=wcount-1;i_++) - rdx[n2].Set(i_,df*rdy[n2][i_]); - for(i_=0;i_<=wcount-1;i_++) - rdy[n1].Set(i_,rdy[n1][i_]+rdx[n2][i_]); - } - } - else - { - //--- Softmax. - //--- Initialize RDY using generalized expression for ei'(yi) - //--- (see expression (9) from p. 5 of "Fast Exact Multiplication by the Hessian"). - //--- When we are working with softmax network,generalized - //--- expression for ei'(yi) is used because softmax - //--- normalization leads to ei,which depends on all y's - if(naturalerr) - { - //--- softmax + cross-entropy. - //--- We have: - //--- S=sum(exp(yk)), - //--- ei=sum(trn)*exp(yi)/S-trn_i - //--- j=i: d(ei)/d(yj)=T*exp(yi)*(S-exp(yi))/S^2 - //--- j<>i: d(ei)/d(yj)=-T*exp(yi)*exp(yj)/S^2 - t=0; - for(i=0;i<=nout-1;i++) - t=t+desiredy[i]; - mx=network.m_neurons[ntotal-nout]; - //--- calculation - for(i=0;i<=nout-1;i++) - mx=MathMax(mx,network.m_neurons[ntotal-nout+i]); - s=0; - for(i=0;i<=nout-1;i++) - { - network.m_nwbuf[i]=MathExp(network.m_neurons[ntotal-nout+i]-mx); - s=s+network.m_nwbuf[i]; - } - //--- calculation - for(i=0;i<=nout-1;i++) - { - for(j=0;j<=nout-1;j++) - { - //--- check - if(j==i) - { - deidyj=t*network.m_nwbuf[i]*(s-network.m_nwbuf[i])/CMath::Sqr(s); - for(i_=0;i_<=wcount-1;i_++) - rdy[ntotal-nout+i].Set(i_,rdy[ntotal-nout+i][i_]+deidyj*ry[ntotal-nout+i][i_]); - } - else - { - deidyj=-(t*network.m_nwbuf[i]*network.m_nwbuf[j]/CMath::Sqr(s)); - for(i_=0;i_<=wcount-1;i_++) - rdy[ntotal-nout+i].Set(i_,rdy[ntotal-nout+i][i_]+deidyj*ry[ntotal-nout+j][i_]); - } - } - } - } - else - { - //--- For a softmax + squared error we have expression - //--- far beyond human imagination so we dont even try - //--- to comment on it. Just enjoy the code... - //--- P.S. That's why "natural error" is called "natural" - - //--- compact beatiful expressions,fast code.... - mx=network.m_neurons[ntotal-nout]; - for(i=0;i<=nout-1;i++) - mx=MathMax(mx,network.m_neurons[ntotal-nout+i]); - //--- calculation - s=0; - s2=0; - for(i=0;i<=nout-1;i++) - { - network.m_nwbuf[i]=MathExp(network.m_neurons[ntotal-nout+i]-mx); - s=s+network.m_nwbuf[i]; - s2=s2+CMath::Sqr(network.m_nwbuf[i]); - } - //--- calculation - q=0; - for(i=0;i<=nout-1;i++) - q=q+(network.m_y[i]-desiredy[i])*network.m_nwbuf[i]; - for(i=0;i<=nout-1;i++) - { - //--- change values - z=-q+(network.m_y[i]-desiredy[i])*s; - expi=network.m_nwbuf[i]; - for(j=0;j<=nout-1;j++) - { - expj=network.m_nwbuf[j]; - //--- check - if(j==i) - deidyj=expi/CMath::Sqr(s)*((z+expi)*(s-2*expi)/s+expi*s2/CMath::Sqr(s)); - else - deidyj=expi*expj/CMath::Sqr(s)*(s2/CMath::Sqr(s)-2*z/s-(expi+expj)/s+(network.m_y[i]-desiredy[i])-(network.m_y[j]-desiredy[j])); - for(i_=0;i_<=wcount-1;i_++) - rdy[ntotal-nout+i].Set(i_,rdy[ntotal-nout+i][i_]+deidyj*ry[ntotal-nout+j][i_]); - } - } - } - } - //--- Hessian. Backward pass of the R-algorithm - //--- Stage 2. Process. - for(i=ntotal-1;i>=0;i--) - { - //--- Possible variants: - //--- 1. Activation function - //--- 2. Adaptive summator - //--- 3. Special neuron - offs=istart+i*m_nfieldwidth; - //--- check - if(network.m_structinfo[offs+0]>0 || network.m_structinfo[offs+0]==-5) - { - n1=network.m_structinfo[offs+2]; - //--- First,calculate R(dE/dX). - MLPActivationFunction(network.m_neurons[n1],network.m_structinfo[offs+0],f,df,d2f); - v=d2f*network.m_derror[i]; - for(i_=0;i_<=wcount-1;i_++) - rdx[i].Set(i_,df*rdy[i][i_]); - for(i_=0;i_<=wcount-1;i_++) - rdx[i].Set(i_,rdx[i][i_]+v*rx[i][i_]); - //--- No R(dE/dWij) is needed since weight of activation neuron - //--- is fixed to 1. - //--- So we can update R(dE/dY) for the connected neuron. - //--- (note that Vij=0,Wij=1) - for(i_=0;i_<=wcount-1;i_++) - rdy[n1].Set(i_,rdy[n1][i_]+rdx[i][i_]); - continue; - } - //--- check - if(network.m_structinfo[offs+0]==0) - { - //--- Adaptive summator - n1=network.m_structinfo[offs+2]; - n2=n1+network.m_structinfo[offs+1]-1; - w1=network.m_structinfo[offs+3]; - w2=w1+network.m_structinfo[offs+1]-1; - //--- First,calculate R(dE/dX). - for(i_=0;i_<=wcount-1;i_++) - rdx[i].Set(i_,rdy[i][i_]); - //--- Then,calculate R(dE/dWij) - for(j=w1;j<=w2;j++) - { - v=network.m_neurons[n1+j-w1]; - for(i_=0;i_<=wcount-1;i_++) - h[j].Set(i_,h[j][i_]+v*rdx[i][i_]); - //--- calculation - v=network.m_derror[i]; - for(i_=0;i_<=wcount-1;i_++) - h[j].Set(i_,h[j][i_]+v*ry[n1+j-w1][i_]); - } - //--- And finally,update R(dE/dY) for connected neurons. - for(j=w1;j<=w2;j++) - { - v=network.m_weights[j]; - for(i_=0;i_<=wcount-1;i_++) - rdy[n1+j-w1].Set(i_,rdy[n1+j-w1][i_]+v*rdx[i][i_]); - rdy[n1+j-w1].Set(j,rdy[n1+j-w1][j]+network.m_derror[i]); - } - continue; - } - //--- check - if(network.m_structinfo[offs+0]<0) - { - bflag=false; - //--- check - if((network.m_structinfo[offs+0]==-2 || network.m_structinfo[offs+0]==-3) || network.m_structinfo[offs+0]==-4) - { - //--- Special neuron type,no back-propagation required - bflag=true; - } - //--- check - if(!CAp::Assert(bflag,__FUNCTION__+": unknown neuron type!")) - return; - continue; - } - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//| Network must be processed by MLPProcess on X | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPInternalCalculateGradient(CMultilayerPerceptron &network, - double &neurons[], - double &weights[], - double &derror[], - double &grad[], - const bool naturalerrorfunc) - { -//--- create variables - int i=0; - int n1=0; - int n2=0; - int w1=0; - int w2=0; - int ntotal=0; - int istart=0; - int nin=0; - int nout=0; - int offs=0; - double dedf=0; - double dfdnet=0; - double v=0; - double fown=0; - double deown=0; - double net=0; - double mx=0; - bool bflag; - int i_=0; - int i1_=0; -//--- Read network geometry - nin=network.m_structinfo[1]; - nout=network.m_structinfo[2]; - ntotal=network.m_structinfo[3]; - istart=network.m_structinfo[5]; -//--- Pre-processing of dError/dOut: -//--- from dError/dOut(normalized) to dError/dOut(non-normalized) - if(!CAp::Assert(network.m_structinfo[6]==0 || network.m_structinfo[6]==1,__FUNCTION__+": unknown normalization type!")) - return; -//--- check - if(network.m_structinfo[6]==1) - { - //--- Softmax - if(!naturalerrorfunc) - { - mx=network.m_neurons[ntotal-nout]; - for(i=0;i<=nout-1;i++) - mx=MathMax(mx,network.m_neurons[ntotal-nout+i]); - net=0; - for(i=0;i<=nout-1;i++) - { - network.m_nwbuf[i]=MathExp(network.m_neurons[ntotal-nout+i]-mx); - net=net+network.m_nwbuf[i]; - } - //--- calculation - i1_=-(ntotal-nout); - v=0.0; - for(i_=ntotal-nout;i_<=ntotal-1;i_++) - v+=network.m_derror[i_]*network.m_nwbuf[i_+i1_]; - for(i=0;i<=nout-1;i++) - { - fown=network.m_nwbuf[i]; - deown=network.m_derror[ntotal-nout+i]; - network.m_nwbuf[nout+i]=(-v+deown*fown+deown*(net-fown))*fown/CMath::Sqr(net); - } - for(i=0;i<=nout-1;i++) - network.m_derror[ntotal-nout+i]=network.m_nwbuf[nout+i]; - } - } - else - { - //--- Un-standardisation - for(i=0;i<=nout-1;i++) - network.m_derror[ntotal-nout+i]=network.m_derror[ntotal-nout+i]*network.m_columnsigmas[nin+i]; - } -//--- Backpropagation - for(i=ntotal-1;i>=0;i--) - { - //--- Extract info - offs=istart+i*m_nfieldwidth; - //--- check - if(network.m_structinfo[offs+0]>0 || network.m_structinfo[offs+0]==-5) - { - //--- Activation function - dedf=network.m_derror[i]; - dfdnet=network.m_dfdnet[i]; - derror[network.m_structinfo[offs+2]]=derror[network.m_structinfo[offs+2]]+dedf*dfdnet; - continue; - } - //--- check - if(network.m_structinfo[offs+0]==0) - { - //--- Adaptive summator - n1=network.m_structinfo[offs+2]; - n2=n1+network.m_structinfo[offs+1]-1; - w1=network.m_structinfo[offs+3]; - w2=w1+network.m_structinfo[offs+1]-1; - dedf=network.m_derror[i]; - dfdnet=1.0; - v=dedf*dfdnet; - i1_=n1-w1; - //--- calculation - for(i_=w1;i_<=w2;i_++) - grad[i_]=v*neurons[i_+i1_]; - i1_=w1-n1; - for(i_=n1;i_<=n2;i_++) - derror[i_]=derror[i_]+v*weights[i_+i1_]; - continue; - } - //--- check - if(network.m_structinfo[offs+0]<0) - { - bflag=false; - //--- check - if((network.m_structinfo[offs+0]==-2 || network.m_structinfo[offs+0]==-3) || network.m_structinfo[offs+0]==-4) - { - //--- Special neuron type,no back-propagation required - bflag=true; - } - //--- check - if(!CAp::Assert(bflag,__FUNCTION__+": unknown neuron type!")) - return; - continue; - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine, chunked gradient | -//+------------------------------------------------------------------+ -static void CMLPBase::MLPChunkedGradient(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int cstart, - const int csize,double &e, - double &grad[],const bool naturalerrorfunc) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int kl=0; - int n1=0; - int n2=0; - int w1=0; - int w2=0; - int c1=0; - int c2=0; - int ntotal=0; - int nin=0; - int nout=0; - int offs=0; - double f=0; - double df=0; - double d2f=0; - double v=0; - double s=0; - double fown=0; - double deown=0; - double net=0; - double lnnet=0; - double mx=0; - bool bflag; - int istart=0; - int ineurons=0; - int idfdnet=0; - int iderror=0; - int izeros=0; - int i_=0; - int i1_=0; -//--- Read network geometry,prepare data - nin=network.m_structinfo[1]; - nout=network.m_structinfo[2]; - ntotal=network.m_structinfo[3]; - istart=network.m_structinfo[5]; - c1=cstart; - c2=cstart+csize-1; - ineurons=0; - idfdnet=ntotal; - iderror=2*ntotal; - izeros=3*ntotal; - for(j=0;j<=csize-1;j++) - network.m_chunks[izeros].Set(j,0); -//--- Forward pass: -//--- 1. Load inputs from XY to Chunks[0:NIn-1,0:CSize-1] -//--- 2. Forward pass - for(i=0;i<=nin-1;i++) - { - for(j=0;j<=csize-1;j++) - { - //--- check - if(network.m_columnsigmas[i]!=0.0) - network.m_chunks[i].Set(j,(xy[c1+j][i]-network.m_columnmeans[i])/network.m_columnsigmas[i]); - else - network.m_chunks[i].Set(j,xy[c1+j][i]-network.m_columnmeans[i]); - } - } - for(i=0;i<=ntotal-1;i++) - { - offs=istart+i*m_nfieldwidth; - //--- check - if(network.m_structinfo[offs+0]>0 || network.m_structinfo[offs+0]==-5) - { - //--- Activation function: - //--- * calculate F vector,F(i)=F(NET(i)) - n1=network.m_structinfo[offs+2]; - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[i].Set(i_,network.m_chunks[n1][i_]); - for(j=0;j<=csize-1;j++) - { - //--- function call - MLPActivationFunction(network.m_chunks[i][j],network.m_structinfo[offs+0],f,df,d2f); - //--- change values - network.m_chunks[i].Set(j,f); - network.m_chunks[idfdnet+i].Set(j,df); - } - continue; - } - //--- check - if(network.m_structinfo[offs+0]==0) - { - //--- Adaptive summator: - //--- * calculate NET vector,NET(i)=SUM(W(j,i)*Neurons(j),j=N1..N2) - n1=network.m_structinfo[offs+2]; - n2=n1+network.m_structinfo[offs+1]-1; - w1=network.m_structinfo[offs+3]; - w2=w1+network.m_structinfo[offs+1]-1; - //--- calculation - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[i].Set(i_,network.m_chunks[izeros][i_]); - for(j=n1;j<=n2;j++) - { - v=network.m_weights[w1+j-n1]; - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[i].Set(i_,network.m_chunks[i][i_]+v*network.m_chunks[j][i_]); - } - continue; - } - //--- check - if(network.m_structinfo[offs+0]<0) - { - bflag=false; - //--- check - if(network.m_structinfo[offs+0]==-2) - { - //--- input neuron,left unchanged - bflag=true; - } - //--- check - if(network.m_structinfo[offs+0]==-3) - { - //--- "-1" neuron - for(k=0;k<=csize-1;k++) - network.m_chunks[i].Set(k,-1); - bflag=true; - } - //--- check - if(network.m_structinfo[offs+0]==-4) - { - //--- "0" neuron - for(k=0;k<=csize-1;k++) - network.m_chunks[i].Set(k,0); - bflag=true; - } - //--- check - if(!CAp::Assert(bflag,__FUNCTION__+": internal error - unknown neuron type!")) - return; - continue; - } - } -//--- Post-processing,error,dError/dOut - for(i=0;i<=ntotal-1;i++) - { - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[iderror+i].Set(i_,network.m_chunks[izeros][i_]); - } -//--- check - if(!CAp::Assert(network.m_structinfo[6]==0 || network.m_structinfo[6]==1,__FUNCTION__+": unknown normalization type!")) - return; -//--- check - if(network.m_structinfo[6]==1) - { - //--- Softmax output,classification network. - //--- For each K=0..CSize-1 do: - //--- 1. place exp(outputs[k]) to NWBuf[0:NOut-1] - //--- 2. place sum(exp(..)) to NET - //--- 3. calculate dError/dOut and place it to the second block of Chunks - for(k=0;k<=csize-1;k++) - { - //--- Normalize - mx=network.m_chunks[ntotal-nout][k]; - for(i=1;i<=nout-1;i++) - mx=MathMax(mx,network.m_chunks[ntotal-nout+i][k]); - net=0; - for(i=0;i<=nout-1;i++) - { - network.m_nwbuf[i]=MathExp(network.m_chunks[ntotal-nout+i][k]-mx); - net=net+network.m_nwbuf[i]; - } - //--- Calculate error function and dError/dOut - if(naturalerrorfunc) - { - //--- Natural error func. - s=1; - lnnet=MathLog(net); - kl=(int)MathRound(xy[cstart+k][nin]); - //--- calculation - for(i=0;i<=nout-1;i++) - { - //--- check - if(i==kl) - v=1; - else - v=0; - network.m_chunks[iderror+ntotal-nout+i].Set(k,s*network.m_nwbuf[i]/net-v); - e=e+SafeCrossEntropy(v,network.m_nwbuf[i]/net); - } - } - else - { - //--- Least squares error func - //--- Error,dError/dOut(normalized) - kl=(int)MathRound(xy[cstart+k][nin]); - for(i=0;i<=nout-1;i++) - { - //--- check - if(i==kl) - v=network.m_nwbuf[i]/net-1; - else - v=network.m_nwbuf[i]/net; - network.m_nwbuf[nout+i]=v; - e=e+CMath::Sqr(v)/2; - } - //--- From dError/dOut(normalized) to dError/dOut(non-normalized) - i1_=-nout; - v=0.0; - for(i_=nout;i_<=2*nout-1;i_++) - v+=network.m_nwbuf[i_]*network.m_nwbuf[i_+i1_]; - //--- calculation - for(i=0;i<=nout-1;i++) - { - fown=network.m_nwbuf[i]; - deown=network.m_nwbuf[nout+i]; - network.m_chunks[iderror+ntotal-nout+i].Set(k,(-v+deown*fown+deown*(net-fown))*fown/CMath::Sqr(net)); - } - } - } - } - else - { - //--- Normal output,regression network - //--- For each K=0..CSize-1 do: - //--- 1. calculate dError/dOut and place it to the second block of Chunks - for(i=0;i<=nout-1;i++) - { - for(j=0;j<=csize-1;j++) - { - v=network.m_chunks[ntotal-nout+i][j]*network.m_columnsigmas[nin+i]+network.m_columnmeans[nin+i]-xy[cstart+j][nin+i]; - network.m_chunks[iderror+ntotal-nout+i].Set(j,v*network.m_columnsigmas[nin+i]); - e=e+CMath::Sqr(v)/2; - } - } - } -//--- Backpropagation - for(i=ntotal-1;i>=0;i--) - { - //--- Extract info - offs=istart+i*m_nfieldwidth; - //--- check - if(network.m_structinfo[offs+0]>0 || network.m_structinfo[offs+0]==-5) - { - //--- Activation function - n1=network.m_structinfo[offs+2]; - for(k=0;k<=csize-1;k++) - network.m_chunks[iderror+i].Set(k,network.m_chunks[iderror+i][k]*network.m_chunks[idfdnet+i][k]); - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[iderror+n1].Set(i_,network.m_chunks[iderror+n1][i_]+network.m_chunks[iderror+i][i_]); - continue; - } - //--- check - if(network.m_structinfo[offs+0]==0) - { - //--- "Normal" activation function - n1=network.m_structinfo[offs+2]; - n2=n1+network.m_structinfo[offs+1]-1; - w1=network.m_structinfo[offs+3]; - w2=w1+network.m_structinfo[offs+1]-1; - //--- calculation - for(j=w1;j<=w2;j++) - { - v=0.0; - for(i_=0;i_<=csize-1;i_++) - v+=network.m_chunks[n1+j-w1][i_]*network.m_chunks[iderror+i][i_]; - grad[j]=grad[j]+v; - } - //--- calculation - for(j=n1;j<=n2;j++) - { - v=network.m_weights[w1+j-n1]; - for(i_=0;i_<=csize-1;i_++) - network.m_chunks[iderror+j].Set(i_,network.m_chunks[iderror+j][i_]+v*network.m_chunks[iderror+i][i_]); - } - continue; - } - //--- check - if(network.m_structinfo[offs+0]<0) - { - bflag=false; - //--- check - if((network.m_structinfo[offs+0]==-2 || network.m_structinfo[offs+0]==-3) || network.m_structinfo[offs+0]==-4) - { - //--- Special neuron type,no back-propagation required - bflag=true; - } - //--- check - if(!CAp::Assert(bflag,__FUNCTION__+": unknown neuron type!")) - return; - continue; - } - } - } -//+------------------------------------------------------------------+ -//| Returns T*Ln(T/Z), guarded against overflow/underflow. | -//| Internal subroutine. | -//+------------------------------------------------------------------+ -static double CMLPBase::SafeCrossEntropy(const double t,const double z) - { -//--- create variables - double result=0; - double r=0; -//--- check - if(t==0.0) - result=0; - else - { - //--- check - if(MathAbs(z)>1.0) - { - //--- Shouldn't be the case with softmax, - //--- but we just want to be sure. - if(t/z==0.0) - r=CMath::m_minrealnumber; - else - r=t/z; - } - else - { - //--- Normal case - if(z==0.0 || MathAbs(t)>=CMath::m_maxrealnumber*MathAbs(z)) - r=CMath::m_maxrealnumber; - else - r=t/z; - } - //--- get result - result=t*MathLog(r); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CLogit | -//+------------------------------------------------------------------+ -class CLogitModel - { -public: - double m_w[]; - //--- constructor, destructor - CLogitModel(void); - ~CLogitModel(void); - //--- copy - void Copy(CLogitModel &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLogitModel::CLogitModel(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLogitModel::~CLogitModel(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CLogitModel::Copy(CLogitModel &obj) - { -//--- copy array - ArrayCopy(m_w,obj.m_w); - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CLogitModel | -//+------------------------------------------------------------------+ -class CLogitModelShell - { -private: - CLogitModel m_innerobj; -public: - //--- constructors, destructor - CLogitModelShell(void); - CLogitModelShell(CLogitModel &obj); - ~CLogitModelShell(void); - //--- method - CLogitModel *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLogitModelShell::CLogitModelShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CLogitModelShell::CLogitModelShell(CLogitModel &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLogitModelShell::~CLogitModelShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CLogitModel *CLogitModelShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CLogit | -//+------------------------------------------------------------------+ -class CLogitMCState - { -public: - //--- variables - bool m_brackt; - bool m_stage1; - int m_infoc; - double m_dg; - double m_dgm; - double m_dginit; - double m_dgtest; - double m_dgx; - double m_dgxm; - double m_dgy; - double m_dgym; - double m_finit; - double m_ftest1; - double m_fm; - double m_fx; - double m_fxm; - double m_fy; - double m_fym; - double m_stx; - double m_sty; - double m_stmin; - double m_stmax; - double m_width; - double m_width1; - double m_xtrapf; - //--- constructor, destructor - CLogitMCState(void); - ~CLogitMCState(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLogitMCState::CLogitMCState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLogitMCState::~CLogitMCState(void) - { - - } -//+------------------------------------------------------------------+ -//| MNLReport structure contains information about training process: | -//| * NGrad - number of gradient calculations | -//| * NHess - number of Hessian calculations | -//+------------------------------------------------------------------+ -class CMNLReport - { -public: - //--- variables - int m_ngrad; - int m_nhess; - //--- constructor, destructor - CMNLReport(void); - ~CMNLReport(void); - //--- copy - void Copy(CMNLReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMNLReport::CMNLReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMNLReport::~CMNLReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMNLReport::Copy(CMNLReport &obj) - { -//--- copy variables - m_ngrad=obj.m_ngrad; - m_nhess=obj.m_nhess; - } -//+------------------------------------------------------------------+ -//| MNLReport structure contains information about training process: | -//| * NGrad - number of gradient calculations | -//| * NHess - number of Hessian calculations | -//+------------------------------------------------------------------+ -class CMNLReportShell - { -private: - CMNLReport m_innerobj; -public: - //--- constructors, destructor - CMNLReportShell(void); - CMNLReportShell(CMNLReport &obj); - ~CMNLReportShell(void); - //--- methods - int GetNGrad(void); - void SetNGrad(const int i); - int GetNHess(void); - void SetNHess(const int i); - CMNLReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMNLReportShell::CMNLReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMNLReportShell::CMNLReportShell(CMNLReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMNLReportShell::~CMNLReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ngrad | -//+------------------------------------------------------------------+ -int CMNLReportShell::GetNGrad(void) - { -//--- return result - return(m_innerobj.m_ngrad); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ngrad | -//+------------------------------------------------------------------+ -void CMNLReportShell::SetNGrad(const int i) - { -//--- change value - m_innerobj.m_ngrad=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nhess | -//+------------------------------------------------------------------+ -int CMNLReportShell::GetNHess(void) - { -//--- return result - return(m_innerobj.m_nhess); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nhess | -//+------------------------------------------------------------------+ -void CMNLReportShell::SetNHess(const int i) - { -//--- change value - m_innerobj.m_nhess=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMNLReport *CMNLReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Class logit model | -//+------------------------------------------------------------------+ -class CLogit - { -private: - //--- private methods - static void MNLIExp(double &w[],double &x[]); - static void MNLAllErrors(CLogitModel &lm,CMatrixDouble &xy,const int npoints,double &relcls,double &avgce,double &rms,double &avg,double &avgrel); - static void MNLMCSrch(const int n,double &x[],double &f,double &g[],double &s[],double &stp,int &info,int &nfev,double &wa[],CLogitMCState &state,int &stage); - static void MNLMCStep(double &stx,double &fx,double &dx,double &sty,double &fy,double &dy,double &stp,const double fp,const double dp,bool &brackt,const double stmin,const double stmax,int &info); -public: - //--- variables - static const double m_xtol; - static const double m_ftol; - static const double m_gtol; - static const int m_maxfev; - static const double m_stpmin; - static const double m_stpmax; - static const int m_logitvnum; - //--- constructor, destructor - CLogit(void); - ~CLogit(void); - //--- public methods - static void MNLTrainH(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,CLogitModel &lm,CMNLReport &rep); - static void MNLProcess(CLogitModel &lm,double &x[],double &y[]); - static void MNLProcessI(CLogitModel &lm,double &x[],double &y[]); - static void MNLUnpack(CLogitModel &lm,CMatrixDouble &a,int &nvars,int &nclasses); - static void MNLPack(CMatrixDouble &a,const int nvars,const int nclasses,CLogitModel &lm); - static void MNLCopy(CLogitModel &lm1,CLogitModel &lm2); - static double MNLAvgCE(CLogitModel &lm,CMatrixDouble &xy,const int npoints); - static double MNLRelClsError(CLogitModel &lm,CMatrixDouble &xy,const int npoints); - static double MNLRMSError(CLogitModel &lm,CMatrixDouble &xy,const int npoints); - static double MNLAvgError(CLogitModel &lm,CMatrixDouble &xy,const int npoints); - static double MNLAvgRelError(CLogitModel &lm,CMatrixDouble &xy,const int ssize); - static int MNLClsError(CLogitModel &lm,CMatrixDouble &xy,const int npoints); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CLogit::m_xtol=100*CMath::m_machineepsilon; -const double CLogit::m_ftol=0.0001; -const double CLogit::m_gtol=0.3; -const int CLogit::m_maxfev=20; -const double CLogit::m_stpmin=1.0E-2; -const double CLogit::m_stpmax=1.0E5; -const int CLogit::m_logitvnum=6; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLogit::CLogit(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLogit::~CLogit(void) - { - - } -//+------------------------------------------------------------------+ -//| This subroutine trains logit model. | -//| INPUT PARAMETERS: | -//| XY - training set, array[0..NPoints-1,0..NVars] | -//| First NVars columns store values of | -//| independent variables, next column stores | -//| number of class (from 0 to NClasses-1) which | -//| dataset element belongs to. Fractional values| -//| are rounded to nearest integer. | -//| NPoints - training set size, NPoints>=1 | -//| NVars - number of independent variables, NVars>=1 | -//| NClasses - number of classes, NClasses>=2 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints=nclasses) - { - info=-2; - return; - } - } -//--- change value - info=1; -//--- Initialize data - rep.m_ngrad=0; - rep.m_nhess=0; -//--- Allocate array - wdim=(nvars+1)*(nclasses-1); - offs=5; - expoffs=offs+wdim; - ssize=5+(nvars+1)*(nclasses-1)+nclasses; -//--- allocation - ArrayResizeAL(lm.m_w,ssize); -//--- change values - lm.m_w[0]=ssize; - lm.m_w[1]=m_logitvnum; - lm.m_w[2]=nvars; - lm.m_w[3]=nclasses; - lm.m_w[4]=offs; -//--- Degenerate case: all outputs are equal - allsame=true; - for(i=1;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][nvars])!=(int)MathRound(xy[i-1][nvars])) - allsame=false; - } -//--- check - if(allsame) - { - for(i=0;i<=(nvars+1)*(nclasses-1)-1;i++) - lm.m_w[offs+i]=0; - //--- change values - v=-(2*MathLog(CMath::m_minrealnumber)); - k=(int)MathRound(xy[0][nvars]); - //--- check - if(k==nclasses-1) - { - for(i=0;i<=nclasses-2;i++) - lm.m_w[offs+i*(nvars+1)+nvars]=-v; - } - else - { - for(i=0;i<=nclasses-2;i++) - { - //--- check - if(i==k) - lm.m_w[offs+i*(nvars+1)+nvars]=v; - else - lm.m_w[offs+i*(nvars+1)+nvars]=0; - } - } - //--- exit the function - return; - } -//--- General case. -//--- Prepare task and network. Allocate space. - CMLPBase::MLPCreateC0(nvars,nclasses,network); -//--- function call - CMLPBase::MLPInitPreprocessor(network,xy,npoints); -//--- function call - CMLPBase::MLPProperties(network,nin,nout,wcount); - for(i=0;i<=wcount-1;i++) - network.m_weights[i]=(2*CMath::RandomReal()-1)/nvars; -//--- allocation - ArrayResizeAL(g,wcount); - h.Resize(wcount,wcount); - ArrayResizeAL(wbase,wcount); - ArrayResizeAL(wdir,wcount); - ArrayResizeAL(work,wcount); -//--- First stage: optimize in gradient direction. - for(k=0;k<=wcount/3+10;k++) - { - //--- Calculate gradient in starting point - CMLPBase::MLPGradNBatch(network,xy,npoints,e,g); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - rep.m_ngrad=rep.m_ngrad+1; - //--- Setup optimization scheme - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=-g[i_]; - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=wdir[i_]*wdir[i_]; - //--- change values - wstep=MathSqrt(v); - v=1/MathSqrt(v); - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=v*wdir[i_]; - mcstage=0; - //--- function call - MNLMCSrch(wcount,network.m_weights,e,g,wdir,wstep,mcinfo,mcnfev,work,mcstate,mcstage); - //--- cycle - while(mcstage!=0) - { - //--- function call - CMLPBase::MLPGradNBatch(network,xy,npoints,e,g); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - rep.m_ngrad=rep.m_ngrad+1; - //--- function call - MNLMCSrch(wcount,network.m_weights,e,g,wdir,wstep,mcinfo,mcnfev,work,mcstate,mcstage); - } - } -//--- Second stage: use Hessian when we are close to the minimum - while(true) - { - //--- Calculate and update E/G/H - CMLPBase::MLPHessianNBatch(network,xy,npoints,e,g,h); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - for(k=0;k<=wcount-1;k++) - h[k].Set(k,h[k][k]+decay); - rep.m_nhess=rep.m_nhess+1; - //--- Select step direction - //--- NOTE: it is important to use lower-triangle Cholesky - //--- factorization since it is much faster than higher-triangle version. - spd=CTrFac::SPDMatrixCholesky(h,wcount,false); - //--- function call - CDenseSolver::SPDMatrixCholeskySolve(h,wcount,false,g,solverinfo,solverrep,wdir); - spd=solverinfo>0; - //--- check - if(spd) - { - //--- H is positive definite. - //--- Step in Newton direction. - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=-1*wdir[i_]; - spd=true; - } - else - { - //--- H is indefinite. - //--- Step in gradient direction. - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=-g[i_]; - spd=false; - } - //--- Optimize in WDir direction - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=wdir[i_]*wdir[i_]; - //--- change values - wstep=MathSqrt(v); - v=1/MathSqrt(v); - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=v*wdir[i_]; - mcstage=0; - //--- function call - MNLMCSrch(wcount,network.m_weights,e,g,wdir,wstep,mcinfo,mcnfev,work,mcstate,mcstage); - //--- cycle - while(mcstage!=0) - { - //--- function call - CMLPBase::MLPGradNBatch(network,xy,npoints,e,g); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - rep.m_ngrad=rep.m_ngrad+1; - //--- function call - MNLMCSrch(wcount,network.m_weights,e,g,wdir,wstep,mcinfo,mcnfev,work,mcstate,mcstage); - } - //--- check - if(spd && ((mcinfo==2 || mcinfo==4) || mcinfo==6)) - break; - } -//--- Convert from NN format to MNL format - i1_=-offs; - for(i_=offs;i_<=offs+wcount-1;i_++) - lm.m_w[i_]=network.m_weights[i_+i1_]; - for(k=0;k<=nvars-1;k++) - { - for(i=0;i<=nclasses-2;i++) - { - s=network.m_columnsigmas[k]; - //--- check - if(s==0.0) - s=1; - //--- change values - j=offs+(nvars+1)*i; - v=lm.m_w[j+k]; - lm.m_w[j+k]=v/s; - lm.m_w[j+nvars]=lm.m_w[j+nvars]+v*network.m_columnmeans[k]/s; - } - } -//--- calculation - for(k=0;k<=nclasses-2;k++) - lm.m_w[offs+(nvars+1)*k+nvars]=-lm.m_w[offs+(nvars+1)*k+nvars]; - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| LM - logit model, passed by non-constant reference | -//| (some fields of structure are used as temporaries| -//| when calculating model output). | -//| X - input vector, array[0..NVars-1]. | -//| Y - (possibly) preallocated buffer; if size of Y is | -//| less than NClasses, it will be reallocated.If it | -//| is large enough, it is NOT reallocated, so we | -//| can save some time on reallocation. | -//| OUTPUT PARAMETERS: | -//| Y - result, array[0..NClasses-1] | -//| Vector of posterior probabilities for | -//| classification task. | -//+------------------------------------------------------------------+ -static void CLogit::MNLProcess(CLogitModel &lm,double &x[],double &y[]) - { -//--- create variables - int nvars=0; - int nclasses=0; - int offs=0; - int i=0; - int i1=0; - double s=0; -//--- check - if(!CAp::Assert(lm.m_w[1]==m_logitvnum,__FUNCTION__+": unexpected model version")) - return; -//--- initialization - nvars=(int)MathRound(lm.m_w[2]); - nclasses=(int)MathRound(lm.m_w[3]); - offs=(int)MathRound(lm.m_w[4]); -//--- function call - MNLIExp(lm.m_w,x); - s=0; -//--- calculation - i1=offs+(nvars+1)*(nclasses-1); - for(i=i1;i<=i1+nclasses-1;i++) - s=s+lm.m_w[i]; -//--- check - if(CAp::Len(y)=0 &&(int)MathRound(xy[i][nvars])0.0) - result=result-MathLog(worky[(int)MathRound(xy[i][nvars])]); - else - result=result-MathLog(CMath::m_minrealnumber); - } -//--- return result - return(result/(npoints*MathLog(2))); - } -//+------------------------------------------------------------------+ -//| Relative classification error on the test set | -//| INPUT PARAMETERS: | -//| LM - logit model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| percent of incorrectly classified cases. | -//+------------------------------------------------------------------+ -static double CLogit::MNLRelClsError(CLogitModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- return result - return((double)MNLClsError(lm,xy,npoints)/(double)npoints); - } -//+------------------------------------------------------------------+ -//| RMS error on the test set | -//| INPUT PARAMETERS: | -//| LM - logit model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| root mean square error (error when estimating posterior | -//| probabilities). | -//+------------------------------------------------------------------+ -static double CLogit::MNLRMSError(CLogitModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double relcls=0; - double avgce=0; - double rms=0; - double avg=0; - double avgrel=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_logitvnum,__FUNCTION__+": Incorrect MNL version!")) - return(EMPTY_VALUE); -//--- function call - MNLAllErrors(lm,xy,npoints,relcls,avgce,rms,avg,avgrel); -//--- return result - return(rms); - } -//+------------------------------------------------------------------+ -//| Average error on the test set | -//| INPUT PARAMETERS: | -//| LM - logit model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| average error (error when estimating posterior | -//| probabilities). | -//+------------------------------------------------------------------+ -static double CLogit::MNLAvgError(CLogitModel &lm,CMatrixDouble &xy, - const int npoints) - { -//--- create variables - double relcls=0; - double avgce=0; - double rms=0; - double avg=0; - double avgrel=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_logitvnum,__FUNCTION__+": Incorrect MNL version!")) - return(EMPTY_VALUE); -//--- function call - MNLAllErrors(lm,xy,npoints,relcls,avgce,rms,avg,avgrel); -//--- return result - return(avg); - } -//+------------------------------------------------------------------+ -//| Average relative error on the test set | -//| INPUT PARAMETERS: | -//| LM - logit model | -//| XY - test set | -//| NPoints - test set size | -//| RESULT: | -//| average relative error (error when estimating posterior | -//| probabilities). | -//+------------------------------------------------------------------+ -static double CLogit::MNLAvgRelError(CLogitModel &lm,CMatrixDouble &xy, - const int ssize) - { -//--- create variables - double relcls=0; - double avgce=0; - double rms=0; - double avg=0; - double avgrel=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_logitvnum,__FUNCTION__+": Incorrect MNL version!")) - return(EMPTY_VALUE); -//--- function call - MNLAllErrors(lm,xy,ssize,relcls,avgce,rms,avg,avgrel); -//--- return result - return(avgrel); - } -//+------------------------------------------------------------------+ -//| Classification error on test set = MNLRelClsError*NPoints | -//+------------------------------------------------------------------+ -static int CLogit::MNLClsError(CLogitModel &lm,CMatrixDouble &xy,const int npoints) - { -//--- create variables - int result=0; - int nvars=0; - int nclasses=0; - int i=0; - int j=0; - int nmax=0; - int i_=0; -//--- creating arrays - double workx[]; - double worky[]; -//--- check - if(!CAp::Assert(lm.m_w[1]==m_logitvnum,__FUNCTION__+": unexpected model version")) - return(-1); -//--- initialization - nvars=(int)MathRound(lm.m_w[2]); - nclasses=(int)MathRound(lm.m_w[3]); -//--- allocation - ArrayResizeAL(workx,nvars); - ArrayResizeAL(worky,nclasses); -//--- calculation - for(i=0;i<=npoints-1;i++) - { - //--- Process - for(i_=0;i_<=nvars-1;i_++) - workx[i_]=xy[i][i_]; - //--- function call - MNLProcess(lm,workx,worky); - //--- Logit version of the answer - nmax=0; - for(j=0;j<=nclasses-1;j++) - { - //--- check - if(worky[j]>worky[nmax]) - nmax=j; - } - //--- compare - if(nmax!=(int)MathRound(xy[i][nvars])) - result=result+1; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine. Places exponents of the anti-overflow | -//| shifted internal linear outputs into the service part of the W | -//| array. | -//+------------------------------------------------------------------+ -static void CLogit::MNLIExp(double &w[],double &x[]) - { -//--- create variables - int nvars=0; - int nclasses=0; - int offs=0; - int i=0; - int i1=0; - double v=0; - double mx=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert(w[1]==m_logitvnum,__FUNCTION__+": unexpected model version")) - return; -//--- initialization - nvars=(int)MathRound(w[2]); - nclasses=(int)MathRound(w[3]); - offs=(int)MathRound(w[4]); -//--- calculation - i1=offs+(nvars+1)*(nclasses-1); - for(i=0;i<=nclasses-2;i++) - { - //--- change values - i1_=-(offs+i*(nvars+1)); - v=0.0; - for(i_=offs+i*(nvars+1);i_<=offs+i*(nvars+1)+nvars-1;i_++) - v+=w[i_]*x[i_+i1_]; - w[i1+i]=v+w[offs+i*(nvars+1)+nvars]; - } -//--- change values - w[i1+nclasses-1]=0; - mx=0; -//--- calculation - for(i=i1;i<=i1+nclasses-1;i++) - mx=MathMax(mx,w[i]); - for(i=i1;i<=i1+nclasses-1;i++) - w[i]=MathExp(w[i]-mx); - } -//+------------------------------------------------------------------+ -//| Calculation of all types of errors | -//+------------------------------------------------------------------+ -static void CLogit::MNLAllErrors(CLogitModel &lm,CMatrixDouble &xy, - const int npoints,double &relcls, - double &avgce,double &rms,double &avg, - double &avgrel) - { -//--- create variables - int nvars=0; - int nclasses=0; - int i=0; - int i_=0; -//--- creating arrays - double buf[]; - double workx[]; - double y[]; - double dy[]; -//--- initialization - relcls=0; - avgce=0; - rms=0; - avg=0; - avgrel=0; -//--- check - if(!CAp::Assert((int)MathRound(lm.m_w[1])==m_logitvnum,__FUNCTION__+": Incorrect MNL version!")) - return; -//--- initialization - nvars=(int)MathRound(lm.m_w[2]); - nclasses=(int)MathRound(lm.m_w[3]); -//--- allocation - ArrayResizeAL(workx,nvars); - ArrayResizeAL(y,nclasses); - ArrayResizeAL(dy,1); -//--- function call - CBdSS::DSErrAllocate(nclasses,buf); - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=nvars-1;i_++) - workx[i_]=xy[i][i_]; - //--- function call - MNLProcess(lm,workx,y); - //--- change value - dy[0]=xy[i][nvars]; - //--- function call - CBdSS::DSErrAccumulate(buf,y,dy); - } -//--- function call - CBdSS::DSErrFinish(buf); -//--- change values - relcls=buf[0]; - avgce=buf[1]; - rms=buf[2]; - avg=buf[3]; - avgrel=buf[4]; - } -//+------------------------------------------------------------------+ -//| The purpose of mcsrch is to find a step which satisfies a | -//| sufficient decrease condition and a curvature condition. | -//| At each stage the subroutine updates an interval of uncertainty | -//| with endpoints stx and sty. The interval of uncertainty is | -//| initially chosen so that it contains a minimizer of the modified | -//| function | -//| f(x+stp*s) - f(x) - ftol*stp*(gradf(x)'s). | -//| If a step is obtained for which the modified function has a | -//| nonpositive function value and nonnegative derivative, then the | -//| interval of uncertainty is chosen so that it contains a minimizer| -//| of f(x+stp*s). | -//| The algorithm is designed to find a step which satisfies the | -//| sufficient decrease condition | -//| f(x+stp*s) .le. f(x) + ftol*stp*(gradf(x)'s), | -//| and the curvature condition | -//| abs(gradf(x+stp*s)'s)) .le. gtol*abs(gradf(x)'s). | -//| If ftol is less than gtol and if, for example, the function is | -//| bounded below, then there is always a step which satisfies both | -//| conditions. If no step can be found which satisfies both | -//| conditions, then the algorithm usually stops when rounding | -//| errors prevent further progress. In this case stp only satisfies | -//| the sufficient decrease condition. | -//| Parameters descriprion | -//| N is a positive integer input variable set to the number of | -//| variables. | -//| X is an array of length n. on input it must contain the base | -//| point for the line search. on output it contains x+stp*s. | -//| F is a variable. on input it must contain the value of f at x. On| -//| output it contains the value of f at x + stp*s. | -//| G is an array of length n. on input it must contain the gradient | -//| of f at x. On output it contains the gradient of f at x + stp*s. | -//| s is an input array of length n which specifies the search | -//| direction. | -//| Stp is a nonnegative variable. on input stp contains an initial| -//| estimate of a satisfactory step. on output stp contains the final| -//| estimate. | -//| Ftol and gtol are nonnegative input variables. termination occurs| -//| when the sufficient decrease condition and the directional | -//| derivative condition are satisfied. | -//| Xtol is a nonnegative input variable. termination occurs when the| -//| relative width of the interval of uncertainty is at most xtol. | -//| Stpmin and stpmax are nonnegative input variables which specify | -//| lower and upper bounds for the step. | -//| Maxfev is a positive integer input variable. termination occurs | -//| when the number of calls to fcn is at least maxfev by the end of | -//| an iteration. | -//| Info is an integer output variable set as follows: | -//| info = 0 improper input parameters. | -//| info = 1 the sufficient decrease condition and the | -//| directional derivative condition hold. | -//| info = 2 relative width of the interval of uncertainty | -//| is at most xtol. | -//| info = 3 number of calls to fcn has reached maxfev. | -//| info = 4 the step is at the lower bound stpmin. | -//| info = 5 the step is at the upper bound stpmax. | -//| info = 6 rounding errors prevent further progress. | -//| there may not be a step which satisfies the | -//| sufficient decrease and curvature conditions. | -//| tolerances may be too small. | -//| Nfev is an integer output variable set to the number of calls to | -//| fcn. | -//| wa is a work array of length n. | -//| argonne national laboratory. minpack project. june 1983 | -//| Jorge J. More', David J. Thuente | -//+------------------------------------------------------------------+ -static void CLogit::MNLMCSrch(const int n,double &x[],double &f,double &g[], - double &s[],double &stp,int &info,int &nfev, - double &wa[],CLogitMCState &state,int &stage) - { -//--- create variables - double v=0; - double p5=0; - double p66=0; - double zero=0; - int i_=0; -//--- init - p5=0.5; - p66=0.66; - state.m_xtrapf=4.0; - zero=0; -//--- Main cycle - while(true) - { - //--- check - if(stage==0) - { - //--- NEXT - stage=2; - continue; - } - //--- check - if(stage==2) - { - state.m_infoc=1; - info=0; - //--- CHECK THE INPUT PARAMETERS FOR ERRORS. - if(n<=0 || stp<=0.0 || m_ftol<0.0 || m_gtol=0.0) - { - stage=0; - return; - } - //--- initialize local variables. - state.m_brackt=false; - state.m_stage1=true; - nfev=0; - state.m_finit=f; - state.m_dgtest=m_ftol*state.m_dginit; - state.m_width=m_stpmax-m_stpmin; - state.m_width1=state.m_width/p5; - for(i_=0;i_<=n-1;i_++) - wa[i_]=x[i_]; - //--- the variables stx,fx,dgx contain the values of the step, - //--- function,and directional derivative at the best step. - //--- the variables sty,fy,dgy contain the value of the step, - //--- function,and derivative at the other endpoint of - //--- the interval of uncertainty. - //--- the variables stp,f,dg contain the values of the step, - //--- function,and derivative at the current step. - state.m_stx=0; - state.m_fx=state.m_finit; - state.m_dgx=state.m_dginit; - state.m_sty=0; - state.m_fy=state.m_finit; - state.m_dgy=state.m_dginit; - //--- NEXT - stage=3; - continue; - } - //--- check - if(stage==3) - { - //--- start of iteration. - //--- set the minimum and maximum steps to correspond - //--- to the present interval of uncertainty. - if(state.m_brackt) - { - //--- check - if(state.m_stxm_stpmax) - stp=m_stpmax; - //--- check - if(stp=state.m_stmax)) || nfev>=m_maxfev-1) || state.m_infoc==0) || (state.m_brackt && state.m_stmax-state.m_stmin<=m_xtol*state.m_stmax)) - stp=state.m_stx; - //--- evaluate the function and gradient at stp - //--- and compute the directional derivative. - for(i_=0;i_<=n-1;i_++) - x[i_]=wa[i_]; - for(i_=0;i_<=n-1;i_++) - x[i_]=x[i_]+stp*s[i_]; - //--- next - stage=4; - return; - } - //--- check - if(stage==4) - { - info=0; - nfev=nfev+1; - v=0.0; - //--- calculation - for(i_=0;i_<=n-1;i_++) - v+=g[i_]*s[i_]; - state.m_dg=v; - state.m_ftest1=state.m_finit+stp*state.m_dgtest; - //--- test for convergence. - if((state.m_brackt && (stp<=state.m_stmin || stp>=state.m_stmax)) || state.m_infoc==0) - info=6; - //--- check - if((stp==m_stpmax &&f<=state.m_ftest1) &&state.m_dg<=state.m_dgtest) - info=5; - //--- check - if(stp==m_stpmin && (f>state.m_ftest1 || state.m_dg>=state.m_dgtest)) - info=4; - //--- check - if(nfev>=m_maxfev) - info=3; - //--- check - if(state.m_brackt && state.m_stmax-state.m_stmin<=m_xtol*state.m_stmax) - info=2; - //--- check - if(f<=state.m_ftest1 && MathAbs(state.m_dg)<=-(m_gtol*state.m_dginit)) - info=1; - //--- check for termination. - if(info!=0) - { - stage=0; - return; - } - //--- in the first stage we seek a step for which the modified - //--- function has a nonpositive value and nonnegative derivative. - if((state.m_stage1 && f<=state.m_ftest1) && state.m_dg>=MathMin(m_ftol,m_gtol)*state.m_dginit) - state.m_stage1=false; - //--- a modified function is used to predict the step only if - //--- we have not obtained a step for which the modified - //--- function has a nonpositive function value and nonnegative - //--- derivative,and if a lower function value has been - //--- obtained but the decrease is not sufficient. - if((state.m_stage1 && f<=state.m_fx) && f>state.m_ftest1) - { - //--- define the modified function and derivative values. - state.m_fm=f-stp*state.m_dgtest; - state.m_fxm=state.m_fx-state.m_stx*state.m_dgtest; - state.m_fym=state.m_fy-state.m_sty*state.m_dgtest; - state.m_dgm=state.m_dg-state.m_dgtest; - state.m_dgxm=state.m_dgx-state.m_dgtest; - state.m_dgym=state.m_dgy-state.m_dgtest; - //--- call cstep to update the interval of uncertainty - //--- and to compute the new step. - MNLMCStep(state.m_stx,state.m_fxm,state.m_dgxm,state.m_sty,state.m_fym,state.m_dgym,stp,state.m_fm,state.m_dgm,state.m_brackt,state.m_stmin,state.m_stmax,state.m_infoc); - //--- reset the function and gradient values for f. - state.m_fx=state.m_fxm+state.m_stx*state.m_dgtest; - state.m_fy=state.m_fym+state.m_sty*state.m_dgtest; - state.m_dgx=state.m_dgxm+state.m_dgtest; - state.m_dgy=state.m_dgym+state.m_dgtest; - } - else - { - //--- call mcstep to update the interval of uncertainty - //--- and to compute the new step. - MNLMCStep(state.m_stx,state.m_fx,state.m_dgx,state.m_sty,state.m_fy,state.m_dgy,stp,f,state.m_dg,state.m_brackt,state.m_stmin,state.m_stmax,state.m_infoc); - } - //--- force a sufficient decrease in the size of the - //--- interval of uncertainty. - if(state.m_brackt) - { - //--- check - if(MathAbs(state.m_sty-state.m_stx)>=p66*state.m_width1) - stp=state.m_stx+p5*(state.m_sty-state.m_stx); - state.m_width1=state.m_width; - state.m_width=MathAbs(state.m_sty-state.m_stx); - } - //--- next. - stage=3; - continue; - } - } - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MNLMCSrch | -//+------------------------------------------------------------------+ -static void CLogit::MNLMCStep(double &stx,double &fx,double &dx,double &sty, - double &fy,double &dy,double &stp,const double fp, - const double dp,bool &brackt,const double stmin, - const double stmax,int &info) - { -//--- create variables - bool bound; - double gamma=0; - double p=0; - double q=0; - double r=0; - double s=0; - double sgnd=0; - double stpc=0; - double stpf=0; - double stpq=0; - double theta=0; -//--- initialization - info=0; -//--- check the input parameters for errors. - if(((brackt && (stp<=MathMin(stx,sty) || stp>=MathMax(stx,sty))) || dx*(stp-stx)>=0.0) || stmaxfx) - { - //--- change value - info=1; - bound=true; - theta=3*(fx-fp)/(stp-stx)+dx+dp; - s=MathMax(MathAbs(theta),MathMax(MathAbs(dx),MathAbs(dp))); - gamma=s*MathSqrt(CMath::Sqr(theta/s)-dx/s*(dp/s)); - //--- check - if(stpstx) - gamma=-gamma; - //--- change values - p=gamma-dp+theta; - q=gamma-dp+gamma+dx; - r=p/q; - stpc=stp+r*(stx-stp); - stpq=stp+dp/(dp-dx)*(stx-stp); - //--- check - if(MathAbs(stpc-stp)>MathAbs(stpq-stp)) - stpf=stpc; - else - stpf=stpq; - brackt=true; - } - else - { - //--- check - if(MathAbs(dp)stx) - gamma=-gamma; - p=gamma-dp+theta; - q=gamma+(dx-dp)+gamma; - r=p/q; - //--- check - if(r<0.0 && gamma!=0.0) - stpc=stp+r*(stx-stp); - else - { - //--- check - if(stp>stx) - stpc=stmax; - else - stpc=stmin; - } - stpq=stp+dp/(dp-dx)*(stx-stp); - //--- check - if(brackt) - { - //--- check - if(MathAbs(stp-stpc)MathAbs(stp-stpq)) - stpf=stpc; - else - stpf=stpq; - } - } - else - { - //--- fourth case. a lower function value,derivatives of the - //--- same sign,and the magnitude of the derivative does - //--- not decrease. if the minimum is not bracketed,the step - //--- is either stpmin or stpmax,else the cubic step is taken. - info=4; - bound=false; - //--- check - if(brackt) - { - //--- change values - theta=3*(fp-fy)/(sty-stp)+dy+dp; - s=MathMax(MathAbs(theta),MathMax(MathAbs(dy),MathAbs(dp))); - gamma=s*MathSqrt(CMath::Sqr(theta/s)-dy/s*(dp/s)); - //--- check - if(stp>sty) - gamma=-gamma; - //--- change values - p=gamma-dp+theta; - q=gamma-dp+gamma+dy; - r=p/q; - stpc=stp+r*(sty-stp); - stpf=stpc; - } - else - { - //--- check - if(stp>stx) - stpf=stmax; - else - stpf=stmin; - } - } - } - } -//--- update the interval of uncertainty. this update does not -//--- depend on the new step or the case analysis above. - if(fp>fx) - { - sty=stp; - fy=fp; - dy=dp; - } - else - { - //--- check - if(sgnd<0.0) - { - sty=stx; - fy=fx; - dy=dx; - } - //--- change values - stx=stp; - fx=fp; - dx=dp; - } -//--- compute the new step and safeguard it. - stpf=MathMin(stmax,stpf); - stpf=MathMax(stmin,stpf); - stp=stpf; -//--- check - if(brackt && bound) - { - //--- check - if(sty>stx) - stp=MathMin(stx+0.66*(sty-stx),stp); - else - stp=MathMax(stx+0.66*(sty-stx),stp); - } - } -//+------------------------------------------------------------------+ -//| This structure is a MCPD (Markov Chains for Population Data) | -//| solver. You should use ALGLIB functions in order to work with | -//| this object. | -//+------------------------------------------------------------------+ -class CMCPDState - { -public: - //--- variables - int m_n; - int m_npairs; - int m_ccnt; - double m_regterm; - int m_repinneriterationscount; - int m_repouteriterationscount; - int m_repnfev; - int m_repterminationtype; - CMinBLEICState m_bs; - CMinBLEICReport m_br; - //--- arrays - int m_states[]; - int m_ct[]; - double m_pw[]; - double m_tmpp[]; - double m_effectivew[]; - double m_effectivebndl[]; - double m_effectivebndu[]; - int m_effectivect[]; - double m_h[]; - //--- matrices - CMatrixDouble m_data; - CMatrixDouble m_ec; - CMatrixDouble m_bndl; - CMatrixDouble m_bndu; - CMatrixDouble m_c; - CMatrixDouble m_priorp; - CMatrixDouble m_effectivec; - CMatrixDouble m_p; - //--- constructor, destructor - CMCPDState(void); - ~CMCPDState(void); - //--- copy - void Copy(CMCPDState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMCPDState::CMCPDState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMCPDState::~CMCPDState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMCPDState::Copy(CMCPDState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_npairs=obj.m_npairs; - m_ccnt=obj.m_ccnt; - m_regterm=obj.m_regterm; - m_repinneriterationscount=obj.m_repinneriterationscount; - m_repouteriterationscount=obj.m_repouteriterationscount; - m_repnfev=obj.m_repnfev; - m_repterminationtype=obj.m_repterminationtype; - m_bs.Copy(obj.m_bs); - m_br.Copy(obj.m_br); -//--- copy arrays - ArrayCopy(m_states,obj.m_states); - ArrayCopy(m_ct,obj.m_ct); - ArrayCopy(m_pw,obj.m_pw); - ArrayCopy(m_tmpp,obj.m_tmpp); - ArrayCopy(m_effectivew,obj.m_effectivew); - ArrayCopy(m_effectivebndl,obj.m_effectivebndl); - ArrayCopy(m_effectivebndu,obj.m_effectivebndu); - ArrayCopy(m_effectivect,obj.m_effectivect); - ArrayCopy(m_h,obj.m_h); -//--- copy matrices - m_data=obj.m_data; - m_ec=obj.m_ec; - m_bndl=obj.m_bndl; - m_bndu=obj.m_bndu; - m_c=obj.m_c; - m_priorp=obj.m_priorp; - m_effectivec=obj.m_effectivec; - m_p=obj.m_p; - } -//+------------------------------------------------------------------+ -//| This structure is a MCPD (Markov Chains for Population Data) | -//| solver. | -//| You should use ALGLIB functions in order to work with this object| -//+------------------------------------------------------------------+ -class CMCPDStateShell - { -private: - CMCPDState m_innerobj; -public: - //--- constructors, destructor - CMCPDStateShell(void); - CMCPDStateShell(CMCPDState &obj); - ~CMCPDStateShell(void); - //--- method - CMCPDState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMCPDStateShell::CMCPDStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMCPDStateShell::CMCPDStateShell(CMCPDState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMCPDStateShell::~CMCPDStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMCPDState *CMCPDStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| This structure is a MCPD training report: | -//| InnerIterationsCount - number of inner iterations of the| -//| underlying optimization algorithm| -//| OuterIterationsCount - number of outer iterations of the| -//| underlying optimization algorithm| -//| NFEV - number of merit function | -//| evaluations | -//| TerminationType - termination type | -//| (same as for MinBLEIC optimizer, | -//| positive values denote success, | -//| negative ones - failure) | -//+------------------------------------------------------------------+ -class CMCPDReport - { -public: - //--- variables - int m_inneriterationscount; - int m_outeriterationscount; - int m_nfev; - int m_terminationtype; - //--- constructor, destructor - CMCPDReport(void); - ~CMCPDReport(void); - //--- copy - void Copy(CMCPDReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMCPDReport::CMCPDReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMCPDReport::~CMCPDReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMCPDReport::Copy(CMCPDReport &obj) - { -//--- copy variables - m_inneriterationscount=obj.m_inneriterationscount; - m_outeriterationscount=obj.m_outeriterationscount; - m_nfev=obj.m_nfev; - m_terminationtype=obj.m_terminationtype; - } -//+------------------------------------------------------------------+ -//| This structure is a MCPD training report: | -//| InnerIterationsCount - number of inner iterations of the| -//| underlying optimization algorithm| -//| OuterIterationsCount - number of outer iterations of the| -//| underlying optimization algorithm| -//| NFEV - number of merit function | -//| evaluations | -//| TerminationType - termination type | -//| (same as for MinBLEIC optimizer, | -//| positive values denote success, | -//| negative ones - failure) | -//+------------------------------------------------------------------+ -class CMCPDReportShell - { -private: - CMCPDReport m_innerobj; -public: - //--- constructors, destructor - CMCPDReportShell(void); - CMCPDReportShell(CMCPDReport &obj); - ~CMCPDReportShell(void); - //--- methods - int GetInnerIterationsCount(void); - void SetInnerIterationsCount(const int i); - int GetOuterIterationsCount(void); - void SetOuterIterationsCount(const int i); - int GetNFev(void); - void SetNFev(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - CMCPDReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMCPDReportShell::CMCPDReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMCPDReportShell::CMCPDReportShell(CMCPDReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMCPDReportShell::~CMCPDReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -int CMCPDReportShell::GetInnerIterationsCount(void) - { -//--- return result - return(m_innerobj.m_inneriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -void CMCPDReportShell::SetInnerIterationsCount(const int i) - { -//--- change value - m_innerobj.m_inneriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -int CMCPDReportShell::GetOuterIterationsCount(void) - { -//--- return result - return(m_innerobj.m_outeriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -void CMCPDReportShell::SetOuterIterationsCount(const int i) - { -//--- change value - m_innerobj.m_outeriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfev | -//+------------------------------------------------------------------+ -int CMCPDReportShell::GetNFev(void) - { -//--- return result - return(m_innerobj.m_nfev); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfev | -//+------------------------------------------------------------------+ -void CMCPDReportShell::SetNFev(const int i) - { -//--- change value - m_innerobj.m_nfev=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMCPDReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMCPDReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMCPDReport *CMCPDReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Markov chains class | -//+------------------------------------------------------------------+ -class CMarkovCPD - { -private: - //--- private method - static void MCPDInit(const int n,const int entrystate,const int exitstate,CMCPDState &s); -public: - //--- constant - static const double m_xtol; - //--- constructor, destructor - CMarkovCPD(void); - ~CMarkovCPD(void); - //--- public methods - static void MCPDCreate(const int n,CMCPDState &s); - static void MCPDCreateEntry(const int n,const int entrystate,CMCPDState &s); - static void MCPDCreateExit(const int n,const int exitstate,CMCPDState &s); - static void MCPDCreateEntryExit(const int n,const int entrystate,const int exitstate,CMCPDState &s); - static void MCPDAddTrack(CMCPDState &s,CMatrixDouble &xy,const int k); - static void MCPDSetEC(CMCPDState &s,CMatrixDouble &ec); - static void MCPDAddEC(CMCPDState &s,const int i,const int j,const double c); - static void MCPDSetBC(CMCPDState &s,CMatrixDouble &bndl,CMatrixDouble &bndu); - static void MCPDAddBC(CMCPDState &s,const int i,const int j,double bndl,double bndu); - static void MCPDSetLC(CMCPDState &s,CMatrixDouble &c,int &ct[],const int k); - static void MCPDSetTikhonovRegularizer(CMCPDState &s,const double v); - static void MCPDSetPrior(CMCPDState &s,CMatrixDouble &cpp); - static void MCPDSetPredictionWeights(CMCPDState &s,double &pw[]); - static void MCPDSolve(CMCPDState &s); - static void MCPDResults(CMCPDState &s,CMatrixDouble &p,CMCPDReport &rep); - }; -//+------------------------------------------------------------------+ -//| Initialize constant | -//+------------------------------------------------------------------+ -const double CMarkovCPD::m_xtol=1.0E-8; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMarkovCPD::CMarkovCPD(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMarkovCPD::~CMarkovCPD(void) - { - - } -//+------------------------------------------------------------------+ -//| DESCRIPTION: | -//| This function creates MCPD (Markov Chains for Population Data) | -//| solver. | -//| This solver can be used to find transition matrix P for | -//| N-dimensional prediction problem where transition from X[i] to | -//| X[i+1] is modelled as X[i+1] = P*X[i] | -//| where X[i] and X[i+1] are N-dimensional population vectors | -//| (components of each X are non-negative), and P is a N*N | -//| transition matrix (elements of are non-negative, each column | -//| sums to 1.0). | -//| Such models arise when when: | -//| * there is some population of individuals | -//| * individuals can have different states | -//| * individuals can transit from one state to another | -//| * population size is constant, i.e. there is no new individuals | -//| and no one leaves population | -//| * you want to model transitions of individuals from one state | -//| into another | -//| USAGE: | -//| Here we give very brief outline of the MCPD. We strongly | -//| recommend you to read examples in the ALGLIB Reference Manual | -//| and to read ALGLIB User Guide on data analysis which is | -//| available at http://www.alglib.net/dataanalysis/ | -//| 1. User initializes algorithm state with MCPDCreate() call | -//| 2. User adds one or more tracks - sequences of states which | -//| describe evolution of a system being modelled from different | -//| starting conditions | -//| 3. User may add optional boundary, equality and/or linear | -//| constraints on the coefficients of P by calling one of the | -//| following functions: | -//| * MCPDSetEC() to set equality constraints | -//| * MCPDSetBC() to set bound constraints | -//| * MCPDSetLC() to set linear constraints | -//| 4. Optionally, user may set custom weights for prediction errors | -//| (by default, algorithm assigns non-equal, automatically chosen| -//| weights for errors in the prediction of different components | -//| of X). It can be done with a call of | -//| MCPDSetPredictionWeights() function. | -//| 5. User calls MCPDSolve() function which takes algorithm state | -//| and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 6. User calls MCPDResults() to get solution | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>=1 | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDCreate(const int n,CMCPDState &s) - { -//--- check - if(!CAp::Assert(n>=1,"MCPDCreate: N<1")) - return; -//--- function call - MCPDInit(n,-1,-1,s); - } -//+------------------------------------------------------------------+ -//| DESCRIPTION: | -//| This function is a specialized version of MCPDCreate() function, | -//| and we recommend you to read comments for this function for | -//| general information about MCPD solver. | -//| This function creates MCPD (Markov Chains for Population Data) | -//| solver for "Entry-state" model, i.e. model where transition from | -//| X[i] to X[i+1] is modelled as | -//| X[i+1] = P*X[i] | -//| where | -//| X[i] and X[i+1] are N-dimensional state vectors | -//| P is a N*N transition matrix | -//| and one selected component of X[] is called "entry" state and | -//| is treated in a special way: | -//| system state always transits from "entry" state to some | -//| another state | -//| system state can not transit from any state into "entry" | -//| state | -//| Such conditions basically mean that row of P which corresponds to| -//| "entry" state is zero. | -//| Such models arise when: | -//| * there is some population of individuals | -//| * individuals can have different states | -//| * individuals can transit from one state to another | -//| * population size is NOT constant - at every moment of time | -//| there is some (unpredictable) amount of "new" individuals, | -//| which can transit into one of the states at the next turn, but | -//| still no one leaves population | -//| * you want to model transitions of individuals from one state | -//| into another | -//| * but you do NOT want to predict amount of "new" individuals | -//| because it does not depends on individuals already present | -//| (hence system can not transit INTO entry state - it can only | -//| transit FROM it). | -//| This model is discussed in more details in the ALGLIB User Guide | -//| (see http://www.alglib.net/dataanalysis/ for more data). | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>=2 | -//| EntryState- index of entry state, in 0..N-1 | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDCreateEntry(const int n,const int entrystate, - CMCPDState &s) - { -//--- check - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2")) - return; -//--- check - if(!CAp::Assert(entrystate>=0,__FUNCTION__+": EntryState<0")) - return; -//--- check - if(!CAp::Assert(entrystate=N")) - return; -//--- function call - MCPDInit(n,entrystate,-1,s); - } -//+------------------------------------------------------------------+ -//| DESCRIPTION: | -//| This function is a specialized version of MCPDCreate() function, | -//| and we recommend you to read comments for this function for | -//| general information about MCPD solver. | -//| This function creates MCPD (Markov Chains for Population Data) | -//| solver for "Exit-state" model, i.e. model where transition from | -//| X[i] to X[i+1] is modelled as | -//| X[i+1] = P*X[i] | -//| where | -//| X[i] and X[i+1] are N-dimensional state vectors | -//| P is a N*N transition matrix | -//| and one selected component of X[] is called "exit" state and | -//| is treated in a special way: | -//| system state can transit from any state into "exit" state | -//| system state can not transit from "exit" state into any other| -//| state transition operator discards "exit" state (makes it | -//| zero at each turn) | -//| Such conditions basically mean that column of P which | -//| corresponds to "exit" state is zero. Multiplication by such P | -//| may decrease sum of vector components. | -//| Such models arise when: | -//| * there is some population of individuals | -//| * individuals can have different states | -//| * individuals can transit from one state to another | -//| * population size is NOT constant - individuals can move into | -//| "exit" state and leave population at the next turn, but there | -//| are no new individuals | -//| * amount of individuals which leave population can be predicted | -//| * you want to model transitions of individuals from one state | -//| into another (including transitions into the "exit" state) | -//| This model is discussed in more details in the ALGLIB User Guide | -//| (see http://www.alglib.net/dataanalysis/ for more data). | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>=2 | -//| ExitState- index of exit state, in 0..N-1 | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDCreateExit(const int n,const int exitstate, - CMCPDState &s) - { -//--- check - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2")) - return; -//--- check - if(!CAp::Assert(exitstate>=0,__FUNCTION__+": ExitState<0")) - return; -//--- check - if(!CAp::Assert(exitstate=N")) - return; -//--- function call - MCPDInit(n,-1,exitstate,s); - } -//+------------------------------------------------------------------+ -//| DESCRIPTION: | -//| This function is a specialized version of MCPDCreate() function, | -//| and we recommend you to read comments for this function for | -//| general information about MCPD solver. | -//| This function creates MCPD (Markov Chains for Population Data) | -//| solver for "Entry-Exit-states" model, i.e. model where transition| -//| from X[i] to X[i+1] is modelled as | -//| X[i+1] = P*X[i] | -//| where | -//| X[i] and X[i+1] are N-dimensional state vectors | -//| P is a N*N transition matrix | -//| one selected component of X[] is called "entry" state and is a | -//| treated in special way: | -//| system state always transits from "entry" state to some | -//| another state | -//| system state can not transit from any state into "entry" | -//| state | -//| and another one component of X[] is called "exit" state and is | -//| treated in a special way too: | -//| system state can transit from any state into "exit" state | -//| system state can not transit from "exit" state into any other| -//| state transition operator discards "exit" state (makes it | -//| zero at each turn) | -//| Such conditions basically mean that: | -//| row of P which corresponds to "entry" state is zero | -//| column of P which corresponds to "exit" state is zero | -//| Multiplication by such P may decrease sum of vector components. | -//| Such models arise when: | -//| * there is some population of individuals | -//| * individuals can have different states | -//| * individuals can transit from one state to another | -//| * population size is NOT constant | -//| * at every moment of time there is some (unpredictable) amount | -//| of "new" individuals, which can transit into one of the states | -//| at the next turn | -//| * some individuals can move (predictably) into "exit" state | -//| and leave population at the next turn | -//| * you want to model transitions of individuals from one state | -//| into another, including transitions from the "entry" state and | -//| into the "exit" state. | -//| * but you do NOT want to predict amount of "new" individuals | -//| because it does not depends on individuals already present | -//| (hence system can not transit INTO entry state - it can only | -//| transit FROM it). | -//| This model is discussed in more details in the ALGLIB User | -//| Guide (see http://www.alglib.net/dataanalysis/ for more data). | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>=2 | -//| EntryState- index of entry state, in 0..N-1 | -//| ExitState- index of exit state, in 0..N-1 | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDCreateEntryExit(const int n,const int entrystate, - const int exitstate,CMCPDState &s) - { -//--- check - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2")) - return; -//--- check - if(!CAp::Assert(entrystate>=0,__FUNCTION__+": EntryState<0")) - return; -//--- check - if(!CAp::Assert(entrystate=N")) - return; -//--- check - if(!CAp::Assert(exitstate>=0,__FUNCTION__+": ExitState<0")) - return; -//--- check - if(!CAp::Assert(exitstate=N")) - return; -//--- check - if(!CAp::Assert(entrystate!=exitstate,__FUNCTION__+": EntryState=ExitState")) - return; -//--- function call - MCPDInit(n,entrystate,exitstate,s); - } -//+------------------------------------------------------------------+ -//| This function is used to add a track - sequence of system states | -//| at the different moments of its evolution. | -//| You may add one or several tracks to the MCPD solver. In case you| -//| have several tracks, they won't overwrite each other. For | -//| example, if you pass two tracks, A1-A2-A3 (system at t=A+1, t=A+2| -//| and t=A+3) and B1-B2-B3, then solver will try to model | -//| transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, t=B+1 to t=B+2, | -//| t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it wont | -//| try to model transition from t=A+3 to t=B+1. | -//| INPUT PARAMETERS: | -//| S - solver | -//| XY - track, array[K,N]: | -//| * I-th row is a state at t=I | -//| * elements of XY must be non-negative (exception | -//| will be thrown on negative elements) | -//| K - number of points in a track | -//| * if given, only leading K rows of XY are used | -//| * if not given, automatically determined from | -//| size of XY | -//| NOTES: | -//| 1. Track may contain either proportional or population data: | -//| * with proportional data all rows of XY must sum to 1.0, i.e. | -//| we have proportions instead of absolute population values | -//| * with population data rows of XY contain population counts | -//| and generally do not sum to 1.0 (although they still must be| -//| non-negative) | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDAddTrack(CMCPDState &s,CMatrixDouble &xy, - const int k) - { -//--- create variables - int i=0; - int j=0; - int n=0; - double s0=0; - double s1=0; -//--- initialization - n=s.m_n; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(xy)>=n,__FUNCTION__+": Cols(XY)=k,__FUNCTION__+": Rows(XY)=0.0,__FUNCTION__+": XY contains negative elements")) - return; - } - } -//--- check - if(k<2) - return; -//--- check - if(CAp::Rows(s.m_data)=0) - s0=s0+xy[i][j]; - //--- check - if(s.m_states[j]<=0) - s1=s1+xy[i+1][j]; - } - //--- check - if(s0>0.0 && s1>0.0) - { - for(j=0;j<=n-1;j++) - { - //--- check - if(s.m_states[j]>=0) - s.m_data[s.m_npairs].Set(j,xy[i][j]/s0); - else - s.m_data[s.m_npairs].Set(j,0.0); - //--- check - if(s.m_states[j]<=0) - s.m_data[s.m_npairs].Set(n+j,xy[i+1][j]/s1); - else - s.m_data[s.m_npairs].Set(n+j,0.0); - } - //--- change value - s.m_npairs=s.m_npairs+1; - } - } - } -//+------------------------------------------------------------------+ -//| This function is used to add equality constraints on the elements| -//| of the transition matrix P. | -//| MCPD solver has four types of constraints which can be placed | -//| on P: | -//| * user-specified equality constraints (optional) | -//| * user-specified bound constraints (optional) | -//| * user-specified general linear constraints (optional) | -//| * basic constraints (always present): | -//| * non-negativity: P[i,j]>=0 | -//| * consistency: every column of P sums to 1.0 | -//| Final constraints which are passed to the underlying optimizer | -//| are calculated as intersection of all present constraints. For | -//| example, you may specify boundary constraint on P[0,0] and | -//| equality one: | -//| 0.1<=P[0,0]<=0.9 | -//| P[0,0]=0.5 | -//| Such combination of constraints will be silently reduced to their| -//| intersection, which is P[0,0]=0.5. | -//| This function can be used to place equality constraints on | -//| arbitrary subset of elements of P. Set of constraints is | -//| specified by EC, which may contain either NAN's or finite numbers| -//| from [0,1]. NAN denotes absence of constraint, finite number | -//| denotes equality constraint on specific element of P. | -//| You can also use MCPDAddEC() function which allows to ADD | -//| equality constraint for one element of P without changing | -//| constraints for other elements. | -//| These functions (MCPDSetEC and MCPDAddEC) interact as follows: | -//| * there is internal matrix of equality constraints which is | -//| stored in the MCPD solver | -//| * MCPDSetEC() replaces this matrix by another one (SET) | -//| * MCPDAddEC() modifies one element of this matrix and leaves | -//| other ones unchanged (ADD) | -//| * thus MCPDAddEC() call preserves all modifications done by | -//| previous calls, while MCPDSetEC() completely discards all | -//| changes done to the equality constraints. | -//| INPUT PARAMETERS: | -//| S - solver | -//| EC - equality constraints, array[N,N]. Elements of EC | -//| can be either NAN's or finite numbers from [0,1].| -//| NAN denotes absence of constraints, while finite | -//| value denotes equality constraint on the | -//| corresponding element of P. | -//| NOTES: | -//| 1. infinite values of EC will lead to exception being thrown. | -//| Values less than 0.0 or greater than 1.0 will lead to error code | -//| being returned after call to MCPDSolve(). | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDSetEC(CMCPDState &s,CMatrixDouble &ec) - { -//--- create variables - int i=0; - int j=0; - int n=0; -//--- initialization - n=s.m_n; -//--- check - if(!CAp::Assert(CAp::Cols(ec)>=n,__FUNCTION__+": Cols(EC)=n,__FUNCTION__+": Rows(EC)=0 | -//| * consistency: every column of P sums to 1.0 | -//| Final constraints which are passed to the underlying optimizer | -//| are calculated as intersection of all present constraints. For | -//| example, you may specify boundary constraint on P[0,0] and | -//| equality one: | -//| 0.1<=P[0,0]<=0.9 | -//| P[0,0]=0.5 | -//| Such combination of constraints will be silently reduced to their| -//| intersection, which is P[0,0]=0.5. | -//| This function can be used to ADD equality constraint for one | -//| element of P without changing constraints for other elements. | -//| You can also use MCPDSetEC() function which allows you to specify| -//| arbitrary set of equality constraints in one call. | -//| These functions (MCPDSetEC and MCPDAddEC) interact as follows: | -//| * there is internal matrix of equality constraints which is | -//| stored in the MCPD solver | -//| * MCPDSetEC() replaces this matrix by another one (SET) | -//| * MCPDAddEC() modifies one element of this matrix and leaves | -//| other ones unchanged (ADD) | -//| * thus MCPDAddEC() call preserves all modifications done by | -//| previous calls, while MCPDSetEC() completely discards all | -//| changes done to the equality constraints. | -//| INPUT PARAMETERS: | -//| S - solver | -//| I - row index of element being constrained | -//| J - column index of element being constrained | -//| C - value (constraint for P[I,J]). Can be either NAN | -//| (no constraint) or finite value from [0,1]. | -//| NOTES: | -//| 1. infinite values of C will lead to exception being thrown. | -//| Values less than 0.0 or greater than 1.0 will lead to error code | -//| being returned after call to MCPDSolve(). | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDAddEC(CMCPDState &s,const int i,const int j, - const double c) - { -//--- check - if(!CAp::Assert(i>=0,__FUNCTION__+": I<0")) - return; -//--- check - if(!CAp::Assert(i=N")) - return; -//--- check - if(!CAp::Assert(j>=0,__FUNCTION__+": J<0")) - return; -//--- check - if(!CAp::Assert(j=N")) - return; -//--- check - if(!CAp::Assert(CInfOrNaN::IsNaN(c) || CMath::IsFinite(c),"MCPDAddEC: C is not finite number or NAN")) - return; - s.m_ec[i].Set(j,c); - } -//+------------------------------------------------------------------+ -//| This function is used to add bound constraints on the elements | -//| of the transition matrix P. | -//| MCPD solver has four types of constraints which can be placed | -//| on P: | -//| * user-specified equality constraints (optional) | -//| * user-specified bound constraints (optional) | -//| * user-specified general linear constraints (optional) | -//| * basic constraints (always present): | -//| * non-negativity: P[i,j]>=0 | -//| * consistency: every column of P sums to 1.0 | -//| Final constraints which are passed to the underlying optimizer | -//| are calculated as intersection of all present constraints. For | -//| example, you may specify boundary constraint on P[0,0] and | -//| equality one: | -//| 0.1<=P[0,0]<=0.9 | -//| P[0,0]=0.5 | -//| Such combination of constraints will be silently reduced to their| -//| intersection, which is P[0,0]=0.5. | -//| This function can be used to place bound constraints on arbitrary| -//| subset of elements of P. Set of constraints is specified by | -//| BndL/BndU matrices, which may contain arbitrary combination of | -//| finite numbers or infinities (like -INF=n,__FUNCTION__+": Cols(BndL)=n,__FUNCTION__+": Rows(BndL)=n,__FUNCTION__+": Cols(BndU)=n,__FUNCTION__+": Rows(BndU)=0 | -//| * consistency: every column of P sums to 1.0 | -//| Final constraints which are passed to the underlying optimizer | -//| are calculated as intersection of all present constraints. For | -//| example, you may specify boundary constraint on P[0,0] and | -//| equality one: | -//| 0.1<=P[0,0]<=0.9 | -//| P[0,0]=0.5 | -//| Such combination of constraints will be silently reduced to their| -//| intersection, which is P[0,0]=0.5. | -//| This function can be used to ADD bound constraint for one element| -//| of P without changing constraints for other elements. | -//| You can also use MCPDSetBC() function which allows to place bound| -//| constraints on arbitrary subset of elements of P. Set of | -//| constraints is specified by BndL/BndU matrices, which may | -//| contain arbitrary combination of finite numbers or infinities | -//| (like -INF=0,__FUNCTION__+": I<0")) - return; -//--- check - if(!CAp::Assert(i=N")) - return; -//--- check - if(!CAp::Assert(j>=0,__FUNCTION__+": J<0")) - return; -//--- check - if(!CAp::Assert(j=N")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(bndl) || CInfOrNaN::IsNegativeInfinity(bndl),"MCPDAddBC: BndL is NAN or +INF")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(bndu) || CInfOrNaN::IsPositiveInfinity(bndu),"MCPDAddBC: BndU is NAN or -INF")) - return; -//--- change values - s.m_bndl[i].Set(j,bndl); - s.m_bndu[i].Set(j,bndu); - } -//+------------------------------------------------------------------+ -//| This function is used to set linear equality/inequality | -//| constraints on the elements of the transition matrix P. | -//| This function can be used to set one or several general linear | -//| constraints on the elements of P. Two types of constraints are | -//| supported: | -//| * equality constraints | -//| * inequality constraints (both less-or-equal and | -//| greater-or-equal) | -//| Coefficients of constraints are specified by matrix C (one of the| -//| parameters). One row of C corresponds to one constraint. | -//| Because transition matrix P has N*N elements, we need N*N columns| -//| to store all coefficients (they are stored row by row), and | -//| one more column to store right part - hence C has N*N+1 columns. | -//| Constraint kind is stored in the CT array. | -//| Thus, I-th linear constraint is | -//| P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + | -//| + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + | -//| + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] | -//| where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" | -//| (CT[i]>0). | -//| Your constraint may involve only some subset of P (less than N*N | -//| elements). | -//| For example it can be something like | -//| P[0,0] + P[0,1] = 0.5 | -//| In this case you still should pass matrix with N*N+1 columns, | -//| but all its elements (except for C[0,0], C[0,1] and C[0,N*N-1]) | -//| will be zero. | -//| INPUT PARAMETERS: | -//| S - solver | -//| C - array[K,N*N+1] - coefficients of constraints | -//| (see above for complete description) | -//| CT - array[K] - constraint types | -//| (see above for complete description) | -//| K - number of equality/inequality constraints, K>=0: | -//| * if given, only leading K elements of C/CT are | -//| used | -//| * if not given, automatically determined from | -//| sizes of C/CT | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDSetLC(CMCPDState &s,CMatrixDouble &c,int &ct[], - const int k) - { -//--- create variables - int i=0; - int j=0; - int n=0; -//--- initialization - n=s.m_n; -//--- check - if(!CAp::Assert(CAp::Cols(c)>=n*n+1,__FUNCTION__+": Cols(C)=k,__FUNCTION__+": Rows(C)=k,__FUNCTION__+": Len(CT)=0.0,__FUNCTION__+": V is less than zero")) - return; -//--- change value - s.m_regterm=v; - } -//+------------------------------------------------------------------+ -//| This function allows to set prior values used for regularization | -//| of your problem. | -//| By default, regularizing term is equal to r*||P-prior_P||^2, | -//| where r is a small non-zero value, P is transition matrix, | -//| prior_P is identity matrix, ||X||^2 is a sum of squared elements | -//| of X. | -//| This function allows you to change prior values prior_P. You can | -//| also change r with MCPDSetTikhonovRegularizer() function. | -//| INPUT PARAMETERS: | -//| S - solver | -//| PP - array[N,N], matrix of prior values: | -//| 1. elements must be real numbers from [0,1] | -//| 2. columns must sum to 1.0. | -//| First property is checked (exception is thrown | -//| otherwise), while second one is not | -//| checked/enforced. | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDSetPrior(CMCPDState &s,CMatrixDouble &cpp) - { -//--- create variables - int i=0; - int j=0; - int n=0; -//--- create copy of matrices - CMatrixDouble pp; - pp=cpp; -//--- initialization - n=s.m_n; -//--- check - if(!CAp::Assert(CAp::Cols(pp)>=n,__FUNCTION__+": Cols(PP)=n,__FUNCTION__+": Rows(PP)=0.0 && pp[i][j]<=1.0,__FUNCTION__+": PP[i][j] is less than 0.0 or greater than 1.0")) - return; - //--- change value - s.m_priorp[i].Set(j,pp[i][j]); - } - } - } -//+------------------------------------------------------------------+ -//| This function is used to change prediction weights | -//| MCPD solver scales prediction errors as follows | -//| Error(P) = ||W*(y-P*x)||^2 | -//| where | -//| x is a system state at time t | -//| y is a system state at time t+1 | -//| P is a transition matrix | -//| W is a diagonal scaling matrix | -//| By default, weights are chosen in order to minimize relative | -//| prediction error instead of absolute one. For example, if one | -//| component of state is about 0.5 in magnitude and another one is | -//| about 0.05, then algorithm will make corresponding weights equal | -//| to 2.0 and 20.0. | -//| INPUT PARAMETERS: | -//| S - solver | -//| PW - array[N], weights: | -//| * must be non-negative values (exception will be | -//| thrown otherwise) | -//| * zero values will be replaced by automatically | -//| chosen values | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDSetPredictionWeights(CMCPDState &s,double &pw[]) - { -//--- create variables - int i=0; - int n=0; -//--- initialization - n=s.m_n; -//--- check - if(!CAp::Assert(CAp::Len(pw)>=n,__FUNCTION__+": Length(PW)=0.0,__FUNCTION__+": PW containts negative elements")) - return; - //--- change value - s.m_pw[i]=pw[i]; - } - } -//+------------------------------------------------------------------+ -//| This function is used to start solution of the MCPD problem. | -//| After return from this function, you can use MCPDResults() to get| -//| solution and completion code. | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDSolve(CMCPDState &s) - { -//--- create variables - int n=0; - int npairs=0; - int ccnt=0; - int i=0; - int j=0; - int k=0; - int k2=0; - double v=0; - double vv=0; - int i_=0; - int i1_=0; -//--- initialization - n=s.m_n; - npairs=s.m_npairs; -//--- init fields of S - s.m_repterminationtype=0; - s.m_repinneriterationscount=0; - s.m_repouteriterationscount=0; - s.m_repnfev=0; - for(k=0;k<=n-1;k++) - { - for(k2=0;k2<=n-1;k2++) - s.m_p[k].Set(k2,CInfOrNaN::NaN()); - } -//--- Generate "effective" weights for prediction and calculate preconditioner - for(i=0;i<=n-1;i++) - { - //--- check - if(s.m_pw[i]==0.0) - { - //--- change values - v=0; - k=0; - for(j=0;j<=npairs-1;j++) - { - //--- check - if(s.m_data[j][n+i]!=0.0) - { - v=v+s.m_data[j][n+i]; - k=k+1; - } - } - //--- check - if(k!=0) - s.m_effectivew[i]=k/v; - else - s.m_effectivew[i]=1.0; - } - else - s.m_effectivew[i]=s.m_pw[i]; - } -//--- calculation - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - s.m_h[i*n+j]=2*s.m_regterm; - } -//--- calculation - for(k=0;k<=npairs-1;k++) - { - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - s.m_h[i*n+j]=s.m_h[i*n+j]+2*CMath::Sqr(s.m_effectivew[i])*CMath::Sqr(s.m_data[k][j]); - } - } -//--- calculation - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - { - //--- check - if(s.m_h[i*n+j]==0.0) - s.m_h[i*n+j]=1; - } - } -//--- Generate "effective" BndL/BndU - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - { - //--- Set default boundary constraints. - //--- Lower bound is always zero,upper bound is calculated - //--- with respect to entry/exit states. - s.m_effectivebndl[i*n+j]=0.0; - //--- check - if(s.m_states[i]>0 || s.m_states[j]<0) - s.m_effectivebndu[i*n+j]=0.0; - else - s.m_effectivebndu[i*n+j]=1.0; - //--- Calculate intersection of the default and user-specified bound constraints. - //--- This code checks consistency of such combination. - if(CMath::IsFinite(s.m_bndl[i][j]) && s.m_bndl[i][j]>s.m_effectivebndl[i*n+j]) - s.m_effectivebndl[i*n+j]=s.m_bndl[i][j]; - //--- check - if(CMath::IsFinite(s.m_bndu[i][j]) && s.m_bndu[i][j]s.m_effectivebndu[i*n+j]) - { - s.m_repterminationtype=-3; - return; - } - //--- Calculate intersection of the effective bound constraints - //--- and user-specified equality constraints. - //--- This code checks consistency of such combination. - if(CMath::IsFinite(s.m_ec[i][j])) - { - //--- check - if(s.m_ec[i][j]s.m_effectivebndu[i*n+j]) - { - s.m_repterminationtype=-3; - return; - } - //--- change values - s.m_effectivebndl[i*n+j]=s.m_ec[i][j]; - s.m_effectivebndu[i*n+j]=s.m_ec[i][j]; - } - } - } -//--- Generate linear constraints: -//--- * "default" sums-to-one constraints (not generated for "exit" states) - CApServ::RMatrixSetLengthAtLeast(s.m_effectivec,s.m_ccnt+n,n*n+1); -//--- function call - CApServ::IVectorSetLengthAtLeast(s.m_effectivect,s.m_ccnt+n); - ccnt=s.m_ccnt; - for(i=0;i<=s.m_ccnt-1;i++) - { - for(j=0;j<=n*n;j++) - s.m_effectivec[i].Set(j,s.m_c[i][j]); - s.m_effectivect[i]=s.m_ct[i]; - } -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- check - if(s.m_states[i]>=0) - { - for(k=0;k<=n*n-1;k++) - s.m_effectivec[ccnt].Set(k,0); - for(k=0;k<=n-1;k++) - s.m_effectivec[ccnt].Set(k*n+i,1); - //--- change values - s.m_effectivec[ccnt].Set(n*n,1.0); - s.m_effectivect[ccnt]=0; - ccnt=ccnt+1; - } - } -//--- create optimizer - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - s.m_tmpp[i*n+j]=1.0/(double)n; - } -//--- function calls - CMinBLEIC::MinBLEICRestartFrom(s.m_bs,s.m_tmpp); - CMinBLEIC::MinBLEICSetBC(s.m_bs,s.m_effectivebndl,s.m_effectivebndu); - CMinBLEIC::MinBLEICSetLC(s.m_bs,s.m_effectivec,s.m_effectivect,ccnt); - CMinBLEIC::MinBLEICSetInnerCond(s.m_bs,0,0,m_xtol); - CMinBLEIC::MinBLEICSetOuterCond(s.m_bs,m_xtol,1.0E-5); - CMinBLEIC::MinBLEICSetPrecDiag(s.m_bs,s.m_h); -//--- solve problem - while(CMinBLEIC::MinBLEICIteration(s.m_bs)) - { - //--- check - if(!CAp::Assert(s.m_bs.m_needfg,__FUNCTION__+": internal error")) - return; - //--- check - if(s.m_bs.m_needfg) - { - //--- Calculate regularization term - s.m_bs.m_f=0.0; - vv=s.m_regterm; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - { - s.m_bs.m_f=s.m_bs.m_f+vv*CMath::Sqr(s.m_bs.m_x[i*n+j]-s.m_priorp[i][j]); - s.m_bs.m_g[i*n+j]=2*vv*(s.m_bs.m_x[i*n+j]-s.m_priorp[i][j]); - } - } - //--- calculate prediction error/gradient for K-th pair - for(k=0;k<=npairs-1;k++) - { - for(i=0;i<=n-1;i++) - { - i1_=(0)-(i*n); - v=0.0; - for(i_=i*n;i_<=i*n+n-1;i_++) - v+=s.m_bs.m_x[i_]*s.m_data[k][i_+i1_]; - vv=s.m_effectivew[i]; - s.m_bs.m_f=s.m_bs.m_f+CMath::Sqr(vv*(v-s.m_data[k][n+i])); - for(j=0;j<=n-1;j++) - { - s.m_bs.m_g[i*n+j]=s.m_bs.m_g[i*n+j]+2*vv*vv*(v-s.m_data[k][n+i])*s.m_data[k][j]; - } - } - } - //--- continue - continue; - } - } -//--- function call - CMinBLEIC::MinBLEICResultsBuf(s.m_bs,s.m_tmpp,s.m_br); - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - s.m_p[i].Set(j,s.m_tmpp[i*n+j]); - } -//--- change values - s.m_repterminationtype=s.m_br.m_terminationtype; - s.m_repinneriterationscount=s.m_br.m_inneriterationscount; - s.m_repouteriterationscount=s.m_br.m_outeriterationscount; - s.m_repnfev=s.m_br.m_nfev; - } -//+------------------------------------------------------------------+ -//| MCPD results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| P - array[N,N], transition matrix | -//| Rep - optimization report. You should check Rep. | -//| TerminationType in order to distinguish successful| -//| termination from unsuccessful one. Speaking short,| -//| positive values denote success, negative ones are | -//| failures. More information about fields of this | -//| structure can befound in the comments on | -//| MCPDReport datatype. | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDResults(CMCPDState &s,CMatrixDouble &p, - CMCPDReport &rep) - { -//--- create variables - int i=0; - int j=0; -//--- allocation - p.Resize(s.m_n,s.m_n); -//--- copy - for(i=0;i<=s.m_n-1;i++) - { - for(j=0;j<=s.m_n-1;j++) - p[i].Set(j,s.m_p[i][j]); - } -//--- change values - rep.m_terminationtype=s.m_repterminationtype; - rep.m_inneriterationscount=s.m_repinneriterationscount; - rep.m_outeriterationscount=s.m_repouteriterationscount; - rep.m_nfev=s.m_repnfev; - } -//+------------------------------------------------------------------+ -//| Internal initialization function | -//+------------------------------------------------------------------+ -static void CMarkovCPD::MCPDInit(const int n,const int entrystate, - const int exitstate,CMCPDState &s) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1")) - return; -//--- initialization - s.m_n=n; -//--- allocation - ArrayResizeAL(s.m_states,n); - for(i=0;i<=n-1;i++) - s.m_states[i]=0; -//--- check - if(entrystate>=0) - s.m_states[entrystate]=1; -//--- check - if(exitstate>=0) - s.m_states[exitstate]=-1; -//--- initialization - s.m_npairs=0; - s.m_regterm=1.0E-8; - s.m_ccnt=0; -//--- allocation - s.m_p.Resize(n,n); - s.m_ec.Resize(n,n); - s.m_bndl.Resize(n,n); - s.m_bndu.Resize(n,n); - ArrayResizeAL(s.m_pw,n); - s.m_priorp.Resize(n,n); - ArrayResizeAL(s.m_tmpp,n*n); - ArrayResizeAL(s.m_effectivew,n); - ArrayResizeAL(s.m_effectivebndl,n*n); - ArrayResizeAL(s.m_effectivebndu,n*n); - ArrayResizeAL(s.m_h,n*n); -//--- change values - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - { - s.m_p[i].Set(j,0.0); - s.m_priorp[i].Set(j,0.0); - s.m_bndl[i].Set(j,CInfOrNaN::NegativeInfinity()); - s.m_bndu[i].Set(j,CInfOrNaN::PositiveInfinity()); - s.m_ec[i].Set(j,CInfOrNaN::NaN()); - } - s.m_pw[i]=0.0; - s.m_priorp[i].Set(i,1.0); - } -//--- allocation - s.m_data.Resize(1,2*n); - for(i=0;i<=2*n-1;i++) - s.m_data[0].Set(i,0.0); - for(i=0;i<=n*n-1;i++) - s.m_tmpp[i]=0.0; -//--- function call - CMinBLEIC::MinBLEICCreate(n*n,s.m_tmpp,s.m_bs); - } -//+------------------------------------------------------------------+ -//| Training report: | -//| * NGrad - number of gradient calculations | -//| * NHess - number of Hessian calculations | -//| * NCholesky - number of Cholesky decompositions | -//+------------------------------------------------------------------+ -class CMLPReport - { -public: - //--- variables - int m_ngrad; - int m_nhess; - int m_ncholesky; - //--- constructor, destructor - CMLPReport(void); - ~CMLPReport(void); - //--- copy - void Copy(CMLPReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPReport::CMLPReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPReport::~CMLPReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMLPReport::Copy(CMLPReport &obj) - { -//--- copy variables - m_ngrad=obj.m_ngrad; - m_nhess=obj.m_nhess; - m_ncholesky=obj.m_ncholesky; - } -//+------------------------------------------------------------------+ -//| Training report: | -//| * NGrad - number of gradient calculations | -//| * NHess - number of Hessian calculations | -//| * NCholesky - number of Cholesky decompositions | -//+------------------------------------------------------------------+ -class CMLPReportShell - { -private: - CMLPReport m_innerobj; -public: - //--- constructors, destructor - CMLPReportShell(void); - CMLPReportShell(CMLPReport &obj); - ~CMLPReportShell(void); - //--- methods - int GetNGrad(void); - void SetNGrad(const int i); - int GetNHess(void); - void SetNHess(const int i); - int GetNCholesky(void); - void SetNCholesky(const int i); - CMLPReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPReportShell::CMLPReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMLPReportShell::CMLPReportShell(CMLPReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPReportShell::~CMLPReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ngrad | -//+------------------------------------------------------------------+ -int CMLPReportShell::GetNGrad(void) - { -//--- return result - return(m_innerobj.m_ngrad); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ngrad | -//+------------------------------------------------------------------+ -void CMLPReportShell::SetNGrad(const int i) - { -//--- change value - m_innerobj.m_ngrad=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nhess | -//+------------------------------------------------------------------+ -int CMLPReportShell::GetNHess(void) - { -//--- return result - return(m_innerobj.m_nhess); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nhess | -//+------------------------------------------------------------------+ -void CMLPReportShell::SetNHess(const int i) - { -//--- change value - m_innerobj.m_nhess=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ncholesky | -//+------------------------------------------------------------------+ -int CMLPReportShell::GetNCholesky(void) - { -//--- return result - return(m_innerobj.m_ncholesky); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ncholesky | -//+------------------------------------------------------------------+ -void CMLPReportShell::SetNCholesky(const int i) - { -//--- change value - m_innerobj.m_ncholesky=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMLPReport *CMLPReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Cross-validation estimates of generalization error | -//+------------------------------------------------------------------+ -class CMLPCVReport - { -public: - //--- variables - double m_relclserror; - double m_avgce; - double m_rmserror; - double m_avgerror; - double m_avgrelerror; - //--- constructor, destructor - CMLPCVReport(void); - ~CMLPCVReport(void); - //--- copy - void Copy(CMLPCVReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPCVReport::CMLPCVReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPCVReport::~CMLPCVReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMLPCVReport::Copy(CMLPCVReport &obj) - { -//--- copy variables - m_relclserror=obj.m_relclserror; - m_avgce=obj.m_avgce; - m_rmserror=obj.m_rmserror; - m_avgerror=obj.m_avgerror; - m_avgrelerror=obj.m_avgrelerror; - } -//+------------------------------------------------------------------+ -//| Cross-validation estimates of generalization error | -//+------------------------------------------------------------------+ -class CMLPCVReportShell - { -private: - CMLPCVReport m_innerobj; -public: - //--- constructors, destructor - CMLPCVReportShell(void); - CMLPCVReportShell(CMLPCVReport &obj); - ~CMLPCVReportShell(void); - //--- methods - double GetRelClsError(void); - void SetRelClsError(const double d); - double GetAvgCE(void); - void SetAvgCE(const double d); - double GetRMSError(void); - void SetRMSError(const double d); - double GetAvgError(void); - void SetAvgError(const double d); - double GetAvgRelError(void); - void SetAvgRelError(const double d); - CMLPCVReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPCVReportShell::CMLPCVReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMLPCVReportShell::CMLPCVReportShell(CMLPCVReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPCVReportShell::~CMLPCVReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable relclserror | -//+------------------------------------------------------------------+ -double CMLPCVReportShell::GetRelClsError(void) - { -//--- return result - return(m_innerobj.m_relclserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable relclserror | -//+------------------------------------------------------------------+ -void CMLPCVReportShell::SetRelClsError(const double d) - { -//--- change value - m_innerobj.m_relclserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgce | -//+------------------------------------------------------------------+ -double CMLPCVReportShell::GetAvgCE(void) - { -//--- return result - return(m_innerobj.m_avgce); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgce | -//+------------------------------------------------------------------+ -void CMLPCVReportShell::SetAvgCE(const double d) - { -//--- change value - m_innerobj.m_avgce=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable rmserror | -//+------------------------------------------------------------------+ -double CMLPCVReportShell::GetRMSError(void) - { -//--- return result - return(m_innerobj.m_rmserror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable rmserror | -//+------------------------------------------------------------------+ -void CMLPCVReportShell::SetRMSError(const double d) - { -//--- change value - m_innerobj.m_rmserror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgerror | -//+------------------------------------------------------------------+ -double CMLPCVReportShell::GetAvgError(void) - { -//--- return result - return(m_innerobj.m_avgerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgerror | -//+------------------------------------------------------------------+ -void CMLPCVReportShell::SetAvgError(const double d) - { -//--- change value - m_innerobj.m_avgerror=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -double CMLPCVReportShell::GetAvgRelError(void) - { -//--- return result - return(m_innerobj.m_avgrelerror); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable avgrelerror | -//+------------------------------------------------------------------+ -void CMLPCVReportShell::SetAvgRelError(const double d) - { -//--- change value - m_innerobj.m_avgrelerror=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMLPCVReport *CMLPCVReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Training neural networks | -//+------------------------------------------------------------------+ -class CMLPTrain - { -private: - //--- private methods - static void MLPKFoldCVGeneral(CMultilayerPerceptron &n,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const int foldscount,const bool lmalgorithm,const double wstep,const int maxits,int &info,CMLPReport &rep,CMLPCVReport &cvrep); - static void MLPKFoldSplit(CMatrixDouble &xy,const int npoints,const int nclasses,const int foldscount,const bool stratifiedsplits,int &folds[]); -public: - //--- constant - static const double m_mindecay; - //--- constructor, destructor - CMLPTrain(void); - ~CMLPTrain(void); - //--- public methods - static void MLPTrainLM(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints,double decay,const int restarts,int &info,CMLPReport &rep); - static void MLPTrainLBFGS(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints,double decay,const int restarts,const double wstep,int maxits,int &info,CMLPReport &rep); - static void MLPTrainES(CMultilayerPerceptron &network,CMatrixDouble &trnxy,const int trnsize,CMatrixDouble &valxy,const int valsize,const double decay,const int restarts,int &info,CMLPReport &rep); - static void MLPKFoldCVLBFGS(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,const int foldscount,int &info,CMLPReport &rep,CMLPCVReport &cvrep); - static void MLPKFoldCVLM(CMultilayerPerceptron &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int foldscount,int &info,CMLPReport &rep,CMLPCVReport &cvrep); - }; -//+------------------------------------------------------------------+ -//| Initialize constant | -//+------------------------------------------------------------------+ -const double CMLPTrain::m_mindecay=0.001; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPTrain::CMLPTrain(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPTrain::~CMLPTrain(void) - { - - } -//+------------------------------------------------------------------+ -//| Neural network training using modified Levenberg-Marquardt with | -//| exact Hessian calculation and regularization. Subroutine trains | -//| neural network with restarts from random positions. Algorithm is | -//| well suited for small | -//| and medium scale problems (hundreds of weights). | -//| INPUT PARAMETERS: | -//| Network - neural network with initialized geometry | -//| XY - training set | -//| NPoints - training set size | -//| Decay - weight decay constant, >=0.001 | -//| Decay term 'Decay*||Weights||^2' is added to | -//| error function. | -//| If you don't know what Decay to choose, use | -//| 0.001. | -//| Restarts - number of restarts from random position, >0. | -//| If you don't know what Restarts to choose, | -//| use 2. | -//| OUTPUT PARAMETERS: | -//| Network - trained neural network. | -//| Info - return code: | -//| * -9, if internal matrix inverse subroutine | -//| failed | -//| * -2, if there is a point with class number | -//| outside of [0..NOut-1]. | -//| * -1, if wrong parameters specified | -//| (NPoints<0, Restarts<1). | -//| * 2, if task has been solved. | -//| Rep - training report | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPTrainLM(CMultilayerPerceptron &network,CMatrixDouble &xy, - const int npoints,double decay,const int restarts, - int &info,CMLPReport &rep) - { -//--- create variables - int nin=0; - int nout=0; - int wcount=0; - double lmm_ftol=0; - double lmsteptol=0; - int i=0; - int k=0; - double v=0; - double e=0; - double enew=0; - double xnorm2=0; - double stepnorm=0; - bool spd; - double nu=0; - double lambdav=0; - double lambdaup=0; - double lambdadown=0; - int pass=0; - double ebest=0; - int invinfo=0; - int solverinfo=0; - int i_=0; -//--- creating arrays - double g[]; - double d[]; - double x[]; - double y[]; - double wbase[]; - double wdir[]; - double wt[]; - double wx[]; - double wbest[]; -//--- create matrix - CMatrixDouble h; - CMatrixDouble hmod; - CMatrixDouble z; -//--- objects of classes - CMinLBFGSReport internalrep; - CMinLBFGSState state; - CMatInvReport invrep; - CDenseSolverReport solverrep; -//--- initialization - info=0; -//--- function call - CMLPBase::MLPProperties(network,nin,nout,wcount); -//--- initialization - lambdaup=10; - lambdadown=0.3; - lmm_ftol=0.001; - lmsteptol=0.001; -//--- Test for inputs - if(npoints<=0 || restarts<1) - { - info=-1; - return; - } -//--- check - if(CMLPBase::MLPIsSoftMax(network)) - { - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][nin])<0 || (int)MathRound(xy[i][nin])>=nout) - { - info=-2; - return; - } - } - } -//--- change values - decay=MathMax(decay,m_mindecay); - info=2; -//--- Initialize data - rep.m_ngrad=0; - rep.m_nhess=0; - rep.m_ncholesky=0; -//--- General case. -//--- Prepare task and network. Allocate space. - CMLPBase::MLPInitPreprocessor(network,xy,npoints); -//--- allocation - ArrayResizeAL(g,wcount); - h.Resize(wcount,wcount); - hmod.Resize(wcount,wcount); - ArrayResizeAL(wbase,wcount); - ArrayResizeAL(wdir,wcount); - ArrayResizeAL(wbest,wcount); - ArrayResizeAL(wt,wcount); - ArrayResizeAL(wx,wcount); -//--- initialization - ebest=CMath::m_maxrealnumber; -//--- Multiple passes - for(pass=1;pass<=restarts;pass++) - { - //--- Initialize weights - CMLPBase::MLPRandomize(network); - //--- First stage of the hybrid algorithm: LBFGS - for(i_=0;i_<=wcount-1;i_++) - wbase[i_]=network.m_weights[i_]; - //--- function calls - CMinLBFGS::MinLBFGSCreate(wcount,(int)(MathMin(wcount,5)),wbase,state); - CMinLBFGS::MinLBFGSSetCond(state,0,0,0,(int)(MathMax(25,wcount))); - while(CMinLBFGS::MinLBFGSIteration(state)) - { - //--- gradient - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=state.m_x[i_]; - //--- function call - CMLPBase::MLPGradBatch(network,xy,npoints,state.m_f,state.m_g); - //--- weight decay - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - state.m_f=state.m_f+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - state.m_g[i_]=state.m_g[i_]+decay*network.m_weights[i_]; - //--- next iteration - rep.m_ngrad=rep.m_ngrad+1; - } - //--- function call - CMinLBFGS::MinLBFGSResults(state,wbase,internalrep); - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=wbase[i_]; - //--- Second stage of the hybrid algorithm: LM - //--- Initialize H with identity matrix, - //--- G with gradient, - //--- E with regularized error. - CMLPBase::MLPHessianBatch(network,xy,npoints,e,g,h); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change values - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - for(k=0;k<=wcount-1;k++) - h[k].Set(k,h[k][k]+decay); - //--- change values - rep.m_nhess=rep.m_nhess+1; - lambdav=0.001; - nu=2; - //--- cycle - while(true) - { - //--- 1. HMod=H+lambda*I - //--- 2. Try to solve (H+Lambda*I)*dx=-g. - //--- Increase lambda if left part is not positive definite. - for(i=0;i<=wcount-1;i++) - { - for(i_=0;i_<=wcount-1;i_++) - hmod[i].Set(i_,h[i][i_]); - hmod[i].Set(i,hmod[i][i]+lambdav); - } - //--- function call - spd=CTrFac::SPDMatrixCholesky(hmod,wcount,true); - rep.m_ncholesky=rep.m_ncholesky+1; - //--- check - if(!spd) - { - lambdav=lambdav*lambdaup*nu; - nu=nu*2; - continue; - } - //--- function call - CDenseSolver::SPDMatrixCholeskySolve(hmod,wcount,true,g,solverinfo,solverrep,wdir); - //--- check - if(solverinfo<0) - { - lambdav=lambdav*lambdaup*nu; - nu=nu*2; - continue; - } - for(i_=0;i_<=wcount-1;i_++) - wdir[i_]=-1*wdir[i_]; - //--- Lambda found. - //--- 1. Save old w in WBase - //--- 1. Test some stopping criterions - //--- 2. If error(w+wdir)>error(w),increase lambda - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=network.m_weights[i_]+wdir[i_]; - xnorm2=0.0; - for(i_=0;i_<=wcount-1;i_++) - xnorm2+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - stepnorm=0.0; - for(i_=0;i_<=wcount-1;i_++) - stepnorm+=wdir[i_]*wdir[i_]; - stepnorm=MathSqrt(stepnorm); - //--- function call - enew=CMLPBase::MLPError(network,xy,npoints)+0.5*decay*xnorm2; - //--- check - if(stepnorme) - { - lambdav=lambdav*lambdaup*nu; - nu=nu*2; - continue; - } - //--- Optimize using inv(cholesky(H)) as preconditioner - CMatInv::RMatrixTrInverse(hmod,wcount,true,false,invinfo,invrep); - //--- check - if(invinfo<=0) - { - //--- if matrix can't be inverted then exit with errors - //--- TODO: make WCount steps in direction suggested by HMod - info=-9; - return; - } - //--- calculation - for(i_=0;i_<=wcount-1;i_++) - wbase[i_]=network.m_weights[i_]; - for(i=0;i<=wcount-1;i++) - wt[i]=0; - //--- function calls - CMinLBFGS::MinLBFGSCreateX(wcount,wcount,wt,1,0.0,state); - CMinLBFGS::MinLBFGSSetCond(state,0,0,0,5); - while(CMinLBFGS::MinLBFGSIteration(state)) - { - //--- gradient - for(i=0;i<=wcount-1;i++) - { - v=0.0; - for(i_=i;i_<=wcount-1;i_++) - v+=state.m_x[i_]*hmod[i][i_]; - network.m_weights[i]=wbase[i]+v; - } - //--- function call - CMLPBase::MLPGradBatch(network,xy,npoints,state.m_f,g); - for(i=0;i<=wcount-1;i++) - state.m_g[i]=0; - for(i=0;i<=wcount-1;i++) - { - v=g[i]; - for(i_=i;i_<=wcount-1;i_++) - state.m_g[i_]=state.m_g[i_]+v*hmod[i][i_]; - } - //--- weight decay - //--- grad(x'*x)=A'*(x0+A*t) - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - state.m_f=state.m_f+0.5*decay*v; - for(i=0;i<=wcount-1;i++) - { - v=decay*network.m_weights[i]; - for(i_=i;i_<=wcount-1;i_++) - state.m_g[i_]=state.m_g[i_]+v*hmod[i][i_]; - } - //--- next iteration - rep.m_ngrad=rep.m_ngrad+1; - } - //--- function call - CMinLBFGS::MinLBFGSResults(state,wt,internalrep); - //--- Accept new position. - //--- Calculate Hessian - for(i=0;i<=wcount-1;i++) - { - v=0.0; - for(i_=i;i_<=wcount-1;i_++) - v+=wt[i_]*hmod[i][i_]; - network.m_weights[i]=wbase[i]+v; - } - //--- function call - CMLPBase::MLPHessianBatch(network,xy,npoints,e,g,h); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=e+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - g[i_]=g[i_]+decay*network.m_weights[i_]; - for(k=0;k<=wcount-1;k++) - h[k].Set(k,h[k][k]+decay); - rep.m_nhess=rep.m_nhess+1; - //--- Update lambda - lambdav=lambdav*lambdadown; - nu=2; - } - //--- update WBest - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=0.5*decay*v+CMLPBase::MLPError(network,xy,npoints); - //--- check - if(e=0.001 | -//| Decay term 'Decay*||Weights||^2' is added to | -//| error function. | -//| If you don't know what Decay to choose, use | -//| 0.001. | -//| Restarts - number of restarts from random position, >0. | -//| If you don't know what Restarts to choose, | -//| use 2. | -//| WStep - stopping criterion. Algorithm stops if step | -//| size is less than WStep. Recommended | -//| value - 0.01. Zero step size means stopping | -//| after MaxIts iterations. | -//| MaxIts - stopping criterion. Algorithm stops after | -//| MaxIts iterations (NOT gradient calculations).| -//| Zero MaxIts means stopping when step is | -//| sufficiently small. | -//| OUTPUT PARAMETERS: | -//| Network - trained neural network. | -//| Info - return code: | -//| * -8, if both WStep=0 and MaxIts=0 | -//| * -2, if there is a point with class number | -//| outside of [0..NOut-1]. | -//| * -1, if wrong parameters specified | -//| (NPoints<0, Restarts<1). | -//| * 2, if task has been solved. | -//| Rep - training report | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPTrainLBFGS(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints, - double decay,const int restarts, - const double wstep,int maxits, - int &info,CMLPReport &rep) - { -//--- create variables - int i=0; - int pass=0; - int nin=0; - int nout=0; - int wcount=0; - double e=0; - double v=0; - double ebest=0; -//--- creating arrays - double w[]; - double wbest[]; -//--- create objects of classes - CMinLBFGSReport internalrep; - CMinLBFGSState state; - int i_=0; -//--- initialization - info=0; -//--- Test inputs,parse flags,read network geometry - if(wstep==0.0 && maxits==0) - { - info=-8; - return; - } -//--- check - if(((npoints<=0 || restarts<1) || wstep<0.0) || maxits<0) - { - info=-1; - return; - } -//--- function call - CMLPBase::MLPProperties(network,nin,nout,wcount); -//--- check - if(CMLPBase::MLPIsSoftMax(network)) - { - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][nin])<0 || (int)MathRound(xy[i][nin])>=nout) - { - info=-2; - return; - } - } - } -//--- change values - decay=MathMax(decay,m_mindecay); - info=2; -//--- Prepare - CMLPBase::MLPInitPreprocessor(network,xy,npoints); -//--- allocation - ArrayResizeAL(w,wcount); - ArrayResizeAL(wbest,wcount); -//--- initialization - ebest=CMath::m_maxrealnumber; -//--- Multiple starts - rep.m_ncholesky=0; - rep.m_nhess=0; - rep.m_ngrad=0; - for(pass=1;pass<=restarts;pass++) - { - //--- Process - CMLPBase::MLPRandomize(network); - for(i_=0;i_<=wcount-1;i_++) - w[i_]=network.m_weights[i_]; - //--- function calls - CMinLBFGS::MinLBFGSCreate(wcount,(int)(MathMin(wcount,10)),w,state); - CMinLBFGS::MinLBFGSSetCond(state,0.0,0.0,wstep,maxits); - while(CMinLBFGS::MinLBFGSIteration(state)) - { - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=state.m_x[i_]; - //--- function call - CMLPBase::MLPGradNBatch(network,xy,npoints,state.m_f,state.m_g); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - state.m_f=state.m_f+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - state.m_g[i_]=state.m_g[i_]+decay*network.m_weights[i_]; - rep.m_ngrad=rep.m_ngrad+1; - } - //--- function call - CMinLBFGS::MinLBFGSResults(state,w,internalrep); - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=w[i_]; - //--- Compare with best - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - //--- change value - e=CMLPBase::MLPErrorN(network,xy,npoints)+0.5*decay*v; - //--- check - if(e=0.001 | -//| Decay term 'Decay*||Weights||^2' is added to | -//| error function. | -//| If you don't know what Decay to choose, use | -//| 0.001. | -//| Restarts - number of restarts from random position, >0. | -//| If you don't know what Restarts to choose, | -//| use 2. | -//| OUTPUT PARAMETERS: | -//| Network - trained neural network. | -//| Info - return code: | -//| * -2, if there is a point with class number | -//| outside of [0..NOut-1]. | -//| * -1, if wrong parameters specified | -//| (NPoints<0, Restarts<1, ...). | -//| * 2, task has been solved, stopping | -//| criterion met - sufficiently small | -//| step size. Not expected (we use EARLY | -//| stopping) but possible and not an error| -//| * 6, task has been solved, stopping | -//| criterion met - increasing of | -//| validation set error. | -//| Rep - training report | -//| NOTE: | -//| Algorithm stops if validation set error increases for a long | -//| enough or step size is small enought (there are task where | -//| validation set may decrease for eternity). In any case solution | -//| returned corresponds to the minimum of validation set error. | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPTrainES(CMultilayerPerceptron &network, - CMatrixDouble &trnxy,const int trnsize, - CMatrixDouble &valxy,const int valsize, - const double decay,const int restarts, - int &info,CMLPReport &rep) - { -//--- create variables - int i=0; - int pass=0; - int nin=0; - int nout=0; - int wcount=0; - double e=0; - double v=0; - double ebest=0; - int itbest=0; - double wstep=0; - int i_=0; -//--- creating arrays - double w[]; - double wbest[]; - double wfinal[]; - double efinal=0; -//--- objects of classes - CMinLBFGSReport internalrep; - CMinLBFGSState state; -//--- initialization - info=0; - wstep=0.001; -//--- Test inputs,parse flags,read network geometry - if(((trnsize<=0 || valsize<=0) || restarts<1) || decay<0.0) - { - info=-1; - return; - } -//--- function call - CMLPBase::MLPProperties(network,nin,nout,wcount); -//--- check - if(CMLPBase::MLPIsSoftMax(network)) - { - for(i=0;i<=trnsize-1;i++) - { - //--- check - if((int)MathRound(trnxy[i][nin])<0 || (int)MathRound(trnxy[i][nin])>=nout) - { - info=-2; - return; - } - } - for(i=0;i<=valsize-1;i++) - { - //--- check - if((int)MathRound(valxy[i][nin])<0 || (int)MathRound(valxy[i][nin])>=nout) - { - info=-2; - return; - } - } - } -//--- change value - info=2; -//--- Prepare - CMLPBase::MLPInitPreprocessor(network,trnxy,trnsize); -//--- allocation - ArrayResizeAL(w,wcount); - ArrayResizeAL(wbest,wcount); - ArrayResizeAL(wfinal,wcount); -//--- initialization - efinal=CMath::m_maxrealnumber; - for(i=0;i<=wcount-1;i++) - wfinal[i]=0; -//--- Multiple starts - rep.m_ncholesky=0; - rep.m_nhess=0; - rep.m_ngrad=0; -//--- calculation - for(pass=1;pass<=restarts;pass++) - { - //--- Process - CMLPBase::MLPRandomize(network); - //--- change values - ebest=CMLPBase::MLPError(network,valxy,valsize); - for(i_=0;i_<=wcount-1;i_++) - wbest[i_]=network.m_weights[i_]; - //--- change values - itbest=0; - for(i_=0;i_<=wcount-1;i_++) - w[i_]=network.m_weights[i_]; - //--- function calls - CMinLBFGS::MinLBFGSCreate(wcount,(int)(MathMin(wcount,10)),w,state); - CMinLBFGS::MinLBFGSSetCond(state,0.0,0.0,wstep,0); - CMinLBFGS::MinLBFGSSetXRep(state,true); - while(CMinLBFGS::MinLBFGSIteration(state)) - { - //--- Calculate gradient - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=state.m_x[i_]; - //--- function call - CMLPBase::MLPGradNBatch(network,trnxy,trnsize,state.m_f,state.m_g); - v=0.0; - for(i_=0;i_<=wcount-1;i_++) - v+=network.m_weights[i_]*network.m_weights[i_]; - state.m_f=state.m_f+0.5*decay*v; - for(i_=0;i_<=wcount-1;i_++) - state.m_g[i_]=state.m_g[i_]+decay*network.m_weights[i_]; - rep.m_ngrad=rep.m_ngrad+1; - //--- Validation set - if(state.m_xupdated) - { - for(i_=0;i_<=wcount-1;i_++) - network.m_weights[i_]=w[i_]; - //--- function call - e=CMLPBase::MLPError(network,valxy,valsize); - //--- check - if(e30 && (double)(internalrep.m_iterationscount)>(double)(1.5*itbest)) - { - info=6; - break; - } - } - } - //--- function call - CMinLBFGS::MinLBFGSResults(state,w,internalrep); - //--- Compare with final answer - if(ebest0. | -//| restarts are counted for each partition | -//| separately, so total number of restarts will | -//| be Restarts*FoldsCount. | -//| WStep - stopping criterion, same as in MLPTrainLBFGS | -//| MaxIts - stopping criterion, same as in MLPTrainLBFGS | -//| FoldsCount - number of folds in k-fold cross-validation, | -//| 2<=FoldsCount<=SSize. | -//| recommended value: 10. | -//| OUTPUT PARAMETERS: | -//| Info - return code, same as in MLPTrainLBFGS | -//| Rep - report, same as in MLPTrainLM/MLPTrainLBFGS | -//| CVRep - generalization error estimates | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPKFoldCVLBFGS(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints, - const double decay,const int restarts, - const double wstep,const int maxits, - const int foldscount,int &info, - CMLPReport &rep,CMLPCVReport &cvrep) - { -//--- initialization - info=0; -//--- function call - MLPKFoldCVGeneral(network,xy,npoints,decay,restarts,foldscount,false,wstep,maxits,info,rep,cvrep); - } -//+------------------------------------------------------------------+ -//| Cross-validation estimate of generalization error. | -//| Base algorithm - Levenberg-Marquardt. | -//| INPUT PARAMETERS: | -//| Network - neural network with initialized geometry. | -//| Network is not changed during | -//| cross-validation - it is used only as a | -//| representative of its architecture. | -//| XY - training set. | -//| SSize - training set size | -//| Decay - weight decay, same as in MLPTrainLBFGS | -//| Restarts - number of restarts, >0. | -//| restarts are counted for each partition | -//| separately, so total number of restarts will | -//| be Restarts*FoldsCount. | -//| FoldsCount - number of folds in k-fold cross-validation, | -//| 2<=FoldsCount<=SSize. | -//| recommended value: 10. | -//| OUTPUT PARAMETERS: | -//| Info - return code, same as in MLPTrainLBFGS | -//| Rep - report, same as in MLPTrainLM/MLPTrainLBFGS | -//| CVRep - generalization error estimates | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPKFoldCVLM(CMultilayerPerceptron &network, - CMatrixDouble &xy,const int npoints, - const double decay,const int restarts, - int foldscount,int &info,CMLPReport &rep, - CMLPCVReport &cvrep) - { -//--- initialization - info=0; -//--- function call - MLPKFoldCVGeneral(network,xy,npoints,decay,restarts,foldscount,true,0.0,0,info,rep,cvrep); - } -//+------------------------------------------------------------------+ -//| Internal cross-validation subroutine | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPKFoldCVGeneral(CMultilayerPerceptron &n, - CMatrixDouble &xy,const int npoints, - const double decay,const int restarts, - const int foldscount,const bool lmalgorithm, - const double wstep,const int maxits, - int &info,CMLPReport &rep, - CMLPCVReport &cvrep) - { -//--- create variables - int i=0; - int fold=0; - int j=0; - int k=0; - int nin=0; - int nout=0; - int rowlen=0; - int wcount=0; - int nclasses=0; - int tssize=0; - int cvssize=0; - int relcnt=0; - int i_=0; -//--- creating arrays - int folds[]; - double x[]; - double y[]; -//--- create matrix - CMatrixDouble cvset; - CMatrixDouble testset; -//--- creating arrays - CMultilayerPerceptron network; - CMLPReport internalrep; -//--- initialization - info=0; -//--- Read network geometry,test parameters - CMLPBase::MLPProperties(n,nin,nout,wcount); -//--- check - if(CMLPBase::MLPIsSoftMax(n)) - { - nclasses=nout; - rowlen=nin+1; - } - else - { - nclasses=-nout; - rowlen=nin+nout; - } -//--- check - if((npoints<=0 || foldscount<2) || foldscount>npoints) - { - info=-1; - return; - } -//--- function call - CMLPBase::MLPCopy(n,network); -//--- K-fold out cross-validation. -//--- First,estimate generalization error - testset.Resize(npoints,rowlen); - cvset.Resize(npoints,rowlen); - ArrayResizeAL(x,nin); - ArrayResizeAL(y,nout); -//--- function call - MLPKFoldSplit(xy,npoints,nclasses,foldscount,false,folds); -//--- change values - cvrep.m_relclserror=0; - cvrep.m_avgce=0; - cvrep.m_rmserror=0; - cvrep.m_avgerror=0; - cvrep.m_avgrelerror=0; - rep.m_ngrad=0; - rep.m_nhess=0; - rep.m_ncholesky=0; - relcnt=0; -//--- calculation - for(fold=0;fold<=foldscount-1;fold++) - { - //--- Separate set - tssize=0; - cvssize=0; - for(i=0;i<=npoints-1;i++) - { - //--- check - if(folds[i]==fold) - { - for(i_=0;i_<=rowlen-1;i_++) - testset[tssize].Set(i_,xy[i][i_]); - tssize=tssize+1; - } - else - { - for(i_=0;i_<=rowlen-1;i_++) - cvset[cvssize].Set(i_,xy[i][i_]); - cvssize=cvssize+1; - } - } - //--- Train on CV training set - if(lmalgorithm) - MLPTrainLM(network,cvset,cvssize,decay,restarts,info,internalrep); - else - MLPTrainLBFGS(network,cvset,cvssize,decay,restarts,wstep,maxits,info,internalrep); - //--- check - if(info<0) - { - //--- change values - cvrep.m_relclserror=0; - cvrep.m_avgce=0; - cvrep.m_rmserror=0; - cvrep.m_avgerror=0; - cvrep.m_avgrelerror=0; - //--- exit the function - return; - } - //--- change values - rep.m_ngrad=rep.m_ngrad+internalrep.m_ngrad; - rep.m_nhess=rep.m_nhess+internalrep.m_nhess; - rep.m_ncholesky=rep.m_ncholesky+internalrep.m_ncholesky; - //--- Estimate error using CV test set - if(CMLPBase::MLPIsSoftMax(network)) - { - //--- classification-only code - cvrep.m_relclserror=cvrep.m_relclserror+CMLPBase::MLPClsError(network,testset,tssize); - cvrep.m_avgce=cvrep.m_avgce+CMLPBase::MLPErrorN(network,testset,tssize); - } - //--- calculation - for(i=0;i<=tssize-1;i++) - { - for(i_=0;i_<=nin-1;i_++) - x[i_]=testset[i][i_]; - //--- function call - CMLPBase::MLPProcess(network,x,y); - //--- check - if(CMLPBase::MLPIsSoftMax(network)) - { - //--- Classification-specific code - k=(int)MathRound(testset[i][nin]); - for(j=0;j<=nout-1;j++) - { - //--- check - if(j==k) - { - //--- change values - cvrep.m_rmserror=cvrep.m_rmserror+CMath::Sqr(y[j]-1); - cvrep.m_avgerror=cvrep.m_avgerror+MathAbs(y[j]-1); - cvrep.m_avgrelerror=cvrep.m_avgrelerror+MathAbs(y[j]-1); - relcnt=relcnt+1; - } - else - { - //--- change values - cvrep.m_rmserror=cvrep.m_rmserror+CMath::Sqr(y[j]); - cvrep.m_avgerror=cvrep.m_avgerror+MathAbs(y[j]); - } - } - } - else - { - //--- Regression-specific code - for(j=0;j<=nout-1;j++) - { - cvrep.m_rmserror=cvrep.m_rmserror+CMath::Sqr(y[j]-testset[i][nin+j]); - cvrep.m_avgerror=cvrep.m_avgerror+MathAbs(y[j]-testset[i][nin+j]); - //--- check - if(testset[i][nin+j]!=0.0) - { - cvrep.m_avgrelerror=cvrep.m_avgrelerror+MathAbs((y[j]-testset[i][nin+j])/testset[i][nin+j]); - relcnt=relcnt+1; - } - } - } - } - } -//--- check - if(CMLPBase::MLPIsSoftMax(network)) - { - cvrep.m_relclserror=cvrep.m_relclserror/npoints; - cvrep.m_avgce=cvrep.m_avgce/(MathLog(2)*npoints); - } -//--- change values - cvrep.m_rmserror=MathSqrt(cvrep.m_rmserror/(npoints*nout)); - cvrep.m_avgerror=cvrep.m_avgerror/(npoints*nout); - cvrep.m_avgrelerror=cvrep.m_avgrelerror/relcnt; - info=1; - } -//+------------------------------------------------------------------+ -//| Subroutine prepares K-fold split of the training set. | -//| NOTES: | -//| "NClasses>0" means that we have classification task. | -//| "NClasses<0" means regression task with -NClasses real | -//| outputs. | -//+------------------------------------------------------------------+ -static void CMLPTrain::MLPKFoldSplit(CMatrixDouble &xy,const int npoints, - const int nclasses,const int foldscount, - const bool stratifiedsplits,int &folds[]) - { -//--- create variables - int i=0; - int j=0; - int k=0; -//--- test parameters - if(!CAp::Assert(npoints>0,__FUNCTION__+": wrong NPoints!")) - return; -//--- check - if(!CAp::Assert(nclasses>1 || nclasses<0,__FUNCTION__+": wrong NClasses!")) - return; -//--- check - if(!CAp::Assert(foldscount>=2 && foldscount<=npoints,__FUNCTION__+" wrong FoldsCount!")) - return; -//--- check - if(!CAp::Assert(!stratifiedsplits,__FUNCTION__+": stratified splits are not supported!")) - return; -//--- Folds - ArrayResizeAL(folds,npoints); - for(i=0;i<=npoints-1;i++) - folds[i]=i*foldscount/npoints; -//--- calculation - for(i=0;i<=npoints-2;i++) - { - j=i+CMath::RandomInteger(npoints-i); - //--- check - if(j!=i) - { - k=folds[i]; - folds[i]=folds[j]; - folds[j]=k; - } - } - } -//+------------------------------------------------------------------+ -//| Neural networks ensemble | -//+------------------------------------------------------------------+ -class CMLPEnsemble - { -public: - //--- variables - int m_ensemblesize; - int m_nin; - int m_nout; - int m_wcount; - bool m_issoftmax; - bool m_postprocessing; - int m_serializedlen; - //--- arrays - int m_structinfo[]; - double m_weights[]; - double m_columnmeans[]; - double m_columnsigmas[]; - double m_serializedmlp[]; - double m_tmpweights[]; - double m_tmpmeans[]; - double m_tmpsigmas[]; - double m_neurons[]; - double m_dfdnet[]; - double m_y[]; - //--- constructor, destructor - CMLPEnsemble(void); - ~CMLPEnsemble(void); - //--- copy - void Copy(CMLPEnsemble &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPEnsemble::CMLPEnsemble(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPEnsemble::~CMLPEnsemble(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMLPEnsemble::Copy(CMLPEnsemble &obj) - { -//--- copy variables - m_ensemblesize=obj.m_ensemblesize; - m_nin=obj.m_nin; - m_nout=obj.m_nout; - m_wcount=obj.m_wcount; - m_issoftmax=obj.m_issoftmax; - m_postprocessing=obj.m_postprocessing; - m_serializedlen=obj.m_serializedlen; -//--- copy arrays - ArrayCopy(m_structinfo,obj.m_structinfo); - ArrayCopy(m_weights,obj.m_weights); - ArrayCopy(m_columnmeans,obj.m_columnmeans); - ArrayCopy(m_columnsigmas,obj.m_columnsigmas); - ArrayCopy(m_serializedmlp,obj.m_serializedmlp); - ArrayCopy(m_tmpweights,obj.m_tmpweights); - ArrayCopy(m_tmpmeans,obj.m_tmpmeans); - ArrayCopy(m_tmpsigmas,obj.m_tmpsigmas); - ArrayCopy(m_neurons,obj.m_neurons); - ArrayCopy(m_dfdnet,obj.m_dfdnet); - ArrayCopy(m_y,obj.m_y); - } -//+------------------------------------------------------------------+ -//| Neural networks ensemble | -//+------------------------------------------------------------------+ -class CMLPEnsembleShell - { -private: - CMLPEnsemble m_innerobj; -public: - //--- constructors, destructor - CMLPEnsembleShell(void); - CMLPEnsembleShell(CMLPEnsemble &obj); - ~CMLPEnsembleShell(void); - //--- method - CMLPEnsemble *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPEnsembleShell::CMLPEnsembleShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMLPEnsembleShell::CMLPEnsembleShell(CMLPEnsemble &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPEnsembleShell::~CMLPEnsembleShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMLPEnsemble *CMLPEnsembleShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Neural networks ensemble | -//+------------------------------------------------------------------+ -class CMLPE - { -private: - //--- private methods - static void MLPEAllErrors(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints,double &relcls,double &avgce,double &rms,double &avg,double &avgrel); - static void MLPEBaggingInternal(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,const bool lmalgorithm,int &info,CMLPReport &rep,CMLPCVReport &ooberrors); -public: - //--- class constants - static const int m_mlpntotaloffset; - static const int m_mlpevnum; - //--- constructor, destructor - CMLPE(void); - ~CMLPE(void); - //--- public methods - static void MLPECreate0(const int nin,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreate1(const int nin,const int nhid,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreate2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateB0(const int nin,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateB1(const int nin,const int nhid,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateR0(const int nin,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateR1(const int nin,const int nhid,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateC0(const int nin,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateC1(const int nin,const int nhid,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateC2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECreateFromNetwork(CMultilayerPerceptron &network,const int ensemblesize,CMLPEnsemble &ensemble); - static void MLPECopy(CMLPEnsemble &ensemble1,CMLPEnsemble &ensemble2); - static void MLPESerialize(CMLPEnsemble &ensemble,double &ra[],int &rlen); - static void MLPEUnserialize(double &ra[],CMLPEnsemble &ensemble); - static void MLPERandomize(CMLPEnsemble &ensemble); - static void MLPEProperties(CMLPEnsemble &ensemble,int &nin,int &nout); - static bool MLPEIsSoftMax(CMLPEnsemble &ensemble); - static void MLPEProcess(CMLPEnsemble &ensemble,double &x[],double &y[]); - static void MLPEProcessI(CMLPEnsemble &ensemble,double &x[],double &y[]); - static double MLPERelClsError(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgCE(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPERMSError(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgError(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints); - static double MLPEAvgRelError(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints); - static void MLPEBaggingLM(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReport &rep,CMLPCVReport &ooberrors); - static void MLPEBaggingLBFGS(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,int &info,CMLPReport &rep,CMLPCVReport &ooberrors); - static void MLPETrainES(CMLPEnsemble &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReport &rep); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CMLPE::m_mlpntotaloffset=3; -const int CMLPE::m_mlpevnum=9; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMLPE::CMLPE(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMLPE::~CMLPE(void) - { - - } -//+------------------------------------------------------------------+ -//| Like MLPCreate0, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreate0(const int nin,const int nout,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreate0(nin,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreate1, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreate1(const int nin,const int nhid,const int nout, - const int ensemblesize,CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreate1(nin,nhid,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreate2, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreate2(const int nin,const int nhid1,const int nhid2, - const int nout,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreate2(nin,nhid1,nhid2,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateB0, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateB0(const int nin,const int nout,const double b, - const double d,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateB0(nin,nout,b,d,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateB1, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateB1(const int nin,const int nhid,const int nout, - const double b,const double d,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateB1(nin,nhid,nout,b,d,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateB2, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateB2(const int nin,const int nhid1,const int nhid2, - const int nout,const double b,const double d, - const int ensemblesize,CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateB2(nin,nhid1,nhid2,nout,b,d,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateR0, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateR0(const int nin,const int nout,const double a, - const double b,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateR0(nin,nout,a,b,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateR1, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateR1(const int nin,const int nhid,const int nout, - const double a,const double b, - const int ensemblesize,CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateR1(nin,nhid,nout,a,b,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateR2, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateR2(const int nin,const int nhid1,const int nhid2, - const int nout,const double a,const double b, - const int ensemblesize,CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateR2(nin,nhid1,nhid2,nout,a,b,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateC0, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateC0(const int nin,const int nout,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateC0(nin,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateC1, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateC1(const int nin,const int nhid,const int nout, - const int ensemblesize,CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateC1(nin,nhid,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Like MLPCreateC2, but for ensembles. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateC2(const int nin,const int nhid1,const int nhid2, - const int nout,const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- object of class - CMultilayerPerceptron net; -//--- function call - CMLPBase::MLPCreateC2(nin,nhid1,nhid2,nout,net); -//--- function call - MLPECreateFromNetwork(net,ensemblesize,ensemble); - } -//+------------------------------------------------------------------+ -//| Creates ensemble from network. Only network geometry is copied. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECreateFromNetwork(CMultilayerPerceptron &network, - const int ensemblesize, - CMLPEnsemble &ensemble) - { -//--- create variables - int i=0; - int ccount=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert(ensemblesize>0,__FUNCTION__+": incorrect ensemble size!")) - return; -//--- network properties - CMLPBase::MLPProperties(network,ensemble.m_nin,ensemble.m_nout,ensemble.m_wcount); -//--- check - if(CMLPBase::MLPIsSoftMax(network)) - ccount=ensemble.m_nin; - else - ccount=ensemble.m_nin+ensemble.m_nout; -//--- change values - ensemble.m_postprocessing=false; - ensemble.m_issoftmax=CMLPBase::MLPIsSoftMax(network); - ensemble.m_ensemblesize=ensemblesize; -//--- structure information - ArrayResizeAL(ensemble.m_structinfo,network.m_structinfo[0]); -//--- copy - for(i=0;i<=network.m_structinfo[0]-1;i++) - ensemble.m_structinfo[i]=network.m_structinfo[i]; -//--- weights,means,sigmas - ArrayResizeAL(ensemble.m_weights,ensemblesize*ensemble.m_wcount); - ArrayResizeAL(ensemble.m_columnmeans,ensemblesize*ccount); - ArrayResizeAL(ensemble.m_columnsigmas,ensemblesize*ccount); -//--- calculation - for(i=0;i<=ensemblesize*ensemble.m_wcount-1;i++) - ensemble.m_weights[i]=CMath::RandomReal()-0.5; -//--- calculation - for(i=0;i<=ensemblesize-1;i++) - { - i1_=-(i*ccount); - for(i_=i*ccount;i_<=(i+1)*ccount-1;i_++) - ensemble.m_columnmeans[i_]=network.m_columnmeans[i_+i1_]; - i1_=-(i*ccount); - for(i_=i*ccount;i_<=(i+1)*ccount-1;i_++) - ensemble.m_columnsigmas[i_]=network.m_columnsigmas[i_+i1_]; - } -//--- serialized part - CMLPBase::MLPSerializeOld(network,ensemble.m_serializedmlp,ensemble.m_serializedlen); -//--- temporaries,internal buffers - ArrayResizeAL(ensemble.m_tmpweights,ensemble.m_wcount); - ArrayResizeAL(ensemble.m_tmpmeans,ccount); - ArrayResizeAL(ensemble.m_tmpsigmas,ccount); - ArrayResizeAL(ensemble.m_neurons,ensemble.m_structinfo[m_mlpntotaloffset]); - ArrayResizeAL(ensemble.m_dfdnet,ensemble.m_structinfo[m_mlpntotaloffset]); - ArrayResizeAL(ensemble.m_y,ensemble.m_nout); - } -//+------------------------------------------------------------------+ -//| Copying of MLPEnsemble strucure | -//| INPUT PARAMETERS: | -//| Ensemble1 - original | -//| OUTPUT PARAMETERS: | -//| Ensemble2 - copy | -//+------------------------------------------------------------------+ -static void CMLPE::MLPECopy(CMLPEnsemble &ensemble1,CMLPEnsemble &ensemble2) - { -//--- create variables - int i=0; - int ssize=0; - int ccount=0; - int ntotal=0; - int i_=0; -//--- Unload info - ssize=ensemble1.m_structinfo[0]; -//--- check - if(ensemble1.m_issoftmax) - ccount=ensemble1.m_nin; - else - ccount=ensemble1.m_nin+ensemble1.m_nout; -//--- change value - ntotal=ensemble1.m_structinfo[m_mlpntotaloffset]; -//--- Allocate space - ArrayResizeAL(ensemble2.m_structinfo,ssize); - ArrayResizeAL(ensemble2.m_weights,ensemble1.m_ensemblesize*ensemble1.m_wcount); - ArrayResizeAL(ensemble2.m_columnmeans,ensemble1.m_ensemblesize*ccount); - ArrayResizeAL(ensemble2.m_columnsigmas,ensemble1.m_ensemblesize*ccount); - ArrayResizeAL(ensemble2.m_tmpweights,ensemble1.m_wcount); - ArrayResizeAL(ensemble2.m_tmpmeans,ccount); - ArrayResizeAL(ensemble2.m_tmpsigmas,ccount); - ArrayResizeAL(ensemble2.m_serializedmlp,ensemble1.m_serializedlen); - ArrayResizeAL(ensemble2.m_neurons,ntotal); - ArrayResizeAL(ensemble2.m_dfdnet,ntotal); - ArrayResizeAL(ensemble2.m_y,ensemble1.m_nout); -//--- Copy - ensemble2.m_nin=ensemble1.m_nin; - ensemble2.m_nout=ensemble1.m_nout; - ensemble2.m_wcount=ensemble1.m_wcount; - ensemble2.m_ensemblesize=ensemble1.m_ensemblesize; - ensemble2.m_issoftmax=ensemble1.m_issoftmax; - ensemble2.m_postprocessing=ensemble1.m_postprocessing; - ensemble2.m_serializedlen=ensemble1.m_serializedlen; -//--- copy - for(i=0;i<=ssize-1;i++) - ensemble2.m_structinfo[i]=ensemble1.m_structinfo[i]; - for(i_=0;i_<=ensemble1.m_ensemblesize*ensemble1.m_wcount-1;i_++) - ensemble2.m_weights[i_]=ensemble1.m_weights[i_]; - for(i_=0;i_<=ensemble1.m_ensemblesize*ccount-1;i_++) - ensemble2.m_columnmeans[i_]=ensemble1.m_columnmeans[i_]; - for(i_=0;i_<=ensemble1.m_ensemblesize*ccount-1;i_++) - ensemble2.m_columnsigmas[i_]=ensemble1.m_columnsigmas[i_]; - for(i_=0;i_<=ensemble1.m_serializedlen-1;i_++) - ensemble2.m_serializedmlp[i_]=ensemble1.m_serializedmlp[i_]; - } -//+------------------------------------------------------------------+ -//| Serialization of MLPEnsemble strucure | -//| INPUT PARAMETERS: | -//| Ensemble- original | -//| OUTPUT PARAMETERS: | -//| RA - array of real numbers which stores ensemble, | -//| array[0..RLen-1] | -//| RLen - RA lenght | -//+------------------------------------------------------------------+ -static void CMLPE::MLPESerialize(CMLPEnsemble &ensemble,double &ra[],int &rlen) - { -//--- create variables - int i=0; - int ssize=0; - int ntotal=0; - int ccount=0; - int hsize=0; - int offs=0; - int i_=0; - int i1_=0; -//--- initialization - rlen=0; - hsize=13; - ssize=ensemble.m_structinfo[0]; -//--- check - if(ensemble.m_issoftmax) - ccount=ensemble.m_nin; - else - ccount=ensemble.m_nin+ensemble.m_nout; -//--- change values - ntotal=ensemble.m_structinfo[m_mlpntotaloffset]; - rlen=hsize+ssize+ensemble.m_ensemblesize*ensemble.m_wcount+2*ccount*ensemble.m_ensemblesize+ensemble.m_serializedlen; -//--- RA format: -//--- [0] RLen -//--- [1] Version (MLPEVNum) -//--- [2] EnsembleSize -//--- [3] NIn -//--- [4] NOut -//--- [5] WCount -//--- [6] IsSoftmax 0/1 -//--- [7] PostProcessing 0/1 -//--- [8] sizeof(StructInfo) -//--- [9] NTotal (sizeof(Neurons),sizeof(DFDNET)) -//--- [10] CCount (sizeof(ColumnMeans),sizeof(ColumnSigmas)) -//--- [11] data offset -//--- [12] SerializedLen -//--- [..] StructInfo -//--- [..] Weights -//--- [..] ColumnMeans -//--- [..] ColumnSigmas - ArrayResizeAL(ra,rlen); -//--- change values - ra[0]=rlen; - ra[1]=m_mlpevnum; - ra[2]=ensemble.m_ensemblesize; - ra[3]=ensemble.m_nin; - ra[4]=ensemble.m_nout; - ra[5]=ensemble.m_wcount; -//--- check - if(ensemble.m_issoftmax) - ra[6]=1; - else - ra[6]=0; -//--- check - if(ensemble.m_postprocessing) - ra[7]=1; - else - ra[7]=9; -//--- change values - ra[8]=ssize; - ra[9]=ntotal; - ra[10]=ccount; - ra[11]=hsize; - ra[12]=ensemble.m_serializedlen; -//--- copy - offs=hsize; - for(i=offs;i<=offs+ssize-1;i++) - ra[i]=ensemble.m_structinfo[i-offs]; -//--- copy - offs=offs+ssize; - i1_=-offs; - for(i_=offs;i_<=offs+ensemble.m_ensemblesize*ensemble.m_wcount-1;i_++) - ra[i_]=ensemble.m_weights[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ensemble.m_wcount; - i1_=-offs; - for(i_=offs;i_<=offs+ensemble.m_ensemblesize*ccount-1;i_++) - ra[i_]=ensemble.m_columnmeans[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ccount; - i1_=-offs; - for(i_=offs;i_<=offs+ensemble.m_ensemblesize*ccount-1;i_++) - ra[i_]=ensemble.m_columnsigmas[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ccount; - i1_=-offs; - for(i_=offs;i_<=offs+ensemble.m_serializedlen-1;i_++) - ra[i_]=ensemble.m_serializedmlp[i_+i1_]; - offs=offs+ensemble.m_serializedlen; - } -//+------------------------------------------------------------------+ -//| Unserialization of MLPEnsemble strucure | -//| INPUT PARAMETERS: | -//| RA - real array which stores ensemble | -//| OUTPUT PARAMETERS: | -//| Ensemble- restored structure | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEUnserialize(double &ra[],CMLPEnsemble &ensemble) - { -//--- create variables - int i=0; - int ssize=0; - int ntotal=0; - int ccount=0; - int hsize=0; - int offs=0; - int i_=0; - int i1_=0; -//--- check - if(!CAp::Assert((int)MathRound(ra[1])==m_mlpevnum,__FUNCTION__+": incorrect array!")) - return; -//--- load info - hsize=13; - ensemble.m_ensemblesize=(int)MathRound(ra[2]); - ensemble.m_nin=(int)MathRound(ra[3]); - ensemble.m_nout=(int)MathRound(ra[4]); - ensemble.m_wcount=(int)MathRound(ra[5]); - ensemble.m_issoftmax=(int)MathRound(ra[6])==1; - ensemble.m_postprocessing=(int)MathRound(ra[7])==1; - ssize=(int)MathRound(ra[8]); - ntotal=(int)MathRound(ra[9]); - ccount=(int)MathRound(ra[10]); - offs=(int)MathRound(ra[11]); - ensemble.m_serializedlen=(int)MathRound(ra[12]); -//--- Allocate arrays - ArrayResizeAL(ensemble.m_structinfo,ssize); - ArrayResizeAL(ensemble.m_weights,ensemble.m_ensemblesize*ensemble.m_wcount); - ArrayResizeAL(ensemble.m_columnmeans,ensemble.m_ensemblesize*ccount); - ArrayResizeAL(ensemble.m_columnsigmas,ensemble.m_ensemblesize*ccount); - ArrayResizeAL(ensemble.m_tmpweights,ensemble.m_wcount); - ArrayResizeAL(ensemble.m_tmpmeans,ccount); - ArrayResizeAL(ensemble.m_tmpsigmas,ccount); - ArrayResizeAL(ensemble.m_neurons,ntotal); - ArrayResizeAL(ensemble.m_dfdnet,ntotal); - ArrayResizeAL(ensemble.m_serializedmlp,ensemble.m_serializedlen); - ArrayResizeAL(ensemble.m_y,ensemble.m_nout); -//--- load data - for(i=offs;i<=offs+ssize-1;i++) - ensemble.m_structinfo[i-offs]=(int)MathRound(ra[i]); -//--- copy - offs=offs+ssize; - i1_=offs; - for(i_=0;i_<=ensemble.m_ensemblesize*ensemble.m_wcount-1;i_++) - ensemble.m_weights[i_]=ra[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ensemble.m_wcount; - i1_=offs; - for(i_=0;i_<=ensemble.m_ensemblesize*ccount-1;i_++) - ensemble.m_columnmeans[i_]=ra[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ccount; - i1_=offs; - for(i_=0;i_<=ensemble.m_ensemblesize*ccount-1;i_++) - ensemble.m_columnsigmas[i_]=ra[i_+i1_]; -//--- copy - offs=offs+ensemble.m_ensemblesize*ccount; - i1_=offs; - for(i_=0;i_<=ensemble.m_serializedlen-1;i_++) - ensemble.m_serializedmlp[i_]=ra[i_+i1_]; - offs=offs+ensemble.m_serializedlen; - } -//+------------------------------------------------------------------+ -//| Randomization of MLP ensemble | -//+------------------------------------------------------------------+ -static void CMLPE::MLPERandomize(CMLPEnsemble &ensemble) - { -//--- create a variable - int i=0; -//--- calculation - for(i=0;i<=ensemble.m_ensemblesize*ensemble.m_wcount-1;i++) - ensemble.m_weights[i]=CMath::RandomReal()-0.5; - } -//+------------------------------------------------------------------+ -//| Return ensemble properties (number of inputs and outputs). | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEProperties(CMLPEnsemble &ensemble,int &nin,int &nout) - { -//--- change values - nin=ensemble.m_nin; - nout=ensemble.m_nout; - } -//+------------------------------------------------------------------+ -//| Return normalization type (whether ensemble is SOFTMAX-normalized| -//| or not). | -//+------------------------------------------------------------------+ -static bool CMLPE::MLPEIsSoftMax(CMLPEnsemble &ensemble) - { -//--- return result - return(ensemble.m_issoftmax); - } -//+------------------------------------------------------------------+ -//| Procesing | -//| INPUT PARAMETERS: | -//| Ensemble- neural networks ensemble | -//| X - input vector, array[0..NIn-1]. | -//| Y - (possibly) preallocated buffer; if size of Y is | -//| less than NOut, it will be reallocated. If it is | -//| large enough, it is NOT reallocated, so we can | -//| save some time on reallocation. | -//| OUTPUT PARAMETERS: | -//| Y - result. Regression estimate when solving | -//| regression task, vector of posterior | -//| probabilities for classification task. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEProcess(CMLPEnsemble &ensemble,double &x[],double &y[]) - { -//--- create variables - int i=0; - int es=0; - int wc=0; - int cc=0; - double v=0; - int i_=0; - int i1_=0; -//--- check - if(CAp::Len(y)=0.001 | -//| Restarts - restarts, >0. | -//| OUTPUT PARAMETERS: | -//| Ensemble - trained model | -//| Info - return code: | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, Restarts<1). | -//| * 2, if task has been solved. | -//| Rep - training report. | -//| OOBErrors - out-of-bag generalization error estimate | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEBaggingLM(CMLPEnsemble &ensemble,CMatrixDouble &xy, - const int npoints,const double decay, - const int restarts,int &info,CMLPReport &rep, - CMLPCVReport &ooberrors) - { -//--- initialization - info=0; -//--- function call - MLPEBaggingInternal(ensemble,xy,npoints,decay,restarts,0.0,0,true,info,rep,ooberrors); - } -//+------------------------------------------------------------------+ -//| Training neural networks ensemble using bootstrap aggregating | -//| (bagging). L-BFGS algorithm is used as base training method. | -//| INPUT PARAMETERS: | -//| Ensemble - model with initialized geometry | -//| XY - training set | -//| NPoints - training set size | -//| Decay - weight decay coefficient, >=0.001 | -//| Restarts - restarts, >0. | -//| WStep - stopping criterion, same as in MLPTrainLBFGS | -//| MaxIts - stopping criterion, same as in MLPTrainLBFGS | -//| OUTPUT PARAMETERS: | -//| Ensemble - trained model | -//| Info - return code: | -//| * -8, if both WStep=0 and MaxIts=0 | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, Restarts<1). | -//| * 2, if task has been solved. | -//| Rep - training report. | -//| OOBErrors - out-of-bag generalization error estimate | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEBaggingLBFGS(CMLPEnsemble &ensemble,CMatrixDouble &xy, - const int npoints,const double decay, - const int restarts,const double wstep, - const int maxits,int &info,CMLPReport &rep, - CMLPCVReport &ooberrors) - { -//--- initialization - info=0; -//--- function call - MLPEBaggingInternal(ensemble,xy,npoints,decay,restarts,wstep,maxits,false,info,rep,ooberrors); - } -//+------------------------------------------------------------------+ -//| Training neural networks ensemble using early stopping. | -//| INPUT PARAMETERS: | -//| Ensemble - model with initialized geometry | -//| XY - training set | -//| NPoints - training set size | -//| Decay - weight decay coefficient, >=0.001 | -//| Restarts - restarts, >0. | -//| OUTPUT PARAMETERS: | -//| Ensemble - trained model | -//| Info - return code: | -//| * -2, if there is a point with class number | -//| outside of [0..NClasses-1]. | -//| * -1, if incorrect parameters was passed | -//| (NPoints<0, Restarts<1). | -//| * 6, if task has been solved. | -//| Rep - training report. | -//| OOBErrors - out-of-bag generalization error estimate | -//+------------------------------------------------------------------+ -static void CMLPE::MLPETrainES(CMLPEnsemble &ensemble,CMatrixDouble &xy, - const int npoints,const double decay, - const int restarts,int &info,CMLPReport &rep) - { -//--- create variables - int i=0; - int k=0; - int ccount=0; - int pcount=0; - int trnsize=0; - int valsize=0; - int tmpinfo=0; - int i_=0; - int i1_=0; -//--- create matrix - CMatrixDouble trnxy; - CMatrixDouble valxy; -//--- objects of classes - CMultilayerPerceptron network; - CMLPReport tmprep; -//--- initialization - info=0; -//--- check - if((npoints<2 || restarts<1) || decay<0.0) - { - info=-1; - return; - } -//--- check - if(ensemble.m_issoftmax) - { - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][ensemble.m_nin])<0 || (int)MathRound(xy[i][ensemble.m_nin])>=ensemble.m_nout) - { - info=-2; - return; - } - } - } -//--- change value - info=6; -//--- allocate - if(ensemble.m_issoftmax) - { - ccount=ensemble.m_nin+1; - pcount=ensemble.m_nin; - } - else - { - ccount=ensemble.m_nin+ensemble.m_nout; - pcount=ensemble.m_nin+ensemble.m_nout; - } -//--- allocation - trnxy.Resize(npoints,ccount); - valxy.Resize(npoints,ccount); -//--- function call - CMLPBase::MLPUnserializeOld(ensemble.m_serializedmlp,network); -//--- change values - rep.m_ngrad=0; - rep.m_nhess=0; - rep.m_ncholesky=0; -//--- train networks - for(k=0;k<=ensemble.m_ensemblesize-1;k++) - { - //--- Split set - do - { - trnsize=0; - valsize=0; - for(i=0;i<=npoints-1;i++) - { - //--- check - if(CMath::RandomReal()<0.66) - { - //--- Assign sample to training set - for(i_=0;i_<=ccount-1;i_++) - trnxy[trnsize].Set(i_,xy[i][i_]); - trnsize=trnsize+1; - } - else - { - //--- Assign sample to validation set - for(i_=0;i_<=ccount-1;i_++) - valxy[valsize].Set(i_,xy[i][i_]); - valsize=valsize+1; - } - } - } - while(!(trnsize!=0 && valsize!=0)); - //--- Train - CMLPTrain::MLPTrainES(network,trnxy,trnsize,valxy,valsize,decay,restarts,tmpinfo,tmprep); - //--- check - if(tmpinfo<0) - { - info=tmpinfo; - return; - } - //--- save results - i1_=-(k*ensemble.m_wcount); - for(i_=k*ensemble.m_wcount;i_<=(k+1)*ensemble.m_wcount-1;i_++) - ensemble.m_weights[i_]=network.m_weights[i_+i1_]; - i1_=-(k*pcount); - for(i_=k*pcount;i_<=(k+1)*pcount-1;i_++) - ensemble.m_columnmeans[i_]=network.m_columnmeans[i_+i1_]; - i1_=-(k*pcount); - for(i_=k*pcount;i_<=(k+1)*pcount-1;i_++) - ensemble.m_columnsigmas[i_]=network.m_columnsigmas[i_+i1_]; - //--- change values - rep.m_ngrad=rep.m_ngrad+tmprep.m_ngrad; - rep.m_nhess=rep.m_nhess+tmprep.m_nhess; - rep.m_ncholesky=rep.m_ncholesky+tmprep.m_ncholesky; - } - } -//+------------------------------------------------------------------+ -//| Calculation of all types of errors | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEAllErrors(CMLPEnsemble &ensemble,CMatrixDouble &xy, - const int npoints,double &relcls, - double &avgce,double &rms, - double &avg,double &avgrel) - { -//--- create variables - int i=0; - int i_=0; - int i1_=0; -//--- creating arrays - double buf[]; - double workx[]; - double y[]; - double dy[]; -//--- initialization - relcls=0; - avgce=0; - rms=0; - avg=0; - avgrel=0; -//--- allocation - ArrayResizeAL(workx,ensemble.m_nin); - ArrayResizeAL(y,ensemble.m_nout); -//--- check - if(ensemble.m_issoftmax) - { - //--- allocation - ArrayResizeAL(dy,1); - //--- function call - CBdSS::DSErrAllocate(ensemble.m_nout,buf); - } - else - { - //--- allocation - ArrayResizeAL(dy,ensemble.m_nout); - //--- function call - CBdSS::DSErrAllocate(-ensemble.m_nout,buf); - } -//--- calculation - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=ensemble.m_nin-1;i_++) - workx[i_]=xy[i][i_]; - //--- function call - MLPEProcess(ensemble,workx,y); - //--- check - if(ensemble.m_issoftmax) - dy[0]=xy[i][ensemble.m_nin]; - else - { - i1_=ensemble.m_nin; - for(i_=0;i_<=ensemble.m_nout-1;i_++) - dy[i_]=xy[i][i_+i1_]; - } - //--- function call - CBdSS::DSErrAccumulate(buf,y,dy); - } -//--- function call - CBdSS::DSErrFinish(buf); -//--- change values - relcls=buf[0]; - avgce=buf[1]; - rms=buf[2]; - avg=buf[3]; - avgrel=buf[4]; - } -//+------------------------------------------------------------------+ -//| Internal bagging subroutine. | -//+------------------------------------------------------------------+ -static void CMLPE::MLPEBaggingInternal(CMLPEnsemble &ensemble,CMatrixDouble &xy, - const int npoints,const double decay, - const int restarts,const double wstep, - const int maxits,const bool lmalgorithm, - int &info,CMLPReport &rep,CMLPCVReport &ooberrors) - { -//--- create variables - int nin=0; - int nout=0; - int ccnt=0; - int pcnt=0; - int i=0; - int j=0; - int k=0; - double v=0; - int i_=0; - int i1_=0; -//--- creating arrays - bool s[]; - int oobcntbuf[]; - double x[]; - double y[]; - double dy[]; - double dsbuf[]; -//--- create matrix - CMatrixDouble xys; - CMatrixDouble oobbuf; -//--- objects of classes - CMLPReport tmprep; - CMultilayerPerceptron network; -//--- initialization - info=0; -//--- Test for inputs - if((!lmalgorithm && wstep==0.0) && maxits==0) - { - info=-8; - return; - } -//--- check - if(((npoints<=0 || restarts<1) || wstep<0.0) || maxits<0) - { - info=-1; - return; - } -//--- check - if(ensemble.m_issoftmax) - { - for(i=0;i<=npoints-1;i++) - { - //--- check - if((int)MathRound(xy[i][ensemble.m_nin])<0 || (int)MathRound(xy[i][ensemble.m_nin])>=ensemble.m_nout) - { - info=-2; - return; - } - } - } -//--- allocate temporaries - info=2; - rep.m_ngrad=0; - rep.m_nhess=0; - rep.m_ncholesky=0; - ooberrors.m_relclserror=0; - ooberrors.m_avgce=0; - ooberrors.m_rmserror=0; - ooberrors.m_avgerror=0; - ooberrors.m_avgrelerror=0; - nin=ensemble.m_nin; - nout=ensemble.m_nout; -//--- check - if(ensemble.m_issoftmax) - { - ccnt=nin+1; - pcnt=nin; - } - else - { - ccnt=nin+nout; - pcnt=nin+nout; - } -//--- allocation - xys.Resize(npoints,ccnt); - ArrayResizeAL(s,npoints); - oobbuf.Resize(npoints,nout); - ArrayResizeAL(oobcntbuf,npoints); - ArrayResizeAL(x,nin); - ArrayResizeAL(y,nout); -//--- check - if(ensemble.m_issoftmax) - ArrayResizeAL(dy,1); - else - ArrayResizeAL(dy,nout); -//--- initialization - for(i=0;i<=npoints-1;i++) - { - for(j=0;j<=nout-1;j++) - oobbuf[i].Set(j,0); - } - for(i=0;i<=npoints-1;i++) - oobcntbuf[i]=0; -//--- function call - CMLPBase::MLPUnserializeOld(ensemble.m_serializedmlp,network); -//--- main bagging cycle - for(k=0;k<=ensemble.m_ensemblesize-1;k++) - { - //--- prepare dataset - for(i=0;i<=npoints-1;i++) - s[i]=false; - for(i=0;i<=npoints-1;i++) - { - j=CMath::RandomInteger(npoints); - s[j]=true; - for(i_=0;i_<=ccnt-1;i_++) - xys[i].Set(i_,xy[j][i_]); - } - //--- train - if(lmalgorithm) - CMLPTrain::MLPTrainLM(network,xys,npoints,decay,restarts,info,tmprep); - else - CMLPTrain::MLPTrainLBFGS(network,xys,npoints,decay,restarts,wstep,maxits,info,tmprep); - //--- check - if(info<0) - return; - //--- save results - rep.m_ngrad=rep.m_ngrad+tmprep.m_ngrad; - rep.m_nhess=rep.m_nhess+tmprep.m_nhess; - rep.m_ncholesky=rep.m_ncholesky+tmprep.m_ncholesky; - //--- copy - i1_=-(k*ensemble.m_wcount); - for(i_=k*ensemble.m_wcount;i_<=(k+1)*ensemble.m_wcount-1;i_++) - ensemble.m_weights[i_]=network.m_weights[i_+i1_]; - //--- copy - i1_=-(k*pcnt); - for(i_=k*pcnt;i_<=(k+1)*pcnt-1;i_++) - ensemble.m_columnmeans[i_]=network.m_columnmeans[i_+i1_]; - //--- copy - i1_=-(k*pcnt); - for(i_=k*pcnt;i_<=(k+1)*pcnt-1;i_++) - ensemble.m_columnsigmas[i_]=network.m_columnsigmas[i_+i1_]; - //--- OOB estimates - for(i=0;i<=npoints-1;i++) - { - //--- check - if(!s[i]) - { - for(i_=0;i_<=nin-1;i_++) - x[i_]=xy[i][i_]; - //--- function call - CMLPBase::MLPProcess(network,x,y); - //--- change value - for(i_=0;i_<=nout-1;i_++) - oobbuf[i].Set(i_,oobbuf[i][i_]+y[i_]); - oobcntbuf[i]=oobcntbuf[i]+1; - } - } - } -//--- OOB estimates - if(ensemble.m_issoftmax) - { - //--- function call - CBdSS::DSErrAllocate(nout,dsbuf); - } - else - { - //--- function call - CBdSS::DSErrAllocate(-nout,dsbuf); - } - for(i=0;i<=npoints-1;i++) - { - //--- check - if(oobcntbuf[i]!=0) - { - v=1.0/(double)oobcntbuf[i]; - for(i_=0;i_<=nout-1;i_++) - y[i_]=v*oobbuf[i][i_]; - //--- check - if(ensemble.m_issoftmax) - dy[0]=xy[i][nin]; - else - { - i1_=nin; - for(i_=0;i_<=nout-1;i_++) - dy[i_]=v*xy[i][i_+i1_]; - } - //--- function call - CBdSS::DSErrAccumulate(dsbuf,y,dy); - } - } -//--- function call - CBdSS::DSErrFinish(dsbuf); -//--- change values - ooberrors.m_relclserror=dsbuf[0]; - ooberrors.m_avgce=dsbuf[1]; - ooberrors.m_rmserror=dsbuf[2]; - ooberrors.m_avgerror=dsbuf[3]; - ooberrors.m_avgrelerror=dsbuf[4]; - } -//+------------------------------------------------------------------+ -//| Principal components analysis | -//+------------------------------------------------------------------+ -class CPCAnalysis - { -public: - //--- constructor, destructor - CPCAnalysis(void); - ~CPCAnalysis(void); - //--- method - static void PCABuildBasis(CMatrixDouble &x,const int npoints,const int nvars,int &info,double &s2[],CMatrixDouble &v); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPCAnalysis::CPCAnalysis(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPCAnalysis::~CPCAnalysis(void) - { - - } -//+------------------------------------------------------------------+ -//| Principal components analysis | -//| Subroutine builds orthogonal basis where first axis corresponds | -//| to direction with maximum variance, second axis maximizes | -//| variance in subspace orthogonal to first axis and so on. | -//| It should be noted that, unlike LDA, PCA does not use class | -//| labels. | -//| INPUT PARAMETERS: | -//| X - dataset, array[0..NPoints-1,0..NVars-1]. | -//| matrix contains ONLY INDEPENDENT VARIABLES. | -//| NPoints - dataset size, NPoints>=0 | -//| NVars - number of independent variables, NVars>=1 | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -4, if SVD subroutine haven't converged | -//| * -1, if wrong parameters has been passed | -//| (NPoints<0, NVars<1) | -//| * 1, if task is solved | -//| S2 - array[0..NVars-1]. variance values | -//| corresponding to basis vectors. | -//| V - array[0..NVars-1,0..NVars-1] | -//| matrix, whose columns store basis vectors. | -//+------------------------------------------------------------------+ -static void CPCAnalysis::PCABuildBasis(CMatrixDouble &x,const int npoints, - const int nvars,int &info,double &s2[], - CMatrixDouble &v) - { -//--- create variables - int i=0; - int j=0; - double mean=0; - double variance=0; - double skewness=0; - double kurtosis=0; - int i_=0; -//--- creating arrays - double m[]; - double t[]; -//--- create matrix - CMatrixDouble a; - CMatrixDouble u; - CMatrixDouble vt; -//--- initialization - info=0; -//--- Check input data - if(npoints<0 || nvars<1) - { - info=-1; - return; - } -//--- change value - info=1; -//--- Special case: NPoints=0 - if(npoints==0) - { - //--- allocation - ArrayResizeAL(s2,nvars); - v.Resize(nvars,nvars); - //--- initialization - for(i=0;i<=nvars-1;i++) - s2[i]=0; - for(i=0;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - { - //--- check - if(i==j) - v[i].Set(j,1); - else - v[i].Set(j,0); - } - } - //--- exit the function - return; - } -//--- Calculate means - ArrayResizeAL(m,nvars); - ArrayResizeAL(t,npoints); - for(j=0;j<=nvars-1;j++) - { - for(i_=0;i_<=npoints-1;i_++) - t[i_]=x[i_][j]; - //--- function call - CBaseStat::SampleMoments(t,npoints,mean,variance,skewness,kurtosis); - m[j]=mean; - } -//--- Center,apply SVD,prepare output - a.Resize(MathMax(npoints,nvars),nvars); -//--- calculation - for(i=0;i<=npoints-1;i++) - { - for(i_=0;i_<=nvars-1;i_++) - a[i].Set(i_,x[i][i_]); - for(i_=0;i_<=nvars-1;i_++) - a[i].Set(i_,a[i][i_]-m[i_]); - } - for(i=npoints;i<=nvars-1;i++) - { - for(j=0;j<=nvars-1;j++) - a[i].Set(j,0); - } -//--- check - if(!CSingValueDecompose::RMatrixSVD(a,MathMax(npoints,nvars),nvars,0,1,2,s2,u,vt)) - { - info=-4; - return; - } -//--- check - if(npoints!=1) - { - for(i=0;i<=nvars-1;i++) - s2[i]=CMath::Sqr(s2[i])/(npoints-1); - } -//--- allocation - v.Resize(nvars,nvars); -//--- function call - CBlas::CopyAndTranspose(vt,0,nvars-1,0,nvars-1,v,0,nvars-1,0,nvars-1); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/delegatefunctions.mqh b/Include/Math/Alglib/delegatefunctions.mqh deleted file mode 100644 index 9b4b0a1..0000000 --- a/Include/Math/Alglib/delegatefunctions.mqh +++ /dev/null @@ -1,412 +0,0 @@ -//+------------------------------------------------------------------+ -//| delegatefunctions.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "matrix.mqh" -//+------------------------------------------------------------------+ -//| Calculates f(arg), stores result to func | -//+------------------------------------------------------------------+ -class CNDimensional_Func - { -public: - CNDimensional_Func(void); - ~CNDimensional_Func(void); - - virtual void Func(double &x[],double &func,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_Func::CNDimensional_Func(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_Func::~CNDimensional_Func(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_Func::Func(double &x[],double &func,CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| calculates func = f(arg), grad[i] = df(arg)/d(arg[i]) | -//+------------------------------------------------------------------+ -class CNDimensional_Grad - { -public: - //--- constructor, destructor - CNDimensional_Grad(void); - ~CNDimensional_Grad(void); - //--- virtual method - virtual void Grad(double &x[],double &func,double &grad[],CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_Grad::CNDimensional_Grad(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_Grad::~CNDimensional_Grad(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_Grad::Grad(double &x[],double &func,double &grad[], - CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates func = f(arg), grad[i] = df(arg)/d(arg[i]), | -//| hess[i,j] = d2f(arg)/(d(arg[i])*d(arg[j])) | -//+------------------------------------------------------------------+ -class CNDimensional_Hess - { -public: - //--- constructor, destructor - CNDimensional_Hess(void); - ~CNDimensional_Hess(void); - //--- virtual method - virtual void Hess(double &x[],double &func,double &grad[],CMatrixDouble &hess,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_Hess::CNDimensional_Hess(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_Hess::~CNDimensional_Hess(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_Hess::Hess(double &x[],double &func,double &grad[], - CMatrixDouble &hess,CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates vector function f(arg), stores result to fi | -//+------------------------------------------------------------------+ -class CNDimensional_FVec - { -public: - //--- constructor, destructor - CNDimensional_FVec(void); - ~CNDimensional_FVec(void); - //--- virtual method - virtual void FVec(double &x[],double &fi[],CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_FVec::CNDimensional_FVec(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_FVec::~CNDimensional_FVec(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_FVec::FVec(double &x[],double &fi[],CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates f[i] = fi(arg), jac[i,j] = df[i](arg)/d(arg[j]) | -//+------------------------------------------------------------------+ -class CNDimensional_Jac - { -public: - //--- constructor, destructor - CNDimensional_Jac(void); - ~CNDimensional_Jac(void); - //--- virtual method - virtual void Jac(double &x[],double &fi[],CMatrixDouble &jac, - CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_Jac::CNDimensional_Jac(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_Jac::~CNDimensional_Jac(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_Jac::Jac(double &x[],double &fi[],CMatrixDouble &jac, - CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates f(p,q), stores result to func | -//+------------------------------------------------------------------+ -class CNDimensional_PFunc - { -public: - //--- constructor, destructor - CNDimensional_PFunc(void); - ~CNDimensional_PFunc(void); - //--- virtual method - virtual void PFunc(double &c[],double &x[],double &func,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_PFunc::CNDimensional_PFunc(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_PFunc::~CNDimensional_PFunc(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_PFunc::PFunc(double &c[],double &x[],double &func, - CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates func = f(p,q), grad[i] = df(p,q)/d(p[i]) | -//+------------------------------------------------------------------+ -class CNDimensional_PGrad - { -public: - //--- constructor, destructor - CNDimensional_PGrad(void); - ~CNDimensional_PGrad(void); - //--- virtual method - virtual void PGrad(double &c[],double &x[],double &func,double &grad[],CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_PGrad::CNDimensional_PGrad(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_PGrad::~CNDimensional_PGrad(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_PGrad::PGrad(double &c[],double &x[],double &func, - double &grad[],CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Calculates func = f(p,q), grad[i] = df(p,q)/d(p[i]), | -//| hess[i,j] = d2f(p,q)/(d(p[i])*d(p[j])) | -//+------------------------------------------------------------------+ -class CNDimensional_PHess - { -public: - //--- constructor, destructor - CNDimensional_PHess(void); - ~CNDimensional_PHess(void); - //--- virtual method - virtual void PHess(double &c[],double &x[],double &func,double &grad[],CMatrixDouble &hess,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_PHess::CNDimensional_PHess(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_PHess::~CNDimensional_PHess(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_PHess::PHess(double &c[],double &x[],double &func, - double &grad[],CMatrixDouble &hess, - CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Callbacks for ODE solvers: calculates dy/dx for given y[] and x | -//+------------------------------------------------------------------+ -class CNDimensional_ODE_RP - { -public: - //--- constructor, destructor - CNDimensional_ODE_RP(void); - ~CNDimensional_ODE_RP(void); - //--- virtual method - virtual void ODE_RP(double &y[],double x,double &dy[],CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_ODE_RP::CNDimensional_ODE_RP(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_ODE_RP::~CNDimensional_ODE_RP(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_ODE_RP::ODE_RP(double &y[],double x,double &dy[], - CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Callbacks for integrators: calculates f(x) for given x | -//| (additional parameters xminusa and bminusx contain x-a and b-x) | -//+------------------------------------------------------------------+ -class CIntegrator1_Func - { -public: - //--- constructor, destructor - CIntegrator1_Func(void); - ~CIntegrator1_Func(void); - //--- virtual method - virtual void Int_Func(double x,double xminusa,double bminusx,double &y,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIntegrator1_Func::CIntegrator1_Func(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIntegrator1_Func::~CIntegrator1_Func(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CIntegrator1_Func::Int_Func(double x,double xminusa,double bminusx, - double &y,CObject &obj) - { - - } -//+------------------------------------------------------------------+ -//| Callbacks for progress reports: reports current position of | -//| optimization algo | -//+------------------------------------------------------------------+ -class CNDimensional_Rep - { -public: - //--- constructor, destructor - CNDimensional_Rep(void); - ~CNDimensional_Rep(void); - //--- virtual method - virtual void Rep(double &arg[],double func,CObject &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNDimensional_Rep::CNDimensional_Rep(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNDimensional_Rep::~CNDimensional_Rep(void) - { - - } -//+------------------------------------------------------------------+ -//| Empty function body | -//+------------------------------------------------------------------+ -void CNDimensional_Rep::Rep(double &arg[],double func,CObject &obj) - { - - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/diffequations.mqh b/Include/Math/Alglib/diffequations.mqh deleted file mode 100644 index 8470b0b..0000000 --- a/Include/Math/Alglib/diffequations.mqh +++ /dev/null @@ -1,928 +0,0 @@ -//+------------------------------------------------------------------+ -//| diffequations.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "matrix.mqh" -#include "alglibinternal.mqh" -//+------------------------------------------------------------------+ -//| Auxiliary class for CODESolver | -//+------------------------------------------------------------------+ -class CODESolverState - { -public: - int m_n; - int m_m; - double m_xscale; - double m_h; - double m_eps; - bool m_fraceps; - int m_repterminationtype; - int m_repnfev; - int m_solvertype; - bool m_needdy; - double m_x; - RCommState m_rstate; - //--- arrays - double m_yc[]; - double m_escale[]; - double m_xg[]; - double m_y[]; - double m_dy[]; - double m_yn[]; - double m_yns[]; - double m_rka[]; - double m_rkc[]; - double m_rkcs[]; - //--- matrices - CMatrixDouble m_ytbl; - CMatrixDouble m_rkb; - CMatrixDouble m_rkk; - -public: - CODESolverState(void); - ~CODESolverState(void); - - void Copy(CODESolverState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CODESolverState::CODESolverState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CODESolverState::~CODESolverState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CODESolverState::Copy(CODESolverState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_m=obj.m_m; - m_xscale=obj.m_xscale; - m_h=obj.m_h; - m_eps=obj.m_eps; - m_fraceps=obj.m_fraceps; - m_repterminationtype=obj.m_repterminationtype; - m_repnfev=obj.m_repnfev; - m_solvertype=obj.m_solvertype; - m_needdy=obj.m_needdy; - m_x=obj.m_x; - m_rstate.Copy(obj.m_rstate); -//--- copy arrays - ArrayCopy(m_yc,obj.m_yc); - ArrayCopy(m_escale,obj.m_escale); - ArrayCopy(m_xg,obj.m_xg); - ArrayCopy(m_y,obj.m_y); - ArrayCopy(m_dy,obj.m_dy); - ArrayCopy(m_yn,obj.m_yn); - ArrayCopy(m_yns,obj.m_yns); - ArrayCopy(m_rka,obj.m_rka); - ArrayCopy(m_rkc,obj.m_rkc); - ArrayCopy(m_rkcs,obj.m_rkcs); -//--- copy matrices - m_ytbl=obj.m_ytbl; - m_rkb=obj.m_rkb; - m_rkk=obj.m_rkk; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CODESolverState | -//+------------------------------------------------------------------+ -class CODESolverStateShell - { -private: - CODESolverState m_innerobj; -public: - //--- constructors, destructor - CODESolverStateShell(void); - CODESolverStateShell(CODESolverState &obj); - ~CODESolverStateShell(void); - //--- methods - bool GetNeedDY(void); - void SetNeedDY(const bool b); - double GetX(void); - void SetX(const double d); - CODESolverState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CODESolverStateShell::CODESolverStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CODESolverStateShell::CODESolverStateShell(CODESolverState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CODESolverStateShell::~CODESolverStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needdy | -//+------------------------------------------------------------------+ -bool CODESolverStateShell::GetNeedDY(void) - { -//--- return result - return(m_innerobj.m_needdy); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needdy | -//+------------------------------------------------------------------+ -void CODESolverStateShell::SetNeedDY(const bool b) - { -//--- change value - m_innerobj.m_needdy=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable x | -//+------------------------------------------------------------------+ -double CODESolverStateShell::GetX(void) - { -//--- return result - return(m_innerobj.m_x); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable x | -//+------------------------------------------------------------------+ -void CODESolverStateShell::SetX(const double d) - { -//--- change value - m_innerobj.m_x=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CODESolverState *CODESolverStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CODESolver | -//+------------------------------------------------------------------+ -class CODESolverReport - { -public: - //--- class variables - int m_nfev; - int m_terminationtype; - //--- constructor, destructor - CODESolverReport(void); - ~CODESolverReport(void); - //--- copy - void Copy(CODESolverReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CODESolverReport::CODESolverReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CODESolverReport::~CODESolverReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CODESolverReport::Copy(CODESolverReport &obj) - { -//--- copy variables - m_nfev=obj.m_nfev; - m_terminationtype=obj.m_terminationtype; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CODESolverReport | -//+------------------------------------------------------------------+ -class CODESolverReportShell - { -private: - CODESolverReport m_innerobj; -public: - //--- constructor, destructor - CODESolverReportShell(void); - CODESolverReportShell(CODESolverReport &obj); - ~CODESolverReportShell(void); - //--- methods - int GetNFev(void); - void SetNFev(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - CODESolverReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CODESolverReportShell::CODESolverReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CODESolverReportShell::CODESolverReportShell(CODESolverReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CODESolverReportShell::~CODESolverReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfev | -//+------------------------------------------------------------------+ -int CODESolverReportShell::GetNFev(void) - { -//--- return result - return(m_innerobj.m_nfev); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfev | -//+------------------------------------------------------------------+ -void CODESolverReportShell::SetNFev(const int i) - { -//--- change value - m_innerobj.m_nfev=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CODESolverReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CODESolverReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CODESolverReport *CODESolverReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Solution of ordinary differential equations | -//+------------------------------------------------------------------+ -class CODESolver - { -private: - //--- private method - static void ODESolverInit(int solvertype,double &y[],const int n,double &x[],const int m,const double eps,double h,CODESolverState &state); - //--- auxiliary functions for ODESolverIteration - static void Func_lbl_rcomm(CODESolverState &state,int n,int m,int i,int j,int k,int klimit,bool gridpoint,double xc,double v,double h,double h2,double err,double maxgrowpow); - static bool Func_lbl_6(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow); - static bool Func_lbl_8(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow); - static bool Func_lbl_10(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow); -public: - //--- class constants - static const double m_odesolvermaxgrow; - static const double m_odesolvermaxshrink; - //--- constructor, destructor - CODESolver(void); - ~CODESolver(void); - //--- public methods - static void ODESolverRKCK(double &y[],const int n,double &x[],const int m,const double eps,const double h,CODESolverState &state); - static void ODESolverResults(CODESolverState &state,int &m,double &xtbl[],CMatrixDouble &ytbl,CODESolverReport &rep); - static bool ODESolverIteration(CODESolverState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CODESolver::m_odesolvermaxgrow=3.0; -const double CODESolver::m_odesolvermaxshrink=10.0; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CODESolver::CODESolver(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CODESolver::~CODESolver(void) - { - - } -//+------------------------------------------------------------------+ -//| Cash-Karp adaptive ODE solver. | -//| This subroutine solves ODE Y'=f(Y,x) with initial conditions | -//| Y(xs)=Ys (here Y may be single variable or vector of N variables)| -//| INPUT PARAMETERS: | -//| Y - initial conditions, array[0..N-1]. | -//| contains values of Y[] at X[0] | -//| N - system size | -//| X - points at which Y should be tabulated, | -//| array[0..M-1] integrations starts at X[0], ends | -//| at X[M-1], intermediate values at X[i] are | -//| returned too. | -//| SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING!!| -//| M - number of intermediate points + first point + | -//| last point: | -//| * M>2 means that you need both Y(X[M-1]) and M-2 | -//| values at intermediate points | -//| * M=2 means that you want just to integrate from | -//| X[0] to X[1] and don't interested in | -//| intermediate values. | -//| * M=1 means that you don't want to integrate :) | -//| it is degenerate case, but it will be handled | -//| correctly. | -//| * M<1 means error | -//| Eps - tolerance (absolute/relative error on each step | -//| will be less than Eps). When passing: | -//| * Eps>0, it means desired ABSOLUTE error | -//| * Eps<0, it means desired RELATIVE error. | -//| Relative errors are calculated with respect to | -//| maximum values of Y seen so far. Be careful to | -//| use this criterion when starting from Y[] that | -//| are close to zero. | -//| H - initial step lenth, it will be adjusted | -//| automatically after the first step. If H=0, step | -//| will be selected automatically (usualy it will | -//| be equal to 0.001 of min(x[i]-x[j])). | -//| OUTPUT PARAMETERS | -//| State - structure which stores algorithm state between | -//| subsequent calls of OdeSolverIteration. Used | -//| for reverse communication. This structure should | -//| be passed to the OdeSolverIteration subroutine. | -//| SEE ALSO | -//| AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults| -//+------------------------------------------------------------------+ -static void CODESolver::ODESolverRKCK(double &y[],const int n,double &x[], - const int m,const double eps, - const double h,CODESolverState &state) - { -//--- check - if(!CAp::Assert(n>=1,"ODESolverRKCK: N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,"ODESolverRKCK: M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,"ODESolverRKCK: Length(Y)=m,"ODESolverRKCK: Length(X)=1 | -//| XTbl - array[0..M-1], values of X | -//| YTbl - array[0..M-1,0..N-1], values of Y in X[i] | -//| Rep - solver report: | -//| * Rep.TerminationType completetion code: | -//| * -2 X is not ordered by | -//| ascending/descending or there are | -//| non-distinct X[], i.e. X[i]=X[i+1] | -//| * -1 incorrect parameters were specified | -//| * 1 task has been solved | -//| * Rep.NFEV contains number of function | -//| calculations | -//+------------------------------------------------------------------+ -static void CODESolver::ODESolverResults(CODESolverState &state,int &m, - double &xtbl[],CMatrixDouble &ytbl, - CODESolverReport &rep) - { -//--- create variables - double v=0; - int i=0; - int i_=0; -//--- initialization - m=0; - rep.m_terminationtype=state.m_repterminationtype; -//--- check - if(rep.m_terminationtype>0) - { - //--- change values - m=state.m_m; - rep.m_nfev=state.m_repnfev; - //--- allocation - ArrayResizeAL(xtbl,state.m_m); - v=state.m_xscale; - //--- calculation - for(i_=0;i_<=state.m_m-1;i_++) - xtbl[i_]=v*state.m_xg[i_]; - //--- allocation - ytbl.Resize(state.m_m,state.m_n); - for(i=0;i<=state.m_m-1;i++) - { - for(i_=0;i_<=state.m_n-1;i_++) - ytbl[i].Set(i_,state.m_ytbl[i][i_]); - } - } - else - rep.m_nfev=0; - } -//+------------------------------------------------------------------+ -//| Internal initialization subroutine | -//+------------------------------------------------------------------+ -static void CODESolver::ODESolverInit(int solvertype,double &y[],const int n, - double &x[],const int m,const double eps, - double h,CODESolverState &state) - { -//--- create variables - int i=0; - double v=0; - int i_=0; -//--- Prepare RComm - ArrayResizeAL(state.m_rstate.ia,6); - ArrayResizeAL(state.m_rstate.ba,1); - ArrayResizeAL(state.m_rstate.ra,6); - state.m_rstate.stage=-1; - state.m_needdy=false; -//--- check parameters. - if((n<=0 || m<1) || eps==0.0) - { - state.m_repterminationtype=-1; - return; - } -//--- check - if(h<0.0) - h=-h; -//--- quick exit if necessary. -//--- after this block we assume that M>1 - if(m==1) - { - //--- change values - state.m_repnfev=0; - state.m_repterminationtype=1; - state.m_ytbl.Resize(1,n); - for(i_=0;i_<=n-1;i_++) - state.m_ytbl[0].Set(i_,y[i_]); - //--- allocation - ArrayResizeAL(state.m_xg,m); - for(i_=0;i_<=m-1;i_++) - state.m_xg[i_]=x[i_]; - //--- exit the function - return; - } -//--- check again: correct order of X[] - if(x[1]==x[0]) - { - state.m_repterminationtype=-2; - return; - } - for(i=1;i<=m-1;i++) - { - //--- check - if((x[1]>x[0] && x[i]<=x[i-1]) || (x[1]=x[i-1])) - { - state.m_repterminationtype=-2; - return; - } - } -//--- auto-select H if necessary - if(h==0.0) - { - v=MathAbs(x[1]-x[0]); - for(i=2;i<=m-1;i++) - v=MathMin(v,MathAbs(x[i]-x[i-1])); - h=0.001*v; - } -//--- store parameters - state.m_n=n; - state.m_m=m; - state.m_h=h; - state.m_eps=MathAbs(eps); - state.m_fraceps=eps<0.0; -//--- allocation - ArrayResizeAL(state.m_xg,m); - for(i_=0;i_<=m-1;i_++) - state.m_xg[i_]=x[i_]; -//--- check - if(x[1]>x[0]) - state.m_xscale=1; - else - { - state.m_xscale=-1; - for(i_=0;i_<=m-1;i_++) - state.m_xg[i_]=-1*state.m_xg[i_]; - } -//--- allocation - ArrayResizeAL(state.m_yc,n); - for(i_=0;i_<=n-1;i_++) - state.m_yc[i_]=y[i_]; -//--- change values - state.m_solvertype=solvertype; - state.m_repterminationtype=0; -//--- Allocate arrays - ArrayResizeAL(state.m_y,n); - ArrayResizeAL(state.m_dy,n); - } -//+------------------------------------------------------------------+ -//| Iterative method | -//+------------------------------------------------------------------+ -static bool CODESolver::ODESolverIteration(CODESolverState &state) - { -//--- create variables - int n=0; - int m=0; - int i=0; - int j=0; - int k=0; - double xc=0; - double v=0; - double h=0; - double h2=0; - bool gridpoint; - double err=0; - double maxgrowpow=0; - int klimit=0; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - m=state.m_rstate.ia[1]; - i=state.m_rstate.ia[2]; - j=state.m_rstate.ia[3]; - k=state.m_rstate.ia[4]; - klimit=state.m_rstate.ia[5]; - gridpoint=state.m_rstate.ba[0]; - xc=state.m_rstate.ra[0]; - v=state.m_rstate.ra[1]; - h=state.m_rstate.ra[2]; - h2=state.m_rstate.ra[3]; - err=state.m_rstate.ra[4]; - maxgrowpow=state.m_rstate.ra[5]; - } - else - { - //--- initialization - n=-983; - m=-989; - i=-834; - j=900; - k=-287; - klimit=364; - gridpoint=false; - xc=-338; - v=-686; - h=912; - h2=585; - err=497; - maxgrowpow=-271; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change values - state.m_needdy=false; - state.m_repnfev=state.m_repnfev+1; - v=h*state.m_xscale; - for(i_=0;i_<=n-1;i_++) - state.m_rkk[k].Set(i_,v*state.m_dy[i_]); - //--- update YN/YNS - v=state.m_rkc[k]; - for(i_=0;i_<=n-1;i_++) - state.m_yn[i_]=state.m_yn[i_]+v*state.m_rkk[k][i_]; - v=state.m_rkcs[k]; - for(i_=0;i_<=n-1;i_++) - state.m_yns[i_]=state.m_yns[i_]+v*state.m_rkk[k][i_]; - k=k+1; - return(Func_lbl_8(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//--- Routine body -//--- prepare - if(state.m_repterminationtype!=0) - return(false); -//--- change values - n=state.m_n; - m=state.m_m; - h=state.m_h; - maxgrowpow=MathPow(m_odesolvermaxgrow,5); - state.m_repnfev=0; -//--- some preliminary checks for internal errors -//--- after this we assume that H>0 and M>1 - if(!CAp::Assert(state.m_h>0.0,"ODESolver: internal error")) - return(false); -//--- check - if(!CAp::Assert(m>1,"ODESolverIteration: internal error")) - return(false); -//--- choose solver - if(state.m_solvertype!=0) - return(false); -//--- Cask-Karp solver -//--- Prepare coefficients table. -//--- Check it for errors - ArrayResizeAL(state.m_rka,6); -//--- calculation - state.m_rka[0]=0; - state.m_rka[1]=1.0/5.0; - state.m_rka[2]=3.0/10.0; - state.m_rka[3]=3.0/5.0; - state.m_rka[4]=1; - state.m_rka[5]=7.0/8.0; - state.m_rkb.Resize(6,5); - state.m_rkb[1].Set(0,1.0/5.0); - state.m_rkb[2].Set(0,3.0/40.0); - state.m_rkb[2].Set(1,9.0/40.0); - state.m_rkb[3].Set(0,3.0/10.0); - state.m_rkb[3].Set(1,-(9.0/10.0)); - state.m_rkb[3].Set(2,6.0/5.0); - state.m_rkb[4].Set(0,-(11.0/54.0)); - state.m_rkb[4].Set(1,5.0/2.0); - state.m_rkb[4].Set(2,-(70.0/27.0)); - state.m_rkb[4].Set(3,35.0/27.0); - state.m_rkb[5].Set(0,1631.0/55296.0); - state.m_rkb[5].Set(1,175.0/512.0); - state.m_rkb[5].Set(2,575.0/13824.0); - state.m_rkb[5].Set(3,44275.0/110592.0); - state.m_rkb[5].Set(4,253.0/4096.0); -//--- allocation - ArrayResizeAL(state.m_rkc,6); -//--- calculation - state.m_rkc[0]=37.0/378.0; - state.m_rkc[1]=0; - state.m_rkc[2]=250.0/621.0; - state.m_rkc[3]=125.0/594.0; - state.m_rkc[4]=0; - state.m_rkc[5]=512.0/1771.0; -//--- allocation - ArrayResizeAL(state.m_rkcs,6); -//--- calculation - state.m_rkcs[0]=2825.0/27648.0; - state.m_rkcs[1]=0; - state.m_rkcs[2]=18575.0/48384.0; - state.m_rkcs[3]=13525.0/55296.0; - state.m_rkcs[4]=277.0/14336.0; - state.m_rkcs[5]=1.0/4.0; - state.m_rkk.Resize(6,n); -//--- Main cycle consists of two iterations: -//--- * outer where we travel from X[i-1] to X[i] -//--- * inner where we travel inside [X[i-1],X[i]] - state.m_ytbl.Resize(m,n); - ArrayResizeAL(state.m_escale,n); - ArrayResizeAL(state.m_yn,n); - ArrayResizeAL(state.m_yns,n); -//--- change value - xc=state.m_xg[0]; - for(i_=0;i_<=n-1;i_++) - state.m_ytbl[0].Set(i_,state.m_yc[i_]); - for(j=0;j<=n-1;j++) - state.m_escale[j]=0; - i=1; -//--- check - if(i>m-1) - { - state.m_repterminationtype=1; - //--- return result - return(false); - } -//--- begin inner iteration - return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ODESolverIteration. Is a product to get | -//| rid of the operator unconditional jump goto | -//+------------------------------------------------------------------+ -static void CODESolver::Func_lbl_rcomm(CODESolverState &state,int n,int m, - int i,int j,int k,int klimit, - bool gridpoint,double xc,double v, - double h,double h2,double err, - double maxgrowpow) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=m; - state.m_rstate.ia[2]=i; - state.m_rstate.ia[3]=j; - state.m_rstate.ia[4]=k; - state.m_rstate.ia[5]=klimit; - state.m_rstate.ba[0]=gridpoint; - state.m_rstate.ra[0]=xc; - state.m_rstate.ra[1]=v; - state.m_rstate.ra[2]=h; - state.m_rstate.ra[3]=h2; - state.m_rstate.ra[4]=err; - state.m_rstate.ra[5]=maxgrowpow; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ODESolverIteration. Is a product to get | -//| rid of the operator unconditional jump goto | -//+------------------------------------------------------------------+ -static bool CODESolver::Func_lbl_6(CODESolverState &state,int &n,int &m, - int &i,int &j,int &k,int &klimit, - bool &gridpoint,double &xc,double &v, - double &h,double &h2,double &err, - double &maxgrowpow) - { -//--- truncate step if needed (beyond right boundary). -//--- determine should we store X or not - if(xc+h>=state.m_xg[i]) - { - h=state.m_xg[i]-xc; - gridpoint=true; - } - else - gridpoint=false; -//--- Update error scale maximums -//--- These maximums are initialized by zeros, -//--- then updated every iterations. - for(j=0;j<=n-1;j++) - state.m_escale[j]=MathMax(state.m_escale[j],MathAbs(state.m_yc[j])); -//--- make one step: -//--- 1. calculate all info needed to do step -//--- 2. update errors scale maximums using values/derivatives -//--- obtained during (1) -//--- Take into account that we use scaling of X to reduce task -//--- to the form where x[0] < x[1] < ... < x[n-1]. So X is -//--- replaced by x=xscale*t,and dy/dx=f(y,x) is replaced -//--- by dy/dt=xscale*f(y,xscale*t). - for(int i_=0;i_<=n-1;i_++) - state.m_yn[i_]=state.m_yc[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_yns[i_]=state.m_yc[i_]; - k=0; -//--- function call, return result - return(Func_lbl_8(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ODESolverIteration. Is a product to get | -//| rid of the operator unconditional jump goto | -//+------------------------------------------------------------------+ -static bool CODESolver::Func_lbl_8(CODESolverState &state,int &n,int &m, - int &i,int &j,int &k,int &klimit, - bool &gridpoint,double &xc,double &v, - double &h,double &h2,double &err, - double &maxgrowpow) - { -//--- check - if(k>5) - return(Func_lbl_10(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); -//--- prepare data for the next update of YN/YNS - state.m_x=state.m_xscale*(xc+state.m_rka[k]*h); - for(int i_=0;i_<=n-1;i_++) - state.m_y[i_]=state.m_yc[i_]; -//--- calculation - for(j=0;j<=k-1;j++) - { - v=state.m_rkb[k][j]; - for(int i_=0;i_<=n-1;i_++) - state.m_y[i_]=state.m_y[i_]+v*state.m_rkk[j][i_]; - } - state.m_needdy=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for ODESolverIteration. Is a product to get | -//| rid of the operator unconditional jump goto | -//+------------------------------------------------------------------+ -static bool CODESolver::Func_lbl_10(CODESolverState &state,int &n,int &m, - int &i,int &j,int &k,int &klimit, - bool &gridpoint,double &xc,double &v, - double &h,double &h2,double &err, - double &maxgrowpow) - { -//--- estimate error - err=0; - for(j=0;j<=n-1;j++) - { - //--- check - if(!state.m_fraceps) - { - //--- absolute error is estimated - err=MathMax(err,MathAbs(state.m_yn[j]-state.m_yns[j])); - } - else - { - //--- Relative error is estimated - v=state.m_escale[j]; - //--- check - if(v==0.0) - v=1; - err=MathMax(err,MathAbs(state.m_yn[j]-state.m_yns[j])/v); - } - } -//--- calculate new step,restart if necessary - if(maxgrowpow*err<=state.m_eps) - h2=m_odesolvermaxgrow*h; - else - h2=h*MathPow(state.m_eps/err,0.2); -//--- check - if(h2state.m_eps) - { - h=h2; - //--- begin inner iteration - return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//--- advance position - xc=xc+h; - for(int i_=0;i_<=n-1;i_++) - state.m_yc[i_]=state.m_yn[i_]; -//--- update H - h=h2; -//--- break on grid point - if(gridpoint) - { - //--- save result - for(int i_=0;i_<=n-1;i_++) - state.m_ytbl[i].Set(i_,state.m_yc[i_]); - i=i+1; - //--- check - if(i>m-1) - { - state.m_repterminationtype=1; - return(false); - } - //--- begin inner iteration - return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//--- begin inner iteration - return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/fasttransforms.mqh b/Include/Math/Alglib/fasttransforms.mqh deleted file mode 100644 index e53c6a7..0000000 --- a/Include/Math/Alglib/fasttransforms.mqh +++ /dev/null @@ -1,2418 +0,0 @@ -//+------------------------------------------------------------------+ -//| fasttransforms.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "complex.mqh" -#include "alglibinternal.mqh" -//+------------------------------------------------------------------+ -//| Fast Fourier Transform | -//+------------------------------------------------------------------+ -class CFastFourierTransform - { -public: - CFastFourierTransform(void); - ~CFastFourierTransform(void); - - static void FFTC1D(al_complex &a[],const int n); - static void FFTC1DInv(al_complex &a[],const int n); - static void FFTR1D(double &a[],const int n,al_complex &f[]); - static void FFTR1DInv(al_complex &f[],const int n,double &a[]); - static void FFTR1DInternalEven(double &a[],const int n,double &buf[],CFtPlan &plan); - static void FFTR1DInvInternalEven(double &a[],const int n,double &buf[],CFtPlan &plan); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFastFourierTransform::CFastFourierTransform(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFastFourierTransform::~CFastFourierTransform(void) - { - - } -//+------------------------------------------------------------------+ -//| 1-dimensional complex FFT. | -//| Array size N may be arbitrary number (composite or prime). | -//| Composite N's are handled with cache-oblivious variation of a | -//| Cooley-Tukey algorithm. Small prime-factors are transformed using| -//| hard coded codelets (similar to FFTW codelets, but without | -//| low-level optimization), large prime-factors are handled with | -//| Bluestein's algorithm. | -//| Fastests transforms are for smooth N's (prime factors are 2, 3, | -//| 5 only), most fast for powers of 2. When N have prime factors | -//| larger than these, but orders of magnitude smaller than N, | -//| computations will be about 4 times slower than for nearby highly | -//| composite N's. When N itself is prime, speed will be 6 times | -//| lower. | -//| Algorithm has O(N*logN) complexity for any N (composite or | -//| prime). | -//| INPUT PARAMETERS | -//| A - array[0..N-1] - complex function to be transformed | -//| N - problem size | -//| OUTPUT PARAMETERS | -//| A - DFT of a input array, array[0..N-1] | -//| A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), | -//| k = 0..N-1) | -//+------------------------------------------------------------------+ -static void CFastFourierTransform::FFTC1D(al_complex &a[],const int n) - { -//--- create a variable - int i=0; -//--- create array - double buf[]; -//--- object of class - CFtPlan plan; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(a)>=n,__FUNCTION__+": Length(A)0,__FUNCTION__+": incorrect N!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(a)>=n,__FUNCTION__+": Length(A)0,__FUNCTION__+": incorrect N!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(a)>=n,__FUNCTION__+": Length(A)0,__FUNCTION__+": incorrect N!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(f)>=(int)MathFloor((double)n/2.0)+1,__FUNCTION__+": Length(F)0 && n%2==0,__FUNCTION__+": incorrect N!")) - return; -//--- Special cases: -//--- * N=2 -//--- After this block we assume that N is strictly greater than 2 - if(n==2) - { - //--- change values - x=a[0]+a[1]; - y=a[0]-a[1]; - a[0]=x; - a[1]=y; - //--- exit the function - return; - } -//--- even-size real FFT,use reduction to the complex task - n2=n/2; -//--- copy - for(i_=0;i_<=n-1;i_++) - buf[i_]=a[i_]; -//--- function call - CFtBase::FtBaseExecutePlan(buf,0,n2,plan); -//--- change value - a[0]=buf[0]+buf[1]; - for(i=1;i<=n2-1;i++) - { - //--- calculation - idx=2*(i%n2); - hn.re=buf[idx+0]; - hn.im=buf[idx+1]; - idx=2*(n2-i); - hmnc.re=buf[idx+0]; - hmnc.im=-buf[idx+1]; - v.re=-MathSin(-(2*M_PI*i/n)); - v.im=MathCos(-(2*M_PI*i/n)); - v=hn+hmnc-v*(hn-hmnc); - a[2*i+0]=0.5*v.re; - a[2*i+1]=0.5*v.im; - } -//--- change value - a[1]=buf[0]-buf[1]; - } -//+------------------------------------------------------------------+ -//| Internal subroutine. Never call it directly! | -//+------------------------------------------------------------------+ -static void CFastFourierTransform::FFTR1DInvInternalEven(double &a[],const int n, - double &buf[],CFtPlan &plan) - { -//--- create variables - double x=0; - double y=0; - double t=0; - int i=0; - int n2=0; -//--- check - if(!CAp::Assert(n>0 && n%2==0,__FUNCTION__+": incorrect N!")) - return; -//--- Special cases: -//--- * N=2 -//--- After this block we assume that N is strictly greater than 2 - if(n==2) - { - //--- change values - x=0.5*(a[0]+a[1]); - y=0.5*(a[0]-a[1]); - a[0]=x; - a[1]=y; - //--- exit the function - return; - } -//--- inverse real FFT is reduced to the inverse real FHT, -//--- which is reduced to the forward real FHT, -//--- which is reduced to the forward real FFT. -//--- Don't worry,it is really compact and efficient reduction :) - n2=n/2; - buf[0]=a[0]; -//--- calculation - for(i=1;i<=n2-1;i++) - { - x=a[2*i+0]; - y=a[2*i+1]; - buf[i]=x-y; - buf[n-i]=x+y; - } - buf[n2]=a[1]; -//--- function call - FFTR1DInternalEven(buf,n,a,plan); -//--- change values - a[0]=buf[0]/n; - t=1.0/(double)n; -//--- calculation - for(i=1;i<=n2-1;i++) - { - x=buf[2*i+0]; - y=buf[2*i+1]; - a[i]=t*(x-y); - a[n-i]=t*(x+y); - } -//--- change value - a[n2]=buf[1]/n; - } -//+------------------------------------------------------------------+ -//| Convolution class | -//+------------------------------------------------------------------+ -class CConv - { -public: - //--- constructor, destructor - CConv(void); - ~CConv(void); - //--- methods - static void ConvC1D(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvC1DInv(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvC1DCircular(al_complex &s[],const int m,al_complex &r[],const int n,al_complex &c[]); - static void ConvC1DCircularInv(al_complex &a[],const int m,al_complex &b[],const int n,al_complex &r[]); - static void ConvR1D(double &a[],const int m,double &b[],const int n,double &r[]); - static void ConvR1DInv(double &a[],const int m,double &b[],const int n,double &r[]); - static void ConvR1DCircular(double &s[],const int m,double &r[],const int n,double &c[]); - static void ConvR1DCircularInv(double &a[],const int m,double &b[],const int n,double &r[]); - static void ConvC1DX(al_complex &a[],const int m,al_complex &b[],const int n,const bool circular,int alg,int q,al_complex &r[]); - static void ConvR1DX(double &a[],const int m,double &b[],const int n,const bool circular,int alg,int q,double &r[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CConv::CConv(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CConv::~CConv(void) - { - - } -//+------------------------------------------------------------------+ -//| 1-dimensional complex convolution. | -//| For given A/B returns conv(A,B) (non-circular). Subroutine can | -//| automatically choose between three implementations: | -//| straightforward O(M*N) formula for very small N (or M), | -//| significantly larger than min(M,N), but O(M*N) algorithm is too | -//| slow, and general FFT-based formula for cases where two previois | -//| algorithms are too slow. | -//| Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. | -//| INPUT PARAMETERS | -//| A - array[0..M-1] - complex function to be transformed | -//| M - problem size | -//| B - array[0..N-1] - complex function to be transformed | -//| N - problem size | -//| OUTPUT PARAMETERS | -//| R - convolution: A*B. array[0..N+M-2]. | -//| NOTE: | -//| It is assumed that A is zero at T<0, B is zero too. If one or| -//| both functions have non-zero values at negative T's, you can | -//| still use this subroutine - just shift its result | -//| correspondingly. | -//+------------------------------------------------------------------+ -static void CConv::ConvC1D(al_complex &a[],const int m,al_complex &b[],const int n, - al_complex &r[]) - { -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer that B. - if(m0 && m>0) && n<=m,__FUNCTION__+": incorrect N or M!")) - return; -//--- function call - p=CFtBase::FtBaseFindSmooth(m); - CFtBase::FtBaseGenerateComplexFFtPlan(p,plan); -//--- allocation - ArrayResizeAL(buf,2*p); -//--- copy - for(i=0;i<=m-1;i++) - { - buf[2*i+0]=a[i].re; - buf[2*i+1]=a[i].im; - } -//--- make zero - for(i=m;i<=p-1;i++) - { - buf[2*i+0]=0; - buf[2*i+1]=0; - } -//--- allocation - ArrayResizeAL(buf2,2*p); -//--- copy - for(i=0;i<=n-1;i++) - { - buf2[2*i+0]=b[i].re; - buf2[2*i+1]=b[i].im; - } -//--- make zero - for(i=n;i<=p-1;i++) - { - buf2[2*i+0]=0; - buf2[2*i+1]=0; - } -//--- function call - CFtBase::FtBaseExecutePlan(buf,0,p,plan); - CFtBase::FtBaseExecutePlan(buf2,0,p,plan); -//--- calculation - for(i=0;i<=p-1;i++) - { - c1.re=buf[2*i+0]; - c1.im=buf[2*i+1]; - c2.re=buf2[2*i+0]; - c2.im=buf2[2*i+1]; - c3=c1/c2; - buf[2*i+0]=c3.re; - buf[2*i+1]=-c3.im; - } -//--- function call - CFtBase::FtBaseExecutePlan(buf,0,p,plan); - t=1.0/(double)p; -//--- allocation - ArrayResizeAL(r,m-n+1); -//--- change values - for(i=0;i<=m-n;i++) - { - r[i].re=t*buf[2*i+0]; - r[i].im=-(t*buf[2*i+1]); - } - } -//+------------------------------------------------------------------+ -//| 1-dimensional circular complex convolution. | -//| For given S/R returns conv(S,R) (circular). Algorithm has | -//| linearithmic complexity for any M/N. | -//| IMPORTANT: normal convolution is commutative, i.e. it is | -//| symmetric - conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One | -//| function - S - is a signal, periodic function, and another - R - | -//| is a response, non-periodic function with limited length. | -//| INPUT PARAMETERS | -//| S - array[0..M-1] - complex periodic signal | -//| M - problem size | -//| B - array[0..N-1] - complex non-periodic response | -//| N - problem size | -//| OUTPUT PARAMETERS | -//| R - convolution: A*B. array[0..M-1]. | -//| NOTE: | -//| It is assumed that B is zero at T<0. If it has non-zero | -//| values at negative T's, you can still use this subroutine - just | -//| shift its result correspondingly. | -//+------------------------------------------------------------------+ -static void CConv::ConvC1DCircular(al_complex &s[],const int m,al_complex &r[], - const int n,al_complex &c[]) - { -//--- create variables - int i1=0; - int i2=0; - int j2=0; - int i_=0; - int i1_=0; -//--- create array - al_complex buf[]; -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer that B. - if(m0 && m>0) && n<=m,__FUNCTION__+": incorrect N or M!")) - return; -//--- function call - p=CFtBase::FtBaseFindSmoothEven(m); -//--- allocation - ArrayResizeAL(buf,p); -//--- copy - for(i_=0;i_<=m-1;i_++) - buf[i_]=a[i_]; -//--- make zero - for(i=m;i<=p-1;i++) - buf[i]=0; -//--- allocation - ArrayResizeAL(buf2,p); - for(i_=0;i_<=n-1;i_++) - buf2[i_]=b[i_]; -//--- make zero - for(i=n;i<=p-1;i++) - buf2[i]=0; -//--- allocation - ArrayResizeAL(buf3,p); -//--- function call - CFtBase::FtBaseGenerateComplexFFtPlan(p/2,plan); -//--- function call - CFastFourierTransform::FFTR1DInternalEven(buf,p,buf3,plan); -//--- function call - CFastFourierTransform::FFTR1DInternalEven(buf2,p,buf3,plan); -//--- change values - buf[0]=buf[0]/buf2[0]; - buf[1]=buf[1]/buf2[1]; -//--- calculation - for(i=1;i<=p/2-1;i++) - { - c1.re=buf[2*i+0]; - c1.im=buf[2*i+1]; - c2.re=buf2[2*i+0]; - c2.im=buf2[2*i+1]; - c3=c1/c2; - buf[2*i+0]=c3.re; - buf[2*i+1]=c3.im; - } -//--- function call - CFastFourierTransform::FFTR1DInvInternalEven(buf,p,buf3,plan); -//--- allocation - ArrayResizeAL(r,m-n+1); -//--- copy - for(i_=0;i_<=m-n;i_++) - r[i_]=buf[i_]; - } -//+------------------------------------------------------------------+ -//| 1-dimensional circular real convolution. | -//| Analogous to ConvC1DCircular(), see ConvC1DCircular() comments | -//| for more details. | -//| INPUT PARAMETERS | -//| S - array[0..M-1] - real signal | -//| M - problem size | -//| B - array[0..N-1] - real response | -//| N - problem size | -//| OUTPUT PARAMETERS | -//| R - convolution: A*B. array[0..M-1]. | -//| NOTE: | -//| It is assumed that B is zero at T<0. If it has non-zero | -//| values at negative T's, you can still use this subroutine - just | -//| shift its result correspondingly. | -//+------------------------------------------------------------------+ -static void CConv::ConvR1DCircular(double &s[],const int m,double &r[], - const int n,double &c[]) - { -//--- create variables - int i1=0; - int i2=0; - int j2=0; - int i_=0; - int i1_=0; -//--- create array - double buf[]; -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- check - if(!CAp::Assert(n<=m,__FUNCTION__+": N0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- check - if(!CAp::Assert(n<=m,__FUNCTION__+": N2 - we should call small case code otherwise - if(alg==1) - { - //--- check - if(!CAp::Assert(m+n-1>2,__FUNCTION__+": internal error!")) - return; - //--- check - if((circular && CFtBase::FtBaseIsSmooth(m)) && m%2==0) - { - //--- special code for circular convolution with smooth even M - ArrayResizeAL(buf,m); - for(i_=0;i_<=m-1;i_++) - buf[i_]=a[i_]; - //--- allocation - ArrayResizeAL(buf2,m); - for(i_=0;i_<=n-1;i_++) - buf2[i_]=b[i_]; - for(i=n;i<=m-1;i++) - buf2[i]=0; - //--- allocation - ArrayResizeAL(buf3,m); - //--- function call - CFtBase::FtBaseGenerateComplexFFtPlan(m/2,plan); - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf,m,buf3,plan); - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf2,m,buf3,plan); - //--- change values - buf[0]=buf[0]*buf2[0]; - buf[1]=buf[1]*buf2[1]; - //--- calculation - for(i=1;i<=m/2-1;i++) - { - ax=buf[2*i+0]; - ay=buf[2*i+1]; - bx=buf2[2*i+0]; - by=buf2[2*i+1]; - tx=ax*bx-ay*by; - ty=ax*by+ay*bx; - buf[2*i+0]=tx; - buf[2*i+1]=ty; - } - //--- function call - CFastFourierTransform::FFTR1DInvInternalEven(buf,m,buf3,plan); - //--- allocation - ArrayResizeAL(r,m); - //--- copy - for(i_=0;i_<=m-1;i_++) - r[i_]=buf[i_]; - } - else - { - //--- M is non-smooth or non-even,general code (circular/non-circular): - //--- * first part is the same for circular and non-circular - //--- convolutions. zero padding,FFTs,inverse FFTs - //--- * second part differs: - //--- * for non-circular convolution we just copy array - //--- * for circular convolution we add array tail to its head - p=CFtBase::FtBaseFindSmoothEven(m+n-1); - //--- allocation - ArrayResizeAL(buf,p); - for(i_=0;i_<=m-1;i_++) - buf[i_]=a[i_]; - for(i=m;i<=p-1;i++) - buf[i]=0; - //--- allocation - ArrayResizeAL(buf2,p); - for(i_=0;i_<=n-1;i_++) - buf2[i_]=b[i_]; - for(i=n;i<=p-1;i++) - buf2[i]=0; - //--- allocation - ArrayResizeAL(buf3,p); - //--- function call - CFtBase::FtBaseGenerateComplexFFtPlan(p/2,plan); - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf,p,buf3,plan); - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf2,p,buf3,plan); - //--- change values - buf[0]=buf[0]*buf2[0]; - buf[1]=buf[1]*buf2[1]; - //--- calculation - for(i=1;i<=p/2-1;i++) - { - ax=buf[2*i+0]; - ay=buf[2*i+1]; - bx=buf2[2*i+0]; - by=buf2[2*i+1]; - tx=ax*bx-ay*by; - ty=ax*by+ay*bx; - buf[2*i+0]=tx; - buf[2*i+1]=ty; - } - //--- function call - CFastFourierTransform::FFTR1DInvInternalEven(buf,p,buf3,plan); - //--- check - if(circular) - { - //--- circular,add tail to head - ArrayResizeAL(r,m); - for(i_=0;i_<=m-1;i_++) - r[i_]=buf[i_]; - //--- check - if(n>=2) - { - i1_=m; - for(i_=0;i_<=n-2;i_++) - r[i_]=r[i_]+buf[i_+i1_]; - } - } - else - { - //--- non-circular,just copy - ArrayResizeAL(r,m+n-1); - for(i_=0;i_<=m+n-2;i_++) - r[i_]=buf[i_]; - } - } - //--- exit the function - return; - } -//--- overlap-add method - if(alg==2) - { - //--- check - if(!CAp::Assert((q+n-1)%2==0,__FUNCTION__+": internal error!")) - return; - //--- allocation - ArrayResizeAL(buf,q+n-1); - ArrayResizeAL(buf2,q+n-1); - ArrayResizeAL(buf3,q+n-1); - //--- function call - CFtBase::FtBaseGenerateComplexFFtPlan((q+n-1)/2,plan); - //--- prepare R - if(circular) - { - //--- allocation - ArrayResizeAL(r,m); - for(i=0;i<=m-1;i++) - r[i]=0; - } - else - { - //--- allocation - ArrayResizeAL(r,m+n-1); - for(i=0;i<=m+n-2;i++) - r[i]=0; - } - //--- pre-calculated FFT(B) - for(i_=0;i_<=n-1;i_++) - buf2[i_]=b[i_]; - for(j=n;j<=q+n-2;j++) - buf2[j]=0; - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf2,q+n-1,buf3,plan); - //--- main overlap-add cycle - i=0; - //--- calculation - while(i<=m-1) - { - p=MathMin(q,m-i); - i1_=i; - //--- copy - for(i_=0;i_<=p-1;i_++) - buf[i_]=a[i_+i1_]; - //--- make zero - for(j=p;j<=q+n-2;j++) - buf[j]=0; - //--- function call - CFastFourierTransform::FFTR1DInternalEven(buf,q+n-1,buf3,plan); - //--- change values - buf[0]=buf[0]*buf2[0]; - buf[1]=buf[1]*buf2[1]; - //--- calculation - for(j=1;j<=(q+n-1)/2-1;j++) - { - ax=buf[2*j+0]; - ay=buf[2*j+1]; - bx=buf2[2*j+0]; - by=buf2[2*j+1]; - tx=ax*bx-ay*by; - ty=ax*by+ay*bx; - buf[2*j+0]=tx; - buf[2*j+1]=ty; - } - //--- function call - CFastFourierTransform::FFTR1DInvInternalEven(buf,q+n-1,buf3,plan); - //--- check - if(circular) - { - j1=MathMin(i+p+n-2,m-1)-i; - j2=j1+1; - } - else - { - j1=p+n-2; - j2=j1+1; - } - //--- change values - i1_=-i; - for(i_=i;i_<=i+j1;i_++) - r[i_]=r[i_]+buf[i_+i1_]; - //--- check - if(p+n-2>=j2) - { - i1_=j2; - for(i_=0;i_<=p+n-2-j2;i_++) - r[i_]=r[i_]+buf[i_+i1_]; - } - i=i+p; - } - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| Cross-correlation class | -//+------------------------------------------------------------------+ -class CCorr - { -public: - //--- constructor, destructor - CCorr(void); - ~CCorr(void); - //--- methods - static void CorrC1D(al_complex &signal[],const int n,al_complex &pattern[],const int m,al_complex &r[]); - static void CorrC1DCircular(al_complex &signal[],const int m,al_complex &pattern[],const int n,al_complex &c[]); - static void CorrR1D(double &signal[],const int n,double &pattern[],const int m,double &r[]); - static void CorrR1DCircular(double &signal[],const int m,double &pattern[],const int n,double &c[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CCorr::CCorr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCorr::~CCorr(void) - { - - } -//+------------------------------------------------------------------+ -//| 1-dimensional complex cross-correlation. | -//| For given Pattern/Signal returns corr(Pattern,Signal) | -//| (non-circular). | -//| Correlation is calculated using reduction to convolution. | -//| Algorithm with max(N,N)*log(max(N,N)) complexity is used (see | -//| ConvC1D() for more info about performance). | -//| IMPORTANT: | -//| for historical reasons subroutine accepts its parameters in | -//| reversed order: CorrC1D(Signal, Pattern) = Pattern x Signal | -//| (using traditional definition of cross-correlation, denoting | -//| cross-correlation as "x"). | -//| INPUT PARAMETERS | -//| Signal - array[0..N-1] - complex function to be | -//| transformed, signal containing pattern | -//| N - problem size | -//| Pattern - array[0..M-1] - complex function to be | -//| transformed, pattern to search withing signal | -//| M - problem size | -//| OUTPUT PARAMETERS | -//| R - cross-correlation, array[0..N+M-2]: | -//| * positive lags are stored in R[0..N-1], | -//| R[i] = sum(conj(pattern[j])*signal[i+j] | -//| * negative lags are stored in R[N..N+M-2], | -//| R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] | -//| NOTE: | -//| It is assumed that pattern domain is [0..M-1]. If Pattern is | -//| non-zero on [-K..M-1], you can still use this subroutine, just | -//| shift result by K. | -//+------------------------------------------------------------------+ -static void CCorr::CorrC1D(al_complex &signal[],const int n,al_complex &pattern[], - const int m,al_complex &r[]) - { -//--- create variables - int i=0; - int i_=0; - int i1_=0; -//--- create arrays - al_complex p[]; - al_complex b[]; -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- allocation - ArrayResizeAL(p,m); - for(i=0;i<=m-1;i++) - p[m-1-i]=CMath::Conj(pattern[i]); -//--- function call - CConv::ConvC1D(p,m,signal,n,b); -//--- allocation - ArrayResizeAL(r,m+n-1); - i1_=m-1; - for(i_=0;i_<=n-1;i_++) - r[i_]=b[i_+i1_]; -//--- check - if(m+n-2>=n) - { - i1_=-n; - for(i_=n;i_<=m+n-2;i_++) - r[i_]=b[i_+i1_]; - } - } -//+------------------------------------------------------------------+ -//| 1-dimensional circular complex cross-correlation. | -//| For given Pattern/Signal returns corr(Pattern,Signal) (circular).| -//| Algorithm has linearithmic complexity for any M/N. | -//| IMPORTANT: | -//| for historical reasons subroutine accepts its parameters in | -//| reversed order: CorrC1DCircular(Signal, Pattern) = Pattern x | -//| Signal (using traditional definition of cross-correlation, | -//| denoting cross-correlation as "x"). | -//| INPUT PARAMETERS | -//| Signal - array[0..N-1] - complex function to be | -//| transformed, periodic signal containing pattern | -//| N - problem size | -//| Pattern - array[0..M-1] - complex function to be | -//| transformed, non-periodic pattern to search | -//| withing signal | -//| M - problem size | -//| OUTPUT PARAMETERS | -//| R - convolution: A*B. array[0..M-1]. | -//+------------------------------------------------------------------+ -static void CCorr::CorrC1DCircular(al_complex &signal[],const int m,al_complex &pattern[], - const int n,al_complex &c[]) - { -//--- create variables - int i1=0; - int i2=0; - int i=0; - int j2=0; - int i_=0; - int i1_=0; -//--- create arrays - al_complex p[]; - al_complex b[]; -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- allocation - ArrayResizeAL(p,m); -//--- copy - for(i=0;i<=m-1;i++) - p[m-1-i]=pattern[i]; -//--- function call - CConv::ConvR1D(p,m,signal,n,b); -//--- allocation - ArrayResizeAL(r,m+n-1); - i1_=m-1; -//--- copy - for(i_=0;i_<=n-1;i_++) - r[i_]=b[i_+i1_]; -//--- check - if(m+n-2>=n) - { - i1_=-n; - for(i_=n;i_<=m+n-2;i_++) - r[i_]=b[i_+i1_]; - } - } -//+------------------------------------------------------------------+ -//| 1-dimensional circular real cross-correlation. | -//| For given Pattern/Signal returns corr(Pattern,Signal) (circular).| -//| Algorithm has linearithmic complexity for any M/N. | -//| IMPORTANT: | -//| for historical reasons subroutine accepts its parameters in | -//| reversed order: CorrR1DCircular(Signal, Pattern) = Pattern x | -//| Signal (using traditional definition of cross-correlation, | -//| denoting cross-correlation as "x"). | -//| INPUT PARAMETERS | -//| Signal - array[0..N-1] - real function to be transformed, | -//| periodic signal containing pattern | -//| N - problem size | -//| Pattern - array[0..M-1] - real function to be transformed, | -//| non-periodic pattern to search withing signal | -//| M - problem size | -//| OUTPUT PARAMETERS | -//| R - convolution: A*B. array[0..M-1]. | -//+------------------------------------------------------------------+ -static void CCorr::CorrR1DCircular(double &signal[],const int m,double &pattern[], - const int n,double &c[]) - { -//--- create variables - int i1=0; - int i2=0; - int i=0; - int j2=0; - int i_=0; - int i1_=0; -//--- create arrays - double p[]; - double b[]; -//--- check - if(!CAp::Assert(n>0 && m>0,__FUNCTION__+": incorrect N or M!")) - return; -//--- normalize task: make M>=N, -//--- so A will be longer (at least - not shorter) that B. - if(m0,__FUNCTION__+": incorrect N!")) - return; -//--- Special case: N=1,FHT is just identity transform. -//--- After this block we assume that N is strictly greater than 1. - if(n==1) - return; -//--- Reduce FHt to real FFT - CFastFourierTransform::FFTR1D(a,n,fa); -//--- change values - for(i=0;i<=n-1;i++) - a[i]=fa[i].re-fa[i].im; - } -//+------------------------------------------------------------------+ -//| 1-dimensional inverse FHT. | -//| Algorithm has O(N*logN) complexity for any N (composite or prime)| -//| INPUT PARAMETERS | -//| A - array[0..N-1] - complex array to be transformed | -//| N - problem size | -//| OUTPUT PARAMETERS | -//| A - inverse FHT of a input array, array[0..N-1] | -//+------------------------------------------------------------------+ -static void CFastHartleyTransform::FHTR1DInv(double &a[],const int n) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- Special case: N=1,iFHT is just identity transform. -//--- After this block we assume that N is strictly greater than 1. - if(n==1) - return; -//--- Inverse FHT can be expressed in terms of the FHT as -//--- invfht(x)=fht(x)/N - FHTR1D(a,n); -//--- change values - for(i=0;i<=n-1;i++) - a[i]=a[i]/n; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/integration.mqh b/Include/Math/Alglib/integration.mqh deleted file mode 100644 index a052c3ec342cf8ff43f0ea87e8392f93011ab8aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249418 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 diff --git a/Include/Math/Alglib/interpolation.mqh b/Include/Math/Alglib/interpolation.mqh deleted file mode 100644 index 1a09b5d..0000000 --- a/Include/Math/Alglib/interpolation.mqh +++ /dev/null @@ -1,13407 +0,0 @@ -//+------------------------------------------------------------------+ -//| interpolation.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "alglibmisc.mqh" -#include "optimization.mqh" -#include "solvers.mqh" -#include "integration.mqh" -//+------------------------------------------------------------------+ -//| IDW interpolant. | -//+------------------------------------------------------------------+ -class CIDWInterpolant - { -public: - int m_n; - int m_nx; - int m_d; - double m_r; - int m_nw; - CKDTree m_tree; - int m_modeltype; - int m_debugsolverfailures; - double m_debugworstrcond; - double m_debugbestrcond; - //--- arrays - double m_xbuf[]; - int m_tbuf[]; - double m_rbuf[]; - //--- matrices - CMatrixDouble m_q; - CMatrixDouble m_xybuf; - -public: - CIDWInterpolant(void); - ~CIDWInterpolant(void); - - void Copy(CIDWInterpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIDWInterpolant::CIDWInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIDWInterpolant::~CIDWInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CIDWInterpolant::Copy(CIDWInterpolant &obj) - { -//--- copy variables - m_n=obj.m_n; - m_nx=obj.m_nx; - m_d=obj.m_d; - m_r=obj.m_r; - m_nw=obj.m_nw; - m_modeltype=obj.m_modeltype; - m_debugsolverfailures=obj.m_debugsolverfailures; - m_debugworstrcond=obj.m_debugworstrcond; - m_debugbestrcond=obj.m_debugbestrcond; - m_tree.Copy(obj.m_tree); -//--- copy arrays - ArrayCopy(m_xbuf,obj.m_xbuf); - ArrayCopy(m_tbuf,obj.m_tbuf); - ArrayCopy(m_rbuf,obj.m_rbuf); -//--- copy matrices - m_q=obj.m_q; - m_xybuf=obj.m_xybuf; - } -//+------------------------------------------------------------------+ -//| IDW interpolant. | -//+------------------------------------------------------------------+ -class CIDWInterpolantShell - { -private: - CIDWInterpolant m_innerobj; -public: - //--- constructors, destructor - CIDWInterpolantShell(void); - CIDWInterpolantShell(CIDWInterpolant &obj); - ~CIDWInterpolantShell(void); - //--- method - CIDWInterpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIDWInterpolantShell::CIDWInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CIDWInterpolantShell::CIDWInterpolantShell(CIDWInterpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIDWInterpolantShell::~CIDWInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CIDWInterpolant *CIDWInterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Inverse distance weighting interpolation | -//+------------------------------------------------------------------+ -class CIDWInt - { -private: - //--- private methods - static double IDWCalcQ(CIDWInterpolant &z,double &x[],const int k); - static void IDWInit1(const int n,const int nx,const int d,int nq,int nw,CIDWInterpolant &z); - static void IDWInternalSolver(double &y[],double &w[],CMatrixDouble &fmatrix,double &temp[],const int n,const int m,int &info,double &x[],double &taskrcond); -public: - //--- class constants - static const double m_idwqfactor; - static const int m_idwkmin; - //--- constructor, destructor - CIDWInt(void); - ~CIDWInt(void); - //--- public methods - static double IDWCalc(CIDWInterpolant &z,double &x[]); - static void IDWBuildModifiedShepard(CMatrixDouble &xy,const int n,const int nx,const int d,int nq,int nw,CIDWInterpolant &z); - static void IDWBuildModifiedShepardR(CMatrixDouble &xy,const int n,const int nx,const double r,CIDWInterpolant &z); - static void IDWBuildNoisy(CMatrixDouble &xy,const int n,const int nx,const int d,int nq,int nw,CIDWInterpolant &z); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CIDWInt::m_idwqfactor=1.5; -const int CIDWInt::m_idwkmin=5; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIDWInt::CIDWInt(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIDWInt::~CIDWInt(void) - { - - } -//+------------------------------------------------------------------+ -//| IDW interpolation | -//| INPUT PARAMETERS: | -//| Z - IDW interpolant built with one of model building | -//| subroutines. | -//| X - array[0..NX-1], interpolation point | -//| Result: | -//| IDW interpolant Z(X) | -//+------------------------------------------------------------------+ -static double CIDWInt::IDWCalc(CIDWInterpolant &z,double &x[]) - { -//--- create variables - double result=0; - int nx=0; - int i=0; - int k=0; - double r=0; - double s=0; - double w=0; - double v1=0; - double v2=0; - double d0=0; - double di=0; -//--- these initializers are not really necessary, -//--- but without them compiler complains about uninitialized locals - k=0; -//--- Query - if(z.m_modeltype==0) - { - //--- NQ/NW-based model - nx=z.m_nx; - k=CNearestNeighbor::KDTreeQueryKNN(z.m_tree,x,z.m_nw,true); - //--- function call - CNearestNeighbor::KDTreeQueryResultsDistances(z.m_tree,z.m_rbuf); - //--- function call - CNearestNeighbor::KDTreeQueryResultsTags(z.m_tree,z.m_tbuf); - } - if(z.m_modeltype==1) - { - //--- R-based model - nx=z.m_nx; - k=CNearestNeighbor::KDTreeQueryRNN(z.m_tree,x,z.m_r,true); - //--- function call - CNearestNeighbor::KDTreeQueryResultsDistances(z.m_tree,z.m_rbuf); - //--- function call - CNearestNeighbor::KDTreeQueryResultsTags(z.m_tree,z.m_tbuf); - if(kd0 -//--- NOTE 2: self-match is USED for this query -//--- NOTE 3: last point almost always gain zero weight,but it MUST -//--- be used for fitting because sometimes it will gain NON-ZERO -//--- weight - for example,when all distances are equal. - r=z.m_rbuf[k-1]; - d0=z.m_rbuf[0]; - result=0; - s=0; - for(i=0;i<=k-1;i++) - { - di=z.m_rbuf[i]; - //--- check - if(di==d0) - { - //--- distance is equal to shortest,set it 1.0 - //--- without explicitly calculating (which would give - //--- us same result,but 'll expose us to the risk of - //--- division by zero). - w=1; - } - else - { - //--- use normalized formula - v1=(r-di)/(r-d0); - v2=d0/di; - w=CMath::Sqr(v1*v2); - } - //--- change result - result=result+w*IDWCalcQ(z,x,z.m_tbuf[i]); - s=s+w; - } -//--- return result - return(result/s); - } -//+------------------------------------------------------------------+ -//| IDW interpolant using modified Shepard method for uniform point | -//| distributions. | -//| INPUT PARAMETERS: | -//| XY - X and Y values, array[0..N-1,0..NX]. | -//| First NX columns contain X-values, last column | -//| contain Y-values. | -//| N - number of nodes, N>0. | -//| NX - space dimension, NX>=1. | -//| D - nodal function type, either: | -//| * 0 constant model. Just for demonstration only,| -//| worst model ever. | -//| * 1 linear model, least squares fitting. Simpe | -//| model for datasets too small for quadratic | -//| models | -//| * 2 quadratic model, least squares fitting. | -//| Best model available (if your dataset is | -//| large enough). | -//| * -1 "fast" linear model, use with caution!!! It | -//| is significantly faster than linear/quadratic| -//| and better than constant model. But it is | -//| less robust (especially in the presence of | -//| noise). | -//| NQ - number of points used to calculate nodal functions | -//| (ignored for constant models). NQ should be LARGER | -//| than: | -//| * max(1.5*(1+NX),2^NX+1) for linear model, | -//| * max(3/4*(NX+2)*(NX+1),2^NX+1) for quadratic model. | -//| Values less than this threshold will be silently | -//| increased. | -//| NW - number of points used to calculate weights and to | -//| interpolate. Required: >=2^NX+1, values less than | -//| this threshold will be silently increased. | -//| Recommended value: about 2*NQ | -//| OUTPUT PARAMETERS: | -//| Z - IDW interpolant. | -//| NOTES: | -//| * best results are obtained with quadratic models, worst - with| -//| constant models | -//| * when N is large, NQ and NW must be significantly smaller than| -//| N both to obtain optimal performance and to obtain optimal | -//| accuracy. In 2 or 3-dimensional tasks NQ=15 and NW=25 are | -//| good values to start with. | -//| * NQ and NW may be greater than N. In such cases they will be | -//| automatically decreased. | -//| * this subroutine is always succeeds (as long as correct | -//| parameters are passed). | -//| * see 'Multivariate Interpolation of Large Sets of Scattered | -//| Data' by Robert J. Renka for more information on this | -//| algorithm. | -//| * this subroutine assumes that point distribution is uniform at| -//| the small scales. If it isn't - for example, points are | -//| concentrated along "lines", but "lines" distribution is | -//| uniform at the larger scale - then you should use | -//| IDWBuildModifiedShepardR() | -//+------------------------------------------------------------------+ -static void CIDWInt::IDWBuildModifiedShepard(CMatrixDouble &xy,const int n, - const int nx,const int d, - int nq,int nw,CIDWInterpolant &z) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int j2=0; - int j3=0; - double v=0; - double r=0; - double s=0; - double d0=0; - double di=0; - double v1=0; - double v2=0; - int nc=0; - int offs=0; - int info=0; - double taskrcond=0; - int i_=0; -//--- create arrays - double x[]; - double qrbuf[]; - double y[]; - double w[]; - double qsol[]; - double temp[]; - int tags[]; -//--- create matrix - CMatrixDouble qxybuf; - CMatrixDouble fmatrix; -//--- these initializers are not really necessary, -//--- but without them compiler complains about uninitialized locals - nc=0; -//--- assertions - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(nx>=1,__FUNCTION__+": NX<1!")) - return; -//--- check - if(!CAp::Assert(d>=-1 && d<=2,__FUNCTION__+": D<>-1 and D<>0 and D<>1 and D<>2!")) - return; -//--- Correct parameters if needed - if(d==1) - { - nq=MathMax(nq,(int)MathCeil(m_idwqfactor*(1+nx))+1); - nq=MathMax(nq,(int)MathRound(MathPow(2,nx))+1); - } -//--- check - if(d==2) - { - nq=MathMax(nq,(int)MathCeil(m_idwqfactor*(nx+2)*(nx+1)/2)+1); - nq=MathMax(nq,(int)MathRound(MathPow(2,nx))+1); - } -//--- change values - nw=MathMax(nw,(int)MathRound(MathPow(2,nx))+1); - nq=MathMin(nq,n); - nw=MathMin(nw,n); -//--- primary initialization of Z - IDWInit1(n,nx,d,nq,nw,z); - z.m_modeltype=0; -//--- Create KD-tree - ArrayResizeAL(tags,n); - for(i=0;i<=n-1;i++) - tags[i]=i; -//--- function call - CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,1,2,z.m_tree); -//--- build nodal functions - ArrayResizeAL(temp,nq+1); - ArrayResizeAL(x,nx); - ArrayResizeAL(qrbuf,nq); - qxybuf.Resize(nq,nx+1); -//--- check - if(d==-1) - ArrayResizeAL(w,nq); -//--- check - if(d==1) - { - //--- allocation - ArrayResizeAL(y,nq); - ArrayResizeAL(w,nq); - ArrayResizeAL(qsol,nx); - //--- NX for linear members, - //--- 1 for temporary storage - fmatrix.Resize(nq,nx+1); - } -//--- check - if(d==2) - { - //--- allocation - ArrayResizeAL(y,nq); - ArrayResizeAL(w,nq); - ArrayResizeAL(qsol,nx+(int)MathRound(nx*(nx+1)*0.5)); - //--- NX for linear members, - //--- Round(NX*(NX+1)*0.5) for quadratic model, - //--- 1 for temporary storage - fmatrix.Resize(nq,nx+(int)MathRound(nx*(nx+1)*0.5)+1); - } - for(i=0;i<=n-1;i++) - { - //--- Initialize center and function value. - //--- If D=0 it is all what we need - for(i_=0;i_<=nx;i_++) - z.m_q[i].Set(i_,xy[i][i_]); - //--- check - if(d==0) - continue; - //--- calculate weights for linear/quadratic members calculation. - //--- NOTE 1: weights are calculated using NORMALIZED modified - //--- Shepard's formula. Original formula is w(i)=sqr((R-di)/(R*di)), - //--- where di is i-th distance,R is max(di). Modified formula have - //--- following form: - //--- w_mod(i)=1,if di=d0 - //--- w_mod(i)=w(i)/w(0),if di<>d0 - //--- NOTE 2: self-match is NOT used for this query - //--- NOTE 3: last point almost always gain zero weight,but it MUST - //--- be used for fitting because sometimes it will gain NON-ZERO - //--- weight - for example,when all distances are equal. - for(i_=0;i_<=nx-1;i_++) - x[i_]=xy[i][i_]; - k=CNearestNeighbor::KDTreeQueryKNN(z.m_tree,x,nq,false); - //--- function call - CNearestNeighbor::KDTreeQueryResultsXY(z.m_tree,qxybuf); - //--- function call - CNearestNeighbor::KDTreeQueryResultsDistances(z.m_tree,qrbuf); - r=qrbuf[k-1]; - d0=qrbuf[0]; - //--- calculation - for(j=0;j<=k-1;j++) - { - di=qrbuf[j]; - //--- check - if(di==d0) - { - //--- distance is equal to shortest,set it 1.0 - //--- without explicitly calculating (which would give - //--- us same result,but 'll expose us to the risk of - //--- division by zero). - w[j]=1; - } - else - { - //--- use normalized formula - v1=(r-di)/(r-d0); - v2=d0/di; - w[j]=CMath::Sqr(v1*v2); - } - } - //--- calculate linear/quadratic members - if(d==-1) - { - //--- "Fast" linear nodal function calculated using - //--- inverse distance weighting - for(j=0;j<=nx-1;j++) - x[j]=0; - s=0; - //--- calculation - for(j=0;j<=k-1;j++) - { - //--- calculate J-th inverse distance weighted gradient: - //--- grad_k=(y_j-y_k)*(x_j-x_k)/sqr(norm(x_j-x_k)) - //--- grad=sum(wk*grad_k)/sum(w_k) - v=0; - for(j2=0;j2<=nx-1;j2++) - v=v+CMath::Sqr(qxybuf[j][j2]-xy[i][j2]); - //--- Although x_j<>x_k,sqr(norm(x_j-x_k)) may be zero due to - //--- underflow. If it is,we assume than J-th gradient is zero - //--- (i.m_e. don't add anything) - if(v!=0.0) - { - for(j2=0;j2<=nx-1;j2++) - x[j2]=x[j2]+w[j]*(qxybuf[j][nx]-xy[i][nx])*(qxybuf[j][j2]-xy[i][j2])/v; - } - s=s+w[j]; - } - for(j=0;j<=nx-1;j++) - z.m_q[i].Set(nx+1+j,x[j]/s); - } - else - { - //--- Least squares models: build - if(d==1) - { - //--- Linear nodal function calculated using - //--- least squares fitting to its neighbors - for(j=0;j<=k-1;j++) - { - for(j2=0;j2<=nx-1;j2++) - fmatrix[j].Set(j2,qxybuf[j][j2]-xy[i][j2]); - y[j]=qxybuf[j][nx]-xy[i][nx]; - } - nc=nx; - } - //--- check - if(d==2) - { - //--- Quadratic nodal function calculated using - //--- least squares fitting to its neighbors - for(j=0;j<=k-1;j++) - { - offs=0; - for(j2=0;j2<=nx-1;j2++) - { - fmatrix[j].Set(offs,qxybuf[j][j2]-xy[i][j2]); - offs=offs+1; - } - //--- calculation - for(j2=0;j2<=nx-1;j2++) - { - for(j3=j2;j3<=nx-1;j3++) - { - fmatrix[j].Set(offs,(qxybuf[j][j2]-xy[i][j2])*(qxybuf[j][j3]-xy[i][j3])); - offs=offs+1; - } - } - y[j]=qxybuf[j][nx]-xy[i][nx]; - } - nc=nx+(int)MathRound(nx*(nx+1)*0.5); - } - //--- function call - IDWInternalSolver(y,w,fmatrix,temp,k,nc,info,qsol,taskrcond); - //--- Least squares models: copy results - if(info>0) - { - //--- LLS task is solved,copy results - z.m_debugworstrcond=MathMin(z.m_debugworstrcond,taskrcond); - z.m_debugbestrcond=MathMax(z.m_debugbestrcond,taskrcond); - for(j=0;j<=nc-1;j++) - z.m_q[i].Set(nx+1+j,qsol[j]); - } - else - { - //--- Solver failure,very strange,but we will use - //--- zero values to handle it. - z.m_debugsolverfailures=z.m_debugsolverfailures+1; - for(j=0;j<=nc-1;j++) - z.m_q[i].Set(nx+1+j,0); - } - } - } - } -//+------------------------------------------------------------------+ -//| IDW interpolant using modified Shepard method for non-uniform | -//| datasets. | -//| This type of model uses constant nodal functions and interpolates| -//| using all nodes which are closer than user-specified radius R. It| -//| may be used when points distribution is non-uniform at the small | -//| scale, but it is at the distances as large as R. | -//| INPUT PARAMETERS: | -//| XY - X and Y values, array[0..N-1,0..NX]. | -//| First NX columns contain X-values, last column | -//| contain Y-values. | -//| N - number of nodes, N>0. | -//| NX - space dimension, NX>=1. | -//| R - radius, R>0 | -//| OUTPUT PARAMETERS: | -//| Z - IDW interpolant. | -//| NOTES: | -//| * if there is less than IDWKMin points within R-ball, algorithm | -//| selects IDWKMin closest ones, so that continuity properties of | -//| interpolant are preserved even far from points. | -//+------------------------------------------------------------------+ -static void CIDWInt::IDWBuildModifiedShepardR(CMatrixDouble &xy,const int n, - const int nx,const double r, - CIDWInterpolant &z) - { -//--- create variables - int i=0; - int i_=0; -//--- create array - int tags[]; -//--- assertions - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(nx>=1,__FUNCTION__+": NX<1!")) - return; -//--- check - if(!CAp::Assert(r>0.0,__FUNCTION__+": R<=0!")) - return; -//--- primary initialization of Z - IDWInit1(n,nx,0,0,n,z); - z.m_modeltype=1; - z.m_r=r; -//--- Create KD-tree - ArrayResizeAL(tags,n); - for(i=0;i<=n-1;i++) - tags[i]=i; -//--- function call - CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,1,2,z.m_tree); -//--- build nodal functions - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=nx;i_++) - z.m_q[i].Set(i_,xy[i][i_]); - } - } -//+------------------------------------------------------------------+ -//| IDW model for noisy data. | -//| This subroutine may be used to handle noisy data, i.e. data with | -//| noise in OUTPUT values. It differs from IDWBuildModifiedShepard()| -//| in the following aspects: | -//| * nodal functions are not constrained to pass through nodes: | -//| Qi(xi)<>yi, i.e. we have fitting instead of interpolation. | -//| * weights which are used during least squares fitting stage are | -//| all equal to 1.0 (independently of distance) | -//| * "fast"-linear or constant nodal functions are not supported | -//| (either not robust enough or too rigid) | -//| This problem require far more complex tuning than interpolation | -//| problems. | -//| Below you can find some recommendations regarding this problem: | -//| * focus on tuning NQ; it controls noise reduction. As for NW, you| -//| can just make it equal to 2*NQ. | -//| * you can use cross-validation to determine optimal NQ. | -//| * optimal NQ is a result of complex tradeoff between noise level | -//| (more noise = larger NQ required) and underlying function | -//| complexity (given fixed N, larger NQ means smoothing of compex | -//| features in the data). For example, NQ=N will reduce noise to | -//| the minimum level possible, but you will end up with just | -//| constant/linear/quadratic (depending on D) least squares | -//| model for the whole dataset. | -//| INPUT PARAMETERS: | -//| XY - X and Y values, array[0..N-1,0..NX]. | -//| First NX columns contain X-values, last column | -//| contain Y-values. | -//| N - number of nodes, N>0. | -//| NX - space dimension, NX>=1. | -//| D - nodal function degree, either: | -//| * 1 linear model, least squares fitting. Simpe | -//| model for datasets too small for quadratic | -//| models (or for very noisy problems). | -//| * 2 quadratic model, least squares fitting. Best | -//| model available (if your dataset is large | -//| enough). | -//| NQ - number of points used to calculate nodal functions. | -//| NQ should be significantly larger than 1.5 times the | -//| number of coefficients in a nodal function to | -//| overcome effects of noise: | -//| * larger than 1.5*(1+NX) for linear model, | -//| * larger than 3/4*(NX+2)*(NX+1) for quadratic model. | -//| Values less than this threshold will be silently | -//| increased. | -//| NW - number of points used to calculate weights and to | -//| interpolate. Required: >=2^NX+1, values less than | -//| this threshold will be silently increased. | -//| Recommended value: about 2*NQ or larger | -//| OUTPUT PARAMETERS: | -//| Z - IDW inte rpolant. | -//| NOTES: | -//| * best results are obtained with quadratic models, linear | -//| models are not recommended to use unless you are pretty sure | -//| that it is what you want | -//| * this subroutine is always succeeds (as long as correct | -//| parameters are passed). | -//| * see 'Multivariate Interpolation of Large Sets of Scattered | -//| Data' by Robert J. Renka for more information on this | -//| algorithm. | -//+------------------------------------------------------------------+ -static void CIDWInt::IDWBuildNoisy(CMatrixDouble &xy,const int n,const int nx, - const int d,int nq,int nw,CIDWInterpolant &z) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int j2=0; - int j3=0; - double v=0; - int nc=0; - int offs=0; - double taskrcond=0; - int info=0; - int i_=0; -//--- create arrays - double x[]; - double qrbuf[]; - double y[]; - double w[]; - double qsol[]; - int tags[]; - double temp[]; -//--- create matrix - CMatrixDouble qxybuf; - CMatrixDouble fmatrix; -//--- these initializers are not really necessary, -//--- but without them compiler complains about uninitialized locals - nc=0; -//--- assertions - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(nx>=1,__FUNCTION__+": NX<1!")) - return; -//--- check - if(!CAp::Assert(d>=1 && d<=2,__FUNCTION__+": D<>1 and D<>2!")) - return; -//--- Correct parameters if needed - if(d==1) - nq=MathMax(nq,(int)MathCeil(m_idwqfactor*(1+nx))+1); -//--- check - if(d==2) - nq=MathMax(nq,(int)MathCeil(m_idwqfactor*(nx+2)*(nx+1)/2)+1); -//--- change values - nw=MathMax(nw,(int)MathRound(MathPow(2,nx))+1); - nq=MathMin(nq,n); - nw=MathMin(nw,n); -//--- primary initialization of Z - IDWInit1(n,nx,d,nq,nw,z); - z.m_modeltype=0; -//--- Create KD-tree - ArrayResizeAL(tags,n); - for(i=0;i<=n-1;i++) - tags[i]=i; -//--- function call - CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,1,2,z.m_tree); -//--- build nodal functions -//--- (special algorithm for noisy data is used) - ArrayResizeAL(temp,nq+1); - ArrayResizeAL(x,nx); - ArrayResizeAL(qrbuf,nq); - qxybuf.Resize(nq,nx+1); -//--- check - if(d==1) - { - //--- allocation - ArrayResizeAL(y,nq); - ArrayResizeAL(w,nq); - ArrayResizeAL(qsol,1+nx); - //--- 1 for constant member, - //--- NX for linear members, - //--- 1 for temporary storage - fmatrix.Resize(nq,1+nx+1); - } -//--- check - if(d==2) - { - //--- allocation - ArrayResizeAL(y,nq); - ArrayResizeAL(w,nq); - ArrayResizeAL(qsol,1+nx+(int)MathRound(nx*(nx+1)*0.5)); - //--- 1 for constant member, - //--- NX for linear members, - //--- Round(NX*(NX+1)*0.5) for quadratic model, - //--- 1 for temporary storage - fmatrix.Resize(nq,1+nx+(int)MathRound(nx*(nx+1)*0.5)+1); - } -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- Initialize center. - for(i_=0;i_<=nx-1;i_++) - z.m_q[i].Set(i_,xy[i][i_]); - //--- Calculate linear/quadratic members - //--- using least squares fit - //--- NOTE 1: all weight are equal to 1.0 - //--- NOTE 2: self-match is USED for this query - for(i_=0;i_<=nx-1;i_++) - x[i_]=xy[i][i_]; - k=CNearestNeighbor::KDTreeQueryKNN(z.m_tree,x,nq,true); - //--- function call - CNearestNeighbor::KDTreeQueryResultsXY(z.m_tree,qxybuf); - //--- function call - CNearestNeighbor::KDTreeQueryResultsDistances(z.m_tree,qrbuf); - //--- check - if(d==1) - { - //--- Linear nodal function calculated using - //--- least squares fitting to its neighbors - for(j=0;j<=k-1;j++) - { - fmatrix[j].Set(0,1.0); - for(j2=0;j2<=nx-1;j2++) - fmatrix[j].Set(1+j2,qxybuf[j][j2]-xy[i][j2]); - //--- change values - y[j]=qxybuf[j][nx]; - w[j]=1; - } - nc=1+nx; - } - //--- check - if(d==2) - { - //--- Quadratic nodal function calculated using - //--- least squares fitting to its neighbors - for(j=0;j<=k-1;j++) - { - fmatrix[j].Set(0,1); - offs=1; - for(j2=0;j2<=nx-1;j2++) - { - fmatrix[j].Set(offs,qxybuf[j][j2]-xy[i][j2]); - offs=offs+1; - } - //--- calculation - for(j2=0;j2<=nx-1;j2++) - { - for(j3=j2;j3<=nx-1;j3++) - { - fmatrix[j].Set(offs,(qxybuf[j][j2]-xy[i][j2])*(qxybuf[j][j3]-xy[i][j3])); - offs=offs+1; - } - } - //--- change values - y[j]=qxybuf[j][nx]; - w[j]=1; - } - nc=1+nx+(int)MathRound(nx*(nx+1)*0.5); - } - //--- function call - IDWInternalSolver(y,w,fmatrix,temp,k,nc,info,qsol,taskrcond); - //--- Least squares models: copy results - if(info>0) - { - //--- LLS task is solved,copy results - z.m_debugworstrcond=MathMin(z.m_debugworstrcond,taskrcond); - z.m_debugbestrcond=MathMax(z.m_debugbestrcond,taskrcond); - for(j=0;j<=nc-1;j++) - z.m_q[i].Set(nx+j,qsol[j]); - } - else - { - //--- Solver failure,very strange,but we will use - //--- zero values to handle it. - z.m_debugsolverfailures=z.m_debugsolverfailures+1; - v=0; - for(j=0;j<=k-1;j++) - v=v+qxybuf[j][nx]; - z.m_q[i].Set(nx,v/k); - for(j=0;j<=nc-2;j++) - z.m_q[i].Set(nx+1+j,0); - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine: K-th nodal function calculation | -//+------------------------------------------------------------------+ -static double CIDWInt::IDWCalcQ(CIDWInterpolant &z,double &x[],const int k) - { -//--- create variables - double result=0; - int nx=0; - int i=0; - int j=0; - int offs=0; -//--- initialization - nx=z.m_nx; -//--- constant member - result=z.m_q[k][nx]; -//--- linear members - if(z.m_d>=1) - { - for(i=0;i<=nx-1;i++) - result=result+z.m_q[k][nx+1+i]*(x[i]-z.m_q[k][i]); - } -//--- quadratic members - if(z.m_d>=2) - { - offs=nx+1+nx; - for(i=0;i<=nx-1;i++) - { - for(j=i;j<=nx-1;j++) - { - result=result+z.m_q[k][offs]*(x[i]-z.m_q[k][i])*(x[j]-z.m_q[k][j]); - offs=offs+1; - } - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Initialization of internal structures. | -//| It assumes correctness of all parameters. | -//+------------------------------------------------------------------+ -static void CIDWInt::IDWInit1(const int n,const int nx,const int d, - int nq,int nw,CIDWInterpolant &z) - { -//--- initialization - z.m_debugsolverfailures=0; - z.m_debugworstrcond=1.0; - z.m_debugbestrcond=0; - z.m_n=n; - z.m_nx=nx; - z.m_d=0; -//--- check - if(d==1) - z.m_d=1; -//--- check - if(d==2) - z.m_d=2; -//--- check - if(d==-1) - z.m_d=1; - z.m_nw=nw; -//--- check - if(d==-1) - z.m_q.Resize(n,2*nx+1); -//--- check - if(d==0) - z.m_q.Resize(n,nx+1); -//--- check - if(d==1) - z.m_q.Resize(n,2*nx+1); -//--- check - if(d==2) - z.m_q.Resize(n,nx+1+nx+(int)MathRound(nx*(nx+1)*0.5)); -//--- allocation - ArrayResizeAL(z.m_tbuf,nw); - ArrayResizeAL(z.m_rbuf,nw); - z.m_xybuf.Resize(nw,nx+1); - ArrayResizeAL(z.m_xbuf,nx); - } -//+------------------------------------------------------------------+ -//| Linear least squares solver for small tasks. | -//| Works faster than standard ALGLIB solver in non-degenerate | -//| cases (due to absense of internal allocations and optimized | -//| row/colums). In degenerate cases it calls standard solver, which| -//| results in small performance penalty associated with preliminary | -//| steps. | -//| INPUT PARAMETERS: | -//| Y array[0..N-1] | -//| W array[0..N-1] | -//| FMatrix array[0..N-1,0..M], have additional column for | -//| temporary values | -//| Temp array[0..N] | -//+------------------------------------------------------------------+ -static void CIDWInt::IDWInternalSolver(double &y[],double &w[],CMatrixDouble &fmatrix, - double &temp[],const int n,const int m, - int &info,double &x[],double &taskrcond) - { -//--- create variables - int i=0; - int j=0; - double v=0; - double tau=0; - int i_=0; - int i1_=0; -//--- create array - double b[]; -//--- object of class - CDenseSolverLSReport srep; -//--- set up info - info=1; -//--- prepare matrix - for(i=0;i<=n-1;i++) - { - fmatrix[i].Set(m,y[i]); - v=w[i]; - for(i_=0;i_<=m;i_++) - fmatrix[i].Set(i_,v*fmatrix[i][i_]); - } -//--- use either fast algorithm or general algorithm - if(m<=n) - { - //--- QR decomposition - //--- We assume that M<=N (we would have called LSFit() otherwise) - for(i=0;i<=m-1;i++) - { - //--- check - if(i10000*n*CMath::m_machineepsilon) - { - //--- solve triangular system R*x=FMatrix[0:M-1,M] - //--- using fast algorithm,then exit - x[m-1]=fmatrix[m-1][m]/fmatrix[m-1][m-1]; - for(i=m-2;i>=0;i--) - { - v=0.0; - for(i_=i+1;i_<=m-1;i_++) - v+=fmatrix[i][i_]*x[i_]; - x[i]=(fmatrix[i][m]-v)/fmatrix[i][i]; - } - } - else - { - //--- use more general algorithm - ArrayResizeAL(b,m); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=i-1;j++) - fmatrix[i].Set(j,0.0); - b[i]=fmatrix[i][m]; - } - //--- function call - CDenseSolver::RMatrixSolveLS(fmatrix,m,m,b,10000*CMath::m_machineepsilon,info,srep,x); - } - } - else - { - //--- use more general algorithm - ArrayResizeAL(b,n); - for(i=0;i<=n-1;i++) - b[i]=fmatrix[i][m]; - //--- function call - CDenseSolver::RMatrixSolveLS(fmatrix,n,m,b,10000*CMath::m_machineepsilon,info,srep,x); - taskrcond=srep.m_r2; - } - } -//+------------------------------------------------------------------+ -//| Barycentric interpolant. | -//+------------------------------------------------------------------+ -class CBarycentricInterpolant - { -public: - //--- variables - int m_n; - double m_sy; - //--- arrays - double m_x[]; - double m_y[]; - double m_w[]; - //--- constructor, destructor - CBarycentricInterpolant(void); - ~CBarycentricInterpolant(void); - //--- copy - void Copy(CBarycentricInterpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CBarycentricInterpolant::CBarycentricInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBarycentricInterpolant::~CBarycentricInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CBarycentricInterpolant::Copy(CBarycentricInterpolant &obj) - { -//--- copy variables - m_n=obj.m_n; - m_sy=obj.m_sy; -//--- copy arrays - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_y,obj.m_y); - ArrayCopy(m_w,obj.m_w); - } -//+------------------------------------------------------------------+ -//| Barycentric interpolant. | -//+------------------------------------------------------------------+ -class CBarycentricInterpolantShell - { -private: - CBarycentricInterpolant m_innerobj; -public: - //--- constructor, destructor - CBarycentricInterpolantShell(void); - CBarycentricInterpolantShell(CBarycentricInterpolant &obj); - ~CBarycentricInterpolantShell(void); - //--- method - CBarycentricInterpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CBarycentricInterpolantShell::CBarycentricInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CBarycentricInterpolantShell::CBarycentricInterpolantShell(CBarycentricInterpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBarycentricInterpolantShell::~CBarycentricInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CBarycentricInterpolant *CBarycentricInterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Rational interpolation | -//+------------------------------------------------------------------+ -class CRatInt - { -private: - //--- private method - static void BarycentricNormalize(CBarycentricInterpolant &b); -public: - //--- constructor, destructor - CRatInt(void); - ~CRatInt(void); - //--- public methods - static double BarycentricCalc(CBarycentricInterpolant &b,const double t); - static void BarycentricDiff1(CBarycentricInterpolant &b,double t,double &f,double &df); - static void BarycentricDiff2(CBarycentricInterpolant &b,const double t,double &f,double &df,double &d2f); - static void BarycentricLinTransX(CBarycentricInterpolant &b,const double ca,const double cb); - static void BarycentricLinTransY(CBarycentricInterpolant &b,const double ca,const double cb); - static void BarycentricUnpack(CBarycentricInterpolant &b,int &n,double &x[],double &y[],double &w[]); - static void BarycentricBuildXYW(double &x[],double &y[],double &w[],const int n,CBarycentricInterpolant &b); - static void BarycentricBuildFloaterHormann(double &x[],double &y[],const int n,int d,CBarycentricInterpolant &b); - static void BarycentricCopy(CBarycentricInterpolant &b,CBarycentricInterpolant &b2); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CRatInt::CRatInt(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CRatInt::~CRatInt(void) - { - - } -//+------------------------------------------------------------------+ -//| Rational interpolation using barycentric formula | -//| F(t)=SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))| -//| Input parameters: | -//| B - barycentric interpolant built with one of model | -//| building subroutines. | -//| T - interpolation point | -//| Result: | -//| barycentric interpolant F(t) | -//+------------------------------------------------------------------+ -static double CRatInt::BarycentricCalc(CBarycentricInterpolant &b,const double t) - { -//--- create variables - double s1=0; - double s2=0; - double s=0; - double v=0; - int i=0; -//--- check - if(!CAp::Assert(!CInfOrNaN::IsInfinity(t),__FUNCTION__+": infinite T!")) - return(EMPTY_VALUE); -//--- special case: NaN - if(CInfOrNaN::IsNaN(t)) - return(CInfOrNaN::NaN()); -//--- special case: N=1 - if(b.m_n==1) - return(b.m_sy*b.m_y[0]); -//--- Here we assume that task is normalized,i.m_e.: -//--- 1. abs(Y[i])<=1 -//--- 2. abs(W[i])<=1 -//--- 3. X[] is ordered - s=MathAbs(t-b.m_x[0]); - for(i=0;i<=b.m_n-1;i++) - { - v=b.m_x[i]; - //--- check - if(v==(double)(t)) - return(b.m_sy*b.m_y[i]); - v=MathAbs(t-v); - //--- check - if(v0.0,__FUNCTION__+": internal error")) - return; -//--- We assume than N>1 and B.SY>0. Find: -//--- 1. pivot point (X[i] closest to T) -//--- 2. width of interval containing X[i] - v=MathAbs(b.m_x[0]-t); - k=0; - xmin=b.m_x[0]; - xmax=b.m_x[0]; -//--- calculation - for(i=1;i<=b.m_n-1;i++) - { - vv=b.m_x[i]; - //--- check - if(MathAbs(vv-t)xprev,__FUNCTION__+": points are too close!")) - return; - xprev=xi; - //--- check - if(i!=k) - { - vv=CMath::Sqr(t-xi); - s0=(t-xk)/(t-xi); - s1=(xk-xi)/vv; - } - else - { - s0=1; - s1=0; - } - //--- change values - vv=b.m_w[i]*b.m_y[i]; - n0=n0+s0*vv; - n1=n1+s1*vv; - vv=b.m_w[i]; - d0=d0+s0*vv; - d1=d1+s1*vv; - } -//--- change values - f=b.m_sy*n0/d0; - df=(n1*d0-n0*d1)/CMath::Sqr(d0); -//--- check - if(df!=0.0) - df=MathSign(df)*MathExp(MathLog(MathAbs(df))+MathLog(b.m_sy)+MathLog(xscale1)+MathLog(xscale2)); - } -//+------------------------------------------------------------------+ -//| Differentiation of barycentric interpolant: first/second | -//| derivatives. | -//| INPUT PARAMETERS: | -//| B - barycentric interpolant built with one of model | -//| building subroutines. | -//| T - interpolation point | -//| OUTPUT PARAMETERS: | -//| F - barycentric interpolant at T | -//| DF - first derivative | -//| D2F - second derivative | -//| NOTE: this algorithm may fail due to overflow/underflor if used | -//| on data whose values are close to MaxRealNumber or MinRealNumber.| -//| Use more robust BarycentricDiff1() subroutine in such cases. | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricDiff2(CBarycentricInterpolant &b,const double t, - double &f,double &df,double &d2f) - { -//--- create variables - double v=0; - double vv=0; - int i=0; - int k=0; - double n0=0; - double n1=0; - double n2=0; - double d0=0; - double d1=0; - double d2=0; - double s0=0; - double s1=0; - double s2=0; - double xk=0; - double xi=0; -//--- initialization - f=0; - df=0; - d2f=0; -//--- check - if(!CAp::Assert(!CInfOrNaN::IsInfinity(t),__FUNCTION__+": infinite T!")) - return; -//--- special case: NaN - if(CInfOrNaN::IsNaN(t)) - { - //--- change values - f=CInfOrNaN::NaN(); - df=CInfOrNaN::NaN(); - d2f=CInfOrNaN::NaN(); - //--- exit the function - return; - } -//--- special case: N=1 - if(b.m_n==1) - { - //--- change values - f=b.m_sy*b.m_y[0]; - df=0; - d2f=0; - //--- exit the function - return; - } -//--- check - if(b.m_sy==0.0) - { - //--- change values - f=0; - df=0; - d2f=0; - //--- exit the function - return; - } -//--- We assume than N>1 and B.SY>0. Find: -//--- 1. pivot point (X[i] closest to T) -//--- 2. width of interval containing X[i] - if(!CAp::Assert(b.m_sy>0.0,__FUNCTION__+": internal error")) - return; -//--- change values - f=0; - df=0; - d2f=0; - v=MathAbs(b.m_x[0]-t); - k=0; - for(i=1;i<=b.m_n-1;i++) - { - vv=b.m_x[i]; - //--- check - if(MathAbs(vv-t)0 - for(i=0;i<=b.m_n-1;i++) - b.m_x[i]=(b.m_x[i]-cb)/ca; -//--- check - if(ca<0.0) - { - for(i=0;i<=b.m_n-1;i++) - { - //--- check - if(i0.0) - { - v=1/b.m_sy; - //--- calculation - for(i_=0;i_<=b.m_n-1;i_++) - b.m_y[i_]=v*b.m_y[i_]; - } - } -//+------------------------------------------------------------------+ -//| Extracts X/Y/W arrays from rational interpolant | -//| INPUT PARAMETERS: | -//| B - barycentric interpolant | -//| OUTPUT PARAMETERS: | -//| N - nodes count, N>0 | -//| X - interpolation nodes, array[0..N-1] | -//| F - function values, array[0..N-1] | -//| W - barycentric weights, array[0..N-1] | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricUnpack(CBarycentricInterpolant &b,int &n, - double &x[],double &y[],double &w[]) - { -//--- create variables - double v=0; - int i_=0; -//--- initialization - n=b.m_n; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); - ArrayResizeAL(w,n); -//--- initialization - v=b.m_sy; -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=b.m_x[i_]; - for(i_=0;i_<=n-1;i_++) - y[i_]=v*b.m_y[i_]; - for(i_=0;i_<=n-1;i_++) - w[i_]=b.m_w[i_]; - } -//+------------------------------------------------------------------+ -//| Rational interpolant from X/Y/W arrays | -//| F(t)=SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))| -//| INPUT PARAMETERS: | -//| X - interpolation nodes, array[0..N-1] | -//| F - function values, array[0..N-1] | -//| W - barycentric weights, array[0..N-1] | -//| N - nodes count, N>0 | -//| OUTPUT PARAMETERS: | -//| B - barycentric interpolant built from (X, Y, W) | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricBuildXYW(double &x[],double &y[],double &w[], - const int n,CBarycentricInterpolant &b) - { -//--- create a variable - int i_=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- fill X/Y/W - ArrayResizeAL(b.m_x,n); - ArrayResizeAL(b.m_y,n); - ArrayResizeAL(b.m_w,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - b.m_x[i_]=x[i_]; - for(i_=0;i_<=n-1;i_++) - b.m_y[i_]=y[i_]; - for(i_=0;i_<=n-1;i_++) - b.m_w[i_]=w[i_]; - b.m_n=n; -//--- Normalize - BarycentricNormalize(b); - } -//+------------------------------------------------------------------+ -//| Rational interpolant without poles | -//| The subroutine constructs the rational interpolating function | -//| without real poles (see 'Barycentric rational interpolation with | -//| no poles and high rates of approximation', Michael S. Floater. | -//| and Kai Hormann, for more information on this subject). | -//| Input parameters: | -//| X - interpolation nodes, array[0..N-1]. | -//| Y - function values, array[0..N-1]. | -//| N - number of nodes, N>0. | -//| D - order of the interpolation scheme, 0 <= D <= N-1. | -//| D<0 will cause an error. | -//| D>=N it will be replaced with D=N-1. | -//| if you don't know what D to choose, use small value | -//| about 3-5. | -//| Output parameters: | -//| B - barycentric interpolant. | -//| Note: | -//| this algorithm always succeeds and calculates the weights | -//| with close to machine precision. | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricBuildFloaterHormann(double &x[],double &y[], - const int n,int d, - CBarycentricInterpolant &b) - { -//--- create variables - double s0=0; - double s=0; - double v=0; - int i=0; - int j=0; - int k=0; - int i_=0; -//--- create arrays - int perm[]; - double wtemp[]; - double sortrbuf[]; - double sortrbuf2[]; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(d>=0,__FUNCTION__+": incorrect D!")) - return; -//--- Prepare - if(d>n-1) - d=n-1; - b.m_n=n; -//--- special case: N=1 - if(n==1) - { - //--- allocation - ArrayResizeAL(b.m_x,n); - ArrayResizeAL(b.m_y,n); - ArrayResizeAL(b.m_w,n); - //--- change values - b.m_x[0]=x[0]; - b.m_y[0]=y[0]; - b.m_w[0]=1; - //--- function call - BarycentricNormalize(b); - //--- exit the function - return; - } -//--- Fill X/Y - ArrayResizeAL(b.m_x,n); - ArrayResizeAL(b.m_y,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - b.m_x[i_]=x[i_]; - for(i_=0;i_<=n-1;i_++) - b.m_y[i_]=y[i_]; -//--- function call - CTSort::TagSortFastR(b.m_x,b.m_y,sortrbuf,sortrbuf2,n); -//--- Calculate Wk - ArrayResizeAL(b.m_w,n); - s0=1; - for(k=1;k<=d;k++) - s0=-s0; -//--- calculation - for(k=0;k<=n-1;k++) - { - //--- Wk - s=0; - for(i=(int)(MathMax(k-d,0));i<=MathMin(k,n-1-d);i++) - { - v=1; - for(j=i;j<=i+d;j++) - { - //--- check - if(j!=k) - v=v/MathAbs(b.m_x[k]-b.m_x[j]); - } - s=s+v; - } - b.m_w[k]=s0*s; - //--- Next S0 - s0=-s0; - } -//--- Normalize - BarycentricNormalize(b); - } -//+------------------------------------------------------------------+ -//| Copying of the barycentric interpolant (for internal use only) | -//| INPUT PARAMETERS: | -//| B - barycentric interpolant | -//| OUTPUT PARAMETERS: | -//| B2 - copy(B1) | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricCopy(CBarycentricInterpolant &b, - CBarycentricInterpolant &b2) - { -//--- create a variable - int i_=0; -//--- change values - b2.m_n=b.m_n; - b2.m_sy=b.m_sy; -//--- allocation - ArrayResizeAL(b2.m_x,b2.m_n); - ArrayResizeAL(b2.m_y,b2.m_n); - ArrayResizeAL(b2.m_w,b2.m_n); -//--- copy - for(i_=0;i_<=b2.m_n-1;i_++) - b2.m_x[i_]=b.m_x[i_]; - for(i_=0;i_<=b2.m_n-1;i_++) - b2.m_y[i_]=b.m_y[i_]; - for(i_=0;i_<=b2.m_n-1;i_++) - b2.m_w[i_]=b.m_w[i_]; - } -//+------------------------------------------------------------------+ -//| Normalization of barycentric interpolant: | -//| * B.N, B.X, B.Y and B.W are initialized | -//| * B.SY is NOT initialized | -//| * Y[] is normalized, scaling coefficient is stored in B.SY | -//| * W[] is normalized, no scaling coefficient is stored | -//| * X[] is sorted | -//| Internal subroutine. | -//+------------------------------------------------------------------+ -static void CRatInt::BarycentricNormalize(CBarycentricInterpolant &b) - { -//--- create variables - int i=0; - int j=0; - int j2=0; - double v=0; - int i_=0; -//--- create arrays - int p1[]; - int p2[]; -//--- Normalize task: |Y|<=1,|W|<=1,sort X[] - b.m_sy=0; - for(i=0;i<=b.m_n-1;i++) - b.m_sy=MathMax(b.m_sy,MathAbs(b.m_y[i])); -//--- check - if(b.m_sy>0.0 && MathAbs(b.m_sy-1)>10*CMath::m_machineepsilon) - { - v=1/b.m_sy; - for(i_=0;i_<=b.m_n-1;i_++) - b.m_y[i_]=v*b.m_y[i_]; - } -//--- change value - v=0; - for(i=0;i<=b.m_n-1;i++) - v=MathMax(v,MathAbs(b.m_w[i])); -//--- check - if(v>0.0 && MathAbs(v-1)>10*CMath::m_machineepsilon) - { - v=1/v; - for(i_=0;i_<=b.m_n-1;i_++) - b.m_w[i_]=v*b.m_w[i_]; - } - for(i=0;i<=b.m_n-2;i++) - { - //--- check - if(b.m_x[i+1]B | -//| OUTPUT PARAMETERS | -//| T - coefficients of Chebyshev representation; | -//| P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, | -//| where Ti - I-th Chebyshev polynomial. | -//| NOTES: | -//| barycentric interpolant passed as P may be either polynomial | -//| obtained from polynomial interpolation/ fitting or rational | -//| function which is NOT polynomial. We can't distinguish | -//| between these two cases, and this algorithm just tries to | -//| work assuming that P IS a polynomial. If not, algorithm will | -//| return results, but they won't have any meaning. | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBar2Cheb(CBarycentricInterpolant &p, - const double a,const double b, - double &t[]) - { -//--- create variables - int i=0; - int k=0; - double v=0; - int i_=0; -//--- create arrays - double vp[]; - double vx[]; - double tk[]; - double tk1[]; -//--- check - if(!CAp::Assert(CMath::IsFinite(a),__FUNCTION__+": A is not finite!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(b),__FUNCTION__+": B is not finite!")) - return; -//--- check - if(!CAp::Assert(a!=b,__FUNCTION__+": A=B!")) - return; -//--- check - if(!CAp::Assert(p.m_n>0,__FUNCTION__+": P is not correctly initialized barycentric interpolant!")) - return; -//--- Calculate function values on a Chebyshev grid - ArrayResizeAL(vp,p.m_n); - ArrayResizeAL(vx,p.m_n); - for(i=0;i<=p.m_n-1;i++) - { - vx[i]=MathCos(M_PI*(i+0.5)/p.m_n); - vp[i]=CRatInt::BarycentricCalc(p,0.5*(vx[i]+1)*(b-a)+a); - } -//--- T[0] - ArrayResizeAL(t,p.m_n); - v=0; - for(i=0;i<=p.m_n-1;i++) - v=v+vp[i]; - t[0]=v/p.m_n; -//--- other T's. -//--- NOTES: -//--- 1. TK stores T{k} on VX,TK1 stores T{k-1} on VX -//--- 2. we can do same calculations with fast DCT,but it -//--- * adds dependencies -//--- * still leaves us with O(N^2) algorithm because -//--- preparation of function values is O(N^2) process - if(p.m_n>1) - { - //--- allocation - ArrayResizeAL(tk,p.m_n); - ArrayResizeAL(tk1,p.m_n); - for(i=0;i<=p.m_n-1;i++) - { - tk[i]=vx[i]; - tk1[i]=1; - } - //--- calculation - for(k=1;k<=p.m_n-1;k++) - { - //--- calculate discrete product of function vector and TK - v=0.0; - for(i_=0;i_<=p.m_n-1;i_++) - v+=tk[i_]*vp[i_]; - t[k]=v/(0.5*p.m_n); - //--- Update TK and TK1 - for(i=0;i<=p.m_n-1;i++) - { - v=2*vx[i]*tk[i]-tk1[i]; - tk1[i]=tk[i]; - tk[i]=v; - } - } - } - } -//+------------------------------------------------------------------+ -//| Conversion from Chebyshev basis to barycentric representation. | -//| This function has O(N^2) complexity. | -//| INPUT PARAMETERS: | -//| T - coefficients of Chebyshev representation; | -//| P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, | -//| where Ti - I-th Chebyshev polynomial. | -//| N - number of coefficients: | -//| * if given, only leading N elements of T are used | -//| * if not given, automatically determined from size | -//| of T | -//| A,B - base interval for Chebyshev polynomials (see above) | -//| A=1,__FUNCTION__+": N<1")) - return; -//--- check - if(!CAp::Assert(CAp::Len(t)>=n,__FUNCTION__+": Length(T)0. | -//| OUTPUT PARAMETERS | -//| A - coefficients, | -//| P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } | -//| N - number of coefficients (polynomial degree plus 1) | -//| NOTES: | -//| 1. this function accepts offset and scale, which can be set to | -//| improve numerical properties of polynomial. For example, if | -//| P was obtained as result of interpolation on [-1,+1], you can| -//| set C=0 and S=1 and represent P as sum of 1, x, x^2, x^3 and | -//| so on. In most cases you it is exactly what you need. | -//| However, if your interpolation model was built on [999,1001],| -//| you will see significant growth of numerical errors when | -//| using {1, x, x^2, x^3} as basis. Representing P as sum of 1, | -//| (x-1000), (x-1000)^2, (x-1000)^3 will be better option. Such | -//| representation can be obtained by using 1000.0 as offset | -//| C and 1.0 as scale S. | -//| 2. power basis is ill-conditioned and tricks described above | -//| can't solve this problem completely. This function will | -//| return coefficients in any case, but for N>8 they will become| -//| unreliable. However, N's less than 5 are pretty safe. | -//| 3. barycentric interpolant passed as P may be either polynomial | -//| obtained from polynomial interpolation/ fitting or rational | -//| function which is NOT polynomial. We can't distinguish | -//| between these two cases, and this algorithm just tries to | -//| work assuming that P IS a polynomial. If not, algorithm will | -//| return results, but they won't have any meaning. | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBar2Pow(CBarycentricInterpolant &p, - const double c,const double s, - double &a[]) - { -//--- create variables - int i=0; - int k=0; - double e=0; - double d=0; - double v=0; - int i_=0; -//--- create arrays - double vp[]; - double vx[]; - double tk[]; - double tk1[]; - double t[]; -//--- check - if(!CAp::Assert(CMath::IsFinite(c),__FUNCTION__+": C is not finite!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(s),__FUNCTION__+": S is not finite!")) - return; -//--- check - if(!CAp::Assert(s!=0.0,__FUNCTION__+": S=0!")) - return; -//--- check - if(!CAp::Assert(p.m_n>0,__FUNCTION__+": P is not correctly initialized barycentric interpolant!")) - return; -//--- Calculate function values on a Chebyshev grid - ArrayResizeAL(vp,p.m_n); - ArrayResizeAL(vx,p.m_n); - for(i=0;i<=p.m_n-1;i++) - { - vx[i]=MathCos(M_PI*(i+0.5)/p.m_n); - vp[i]=CRatInt::BarycentricCalc(p,s*vx[i]+c); - } -//--- T[0] - ArrayResizeAL(t,p.m_n); - v=0; - for(i=0;i<=p.m_n-1;i++) - v=v+vp[i]; - t[0]=v/p.m_n; -//--- other T's. -//--- NOTES: -//--- 1. TK stores T{k} on VX,TK1 stores T{k-1} on VX -//--- 2. we can do same calculations with fast DCT,but it -//--- * adds dependencies -//--- * still leaves us with O(N^2) algorithm because -//--- preparation of function values is O(N^2) process - if(p.m_n>1) - { - //--- allocation - ArrayResizeAL(tk,p.m_n); - ArrayResizeAL(tk1,p.m_n); - for(i=0;i<=p.m_n-1;i++) - { - tk[i]=vx[i]; - tk1[i]=1; - } - //--- calculation - for(k=1;k<=p.m_n-1;k++) - { - //--- calculate discrete product of function vector and TK - v=0.0; - for(i_=0;i_<=p.m_n-1;i_++) - v+=tk[i_]*vp[i_]; - t[k]=v/(0.5*p.m_n); - //--- Update TK and TK1 - for(i=0;i<=p.m_n-1;i++) - { - v=2*vx[i]*tk[i]-tk1[i]; - tk1[i]=tk[i]; - tk[i]=v; - } - } - } -//--- Convert from Chebyshev basis to power basis - ArrayResizeAL(a,p.m_n); - for(i=0;i<=p.m_n-1;i++) - a[i]=0; - d=0; -//--- calculation - for(i=0;i<=p.m_n-1;i++) - { - for(k=i;k<=p.m_n-1;k++) - { - e=a[k]; - a[k]=0; - //--- check - if(i<=1 && k==i) - a[k]=1; - else - { - //--- check - if(i!=0) - a[k]=2*d; - //--- check - if(k>i+1) - a[k]=a[k]-a[k-2]; - } - d=e; - } - //--- change values - d=a[i]; - e=0; - k=i; - //--- cycle - while(k<=p.m_n-1) - { - e=e+a[k]*t[k]; - k=k+2; - } - a[i]=e; - } - } -//+------------------------------------------------------------------+ -//| Conversion from power basis to barycentric representation. | -//| This function has O(N^2) complexity. | -//| INPUT PARAMETERS: | -//| A - coefficients, P(x)=sum { A[i]*((X-C)/S)^i, i=0..N-1 }| -//| N - number of coefficients (polynomial degree plus 1) | -//| * if given, only leading N elements of A are used | -//| * if not given, automatically determined from size | -//| of A | -//| C - offset (see below); 0.0 is used as default value. | -//| S - scale (see below); 1.0 is used as default value. | -//| S<>0. | -//| OUTPUT PARAMETERS | -//| P - polynomial in barycentric form | -//| NOTES: | -//| 1. this function accepts offset and scale, which can be set to | -//| improve numerical properties of polynomial. For example, if | -//| you interpolate on [-1,+1], you can set C=0 and S=1 and | -//| convert from sum of 1, x, x^2, x^3 and so on. In most cases | -//| you it is exactly what you need. | -//| However, if your interpolation model was built on [999,1001],| -//| you will see significant growth of numerical errors when | -//| using {1, x, x^2, x^3} as input basis. Converting from sum | -//| of 1, (x-1000), (x-1000)^2, (x-1000)^3 will be better option | -//| (you have to specify 1000.0 as offset C and 1.0 as scale S). | -//| 2. power basis is ill-conditioned and tricks described above | -//| can't solve this problem completely. This function will | -//| return barycentric model in any case, but for N>8 accuracy | -//| well degrade. However, N's less than 5 are pretty safe. | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialPow2Bar(double &a[],const int n,const double c, - const double s,CBarycentricInterpolant &p) - { -//--- create variables - int i=0; - int k=0; - double vx=0; - double vy=0; - double px=0; -//--- create array - double y[]; -//--- check - if(!CAp::Assert(CMath::IsFinite(c),__FUNCTION__+": C is not finite!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(s),__FUNCTION__+": S is not finite!")) - return; -//--- check - if(!CAp::Assert(s!=0.0,__FUNCTION__+": S is zero!")) - return; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1")) - return; -//--- check - if(!CAp::Assert(CAp::Len(a)>=n,__FUNCTION__+": Length(A)=1 | -//| OUTPUT PARAMETERS | -//| P - barycentric model which represents Lagrange | -//| interpolant (see ratint unit info and | -//| BarycentricCalc() description for more information). | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBuild(double &cx[],double &cy[],const int n, - CBarycentricInterpolant &p) - { -//--- create variables - int j=0; - int k=0; - double b=0; - double a=0; - double v=0; - double mx=0; - int i_=0; -//--- create arrays - double w[]; - double sortrbuf[]; - double sortrbuf2[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=1 | -//| for N=1 a constant model is constructed. | -//| OUTPUT PARAMETERS | -//| P - barycentric model which represents Lagrange | -//| interpolant (see ratint unit info and | -//| BarycentricCalc() description for more information). | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBuildEqDist(const double a,const double b, - double &y[],const int n, - CBarycentricInterpolant &p) - { -//--- create variables - int i=0; - double v=0; -//--- create arrays - double w[]; - double x[]; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": Length(Y)=1 | -//| for N=1 a constant model is constructed. | -//| OUTPUT PARAMETERS | -//| P - barycentric model which represents Lagrange | -//| interpolant (see ratint unit info and | -//| BarycentricCalc() description for more information). | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBuildCheb1(const double a,const double b, - double &y[],const int n, - CBarycentricInterpolant &p) - { -//--- create variables - int i=0; - double v=0; - double t=0; -//--- create arrays - double w[]; - double x[]; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": Length(Y)=1 | -//| for N=1 a constant model is constructed. | -//| OUTPUT PARAMETERS | -//| P - barycentric model which represents Lagrange | -//| interpolant (see ratint unit info and | -//| BarycentricCalc() description for more information). | -//+------------------------------------------------------------------+ -static void CPolInt::PolynomialBuildCheb2(const double a,const double b, - double &y[],const int n, - CBarycentricInterpolant &p) - { -//--- create variables - int i=0; - double v=0; -//--- create arrays - double w[]; - double x[]; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": Length(Y)=1 | -//| for N=1 a constant model is constructed. | -//| T - position where P(x) is calculated | -//| RESULT | -//| value of the Lagrange interpolant at T | -//| IMPORTANT | -//| this function provides fast interface which is not | -//| overflow-safe nor it is very precise. | -//| the best option is to use PolynomialBuildEqDist() or | -//| BarycentricCalc() subroutines unless you are pretty sure that| -//| your data will not result in overflow. | -//+------------------------------------------------------------------+ -static double CPolInt::PolynomialCalcEqDist(const double a,const double b, - double &f[],const int n,const double t) - { -//--- create variables - double s1=0; - double s2=0; - double v=0; - double threshold=0; - double s=0; - double h=0; - int i=0; - int j=0; - double w=0; - double x=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(f)>=n,__FUNCTION__+": Length(F)threshold) - { - //--- use fast formula - j=-1; - s=1.0; - } -//--- Calculate using safe or fast barycentric formula - s1=0; - s2=0; - w=1.0; - h=(b-a)/(n-1); -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- check - if(i!=j) - { - v=s*w/(t-(a+i*h)); - s1=s1+v*f[i]; - s2=s2+v; - } - else - { - v=w; - s1=s1+v*f[i]; - s2=s2+v; - } - //--- change values - w=-(w*(n-1-i)); - w=w/(i+1); - } -//--- return result - return(s1/s2); - } -//+------------------------------------------------------------------+ -//| Fast polynomial interpolation function on Chebyshev points (first| -//| kind) with O(N) complexity. | -//| INPUT PARAMETERS: | -//| A - left boundary of [A,B] | -//| B - right boundary of [A,B] | -//| F - function values, array[0..N-1] | -//| N - number of points on Chebyshev grid (first kind), | -//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) | -//| for N=1 a constant model is constructed. | -//| T - position where P(x) is calculated | -//| RESULT | -//| value of the Lagrange interpolant at T | -//| IMPORTANT | -//| this function provides fast interface which is not | -//| overflow-safe nor it is very precise | -//| the best option is to use PolIntBuildCheb1() or | -//| BarycentricCalc() subroutines unless you are pretty sure that| -//| your data will not result in overflow. | -//+------------------------------------------------------------------+ -static double CPolInt::PolynomialCalcCheb1(const double a,const double b, - double &f[],const int n,double t) - { -//--- create variables - double s1=0; - double s2=0; - double v=0; - double threshold=0; - double s=0; - int i=0; - int j=0; - double a0=0; - double delta=0; - double alpha=0; - double beta=0; - double ca=0; - double sa=0; - double tempc=0; - double temps=0; - double x=0; - double w=0; - double p1=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(f)>=n,__FUNCTION__+": Length(F)threshold) - { - //--- use fast formula - j=-1; - s=1.0; - } -//--- Calculate using safe or fast barycentric formula - s1=0; - s2=0; - ca=MathCos(a0); - sa=MathSin(a0); - p1=1.0; -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- Calculate X[i],W[i] - x=ca; - w=p1*sa; - //--- Proceed - if(i!=j) - { - v=s*w/(t-x); - s1=s1+v*f[i]; - s2=s2+v; - } - else - { - v=w; - s1=s1+v*f[i]; - s2=s2+v; - } - //--- Next CA,SA,P1 - temps=sa-(alpha*sa-beta*ca); - tempc=ca-(alpha*ca+beta*sa); - sa=temps; - ca=tempc; - p1=-p1; - } -//--- return result - return(s1/s2); - } -//+------------------------------------------------------------------+ -//| Fast polynomial interpolation function on Chebyshev points | -//| (second kind) with O(N) complexity. | -//| INPUT PARAMETERS: | -//| A - left boundary of [A,B] | -//| B - right boundary of [A,B] | -//| F - function values, array[0..N-1] | -//| N - number of points on Chebyshev grid (second kind), | -//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) | -//| for N=1 a constant model is constructed. | -//| T - position where P(x) is calculated | -//| RESULT | -//| value of the Lagrange interpolant at T | -//| IMPORTANT | -//| this function provides fast interface which is not | -//| overflow-safe nor it is very precise. | -//| the best option is to use PolIntBuildCheb2() or | -//| BarycentricCalc() subroutines unless you are pretty sure that| -//| your data will not result in overflow. | -//+------------------------------------------------------------------+ -static double CPolInt::PolynomialCalcCheb2(const double a,const double b, - double &f[],const int n,double t) - { -//--- create variables - double s1=0; - double s2=0; - double v=0; - double threshold=0; - double s=0; - int i=0; - int j=0; - double a0=0; - double delta=0; - double alpha=0; - double beta=0; - double ca=0; - double sa=0; - double tempc=0; - double temps=0; - double x=0; - double w=0; - double p1=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(f)>=n,__FUNCTION__+": Length(F)threshold) - { - //--- use fast formula - j=-1; - s=1.0; - } -//--- Calculate using safe or fast barycentric formula - s1=0; - s2=0; - ca=MathCos(a0); - sa=MathSin(a0); - p1=1.0; -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- Calculate X[i],W[i] - x=ca; - //--- check - if(i==0 || i==n-1) - w=0.5*p1; - else - w=1.0*p1; - //--- Proceed - if(i!=j) - { - v=s*w/(t-x); - s1=s1+v*f[i]; - s2=s2+v; - } - else - { - v=w; - s1=s1+v*f[i]; - s2=s2+v; - } - //--- Next CA,SA,P1 - temps=sa-(alpha*sa-beta*ca); - tempc=ca-(alpha*ca+beta*sa); - sa=temps; - ca=tempc; - p1=-p1; - } -//--- return result - return(s1/s2); - } -//+------------------------------------------------------------------+ -//| 1-dimensional spline inteprolant | -//+------------------------------------------------------------------+ -class CSpline1DInterpolant - { -public: - //--- variables - bool m_periodic; - int m_n; - int m_k; - //--- arrays - double m_x[]; - double m_c[]; - //--- constructor, destructor - CSpline1DInterpolant(void); - ~CSpline1DInterpolant(void); - //--- copy - void Copy(CSpline1DInterpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline1DInterpolant::CSpline1DInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline1DInterpolant::~CSpline1DInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CSpline1DInterpolant::Copy(CSpline1DInterpolant &obj) - { -//--- copy variables - m_periodic=obj.m_periodic; - m_n=obj.m_n; - m_k=obj.m_k; -//--- copy arrays - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_c,obj.m_c); - } -//+------------------------------------------------------------------+ -//| 1-dimensional spline inteprolant | -//+------------------------------------------------------------------+ -class CSpline1DInterpolantShell - { -private: - CSpline1DInterpolant m_innerobj; -public: - //--- constructors, destructor - CSpline1DInterpolantShell(void); - CSpline1DInterpolantShell(CSpline1DInterpolant &obj); - ~CSpline1DInterpolantShell(void); - //--- method - CSpline1DInterpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline1DInterpolantShell::CSpline1DInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CSpline1DInterpolantShell::CSpline1DInterpolantShell(CSpline1DInterpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline1DInterpolantShell::~CSpline1DInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CSpline1DInterpolant *CSpline1DInterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| 1-dimensional spline interpolation | -//+------------------------------------------------------------------+ -class CSpline1D - { -private: - //--- private methods - static void Spline1DGridDiffCubicInternal(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d[],double &a1[],double &a2[],double &a3[],double &b[],double &dt[]); - static void HeapSortPoints(double &x[],double &y[],const int n); - static void HeapSortPPoints(double &x[],double &y[],int &p[],const int n); - static void SolveTridiagonal(double &a[],double &cb[],double &c[],double &cd[],const int n,double &x[]); - static void SolveCyclicTridiagonal(double &a[],double &cb[],double &c[],double &d[],const int n,double &x[]); - static double DiffThreePoint(double t,const double x0,const double f0,double x1,const double f1,double x2,const double f2); -public: - //--- constructor, destructor - CSpline1D(void); - ~CSpline1D(void); - //--- public methods - static void Spline1DBuildLinear(double &cx[],double &cy[],const int n,CSpline1DInterpolant &c); - static void Spline1DBuildCubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,CSpline1DInterpolant &c); - static void Spline1DGridDiffCubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d[]); - static void Spline1DGridDiff2Cubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d1[],double &d2[]); - static void Spline1DConvCubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &cx2[],const int n2,double &y2[]); - static void Spline1DConvDiffCubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &cx2[],const int n2,double &y2[],double &d2[]); - static void Spline1DConvDiff2Cubic(double &cx[],double &cy[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &cx2[],const int n2,double &y2[],double &d2[],double &dd2[]); - static void Spline1DBuildCatmullRom(double &cx[],double &cy[],const int n,const int boundtype,const double tension,CSpline1DInterpolant &c); - static void Spline1DBuildHermite(double &cx[],double &cy[],double &cd[],const int n,CSpline1DInterpolant &c); - static void Spline1DBuildAkima(double &cx[],double &cy[],const int n,CSpline1DInterpolant &c); - static double Spline1DCalc(CSpline1DInterpolant &c,double x); - static void Spline1DDiff(CSpline1DInterpolant &c,double x,double &s,double &ds,double &d2s); - static void Spline1DCopy(CSpline1DInterpolant &c,CSpline1DInterpolant &cc); - static void Spline1DUnpack(CSpline1DInterpolant &c,int &n,CMatrixDouble &tbl); - static void Spline1DLinTransX(CSpline1DInterpolant &c,const double a,const double b); - static void Spline1DLinTransY(CSpline1DInterpolant &c,const double a,const double b); - static double Spline1DIntegrate(CSpline1DInterpolant &c,double x); - static void Spline1DConvDiffInternal(double &xold[],double &yold[],double &dold[],const int n,double &x2[],const int n2,double &y[],const bool needy,double &d1[],const bool needd1,double &d2[],const bool needd2); - static void HeapSortDPoints(double &x[],double &y[],double &d[],const int n); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline1D::CSpline1D(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline1D::~CSpline1D(void) - { - - } -//+------------------------------------------------------------------+ -//| This subroutine builds linear spline interpolant | -//| INPUT PARAMETERS: | -//| X - spline nodes, array[0..N-1] | -//| Y - function values, array[0..N-1] | -//| N - points count (optional): | -//| * N>=2 | -//| * if given, only first N points are used to build | -//| spline | -//| * if not given, automatically detected from X/Y | -//| sizes (len(X) must be equal to len(Y)) | -//| OUTPUT PARAMETERS: | -//| C - spline interpolant | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DBuildLinear(double &cx[],double &cy[], - const int n,CSpline1DInterpolant &c) - { -//--- create a variable - int i=0; -//--- create arrays - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check - if(!CAp::Assert(n>1,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2 | -//| * if given, only first N points are used to | -//| build spline | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| OUTPUT PARAMETERS: | -//| C - spline interpolant | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. However, this subroutine doesn't | -//| require you to specify equal values for the first and last | -//| points - it automatically forces them to be equal by copying | -//| Y[first_point] (corresponds to the leftmost, minimal X[]) to | -//| Y[last_point]. However it is recommended to pass consistent | -//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DBuildCubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl,const int boundrtype, - const double boundr,CSpline1DInterpolant &c) - { -//--- create a variable - int ylen=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double dt[]; - double d[]; - int p[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2 | -//| * if given, only first N points are used | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| OUTPUT PARAMETERS: | -//| D - derivative values at X[] | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. Derivative values are correctly reordered on | -//| return, so D[I] is always equal to S'(X[I]) independently of | -//| points order. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. However, this subroutine doesn't | -//| require you to specify equal values for the first and last | -//| points - it automatically forces them to be equal by copying | -//| Y[first_point] (corresponds to the leftmost, minimal X[]) to | -//| Y[last_point]. However it is recommended to pass consistent | -//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DGridDiffCubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl,const int boundrtype, - const double boundr,double &d[]) - { -//--- create variables - int i=0; - int ylen=0; - int i_=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double dt[]; - int p[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2 | -//| * if given, only first N points are used | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| OUTPUT PARAMETERS: | -//| D1 - S' values at X[] | -//| D2 - S'' values at X[] | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. Derivative values are correctly reordered on | -//| return, so D[I] is always equal to S'(X[I]) independently of | -//| points order. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. | -//| However, this subroutine doesn't require you to specify equal | -//| values for the first and last points - it automatically forces | -//| them to be equal by copying Y[first_point] (corresponds to the | -//| leftmost, minimal X[]) to Y[last_point]. However it is | -//| recommended to pass consistent values of Y[], i.e. to make | -//| Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DGridDiff2Cubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl,const int boundrtype, - const double boundr,double &d1[],double &d2[]) - { -//--- create variables - int i=0; - int ylen=0; - double delta=0; - double delta2=0; - double delta3=0; - double s0=0; - double s1=0; - double s2=0; - double s3=0; - int i_=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double dt[]; - int p[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2 | -//| * if given, only first N points from X/Y are | -//| used | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| N2 - new points count: | -//| * N2>=2 | -//| * if given, only first N2 points from X2 are | -//| used | -//| * if not given, automatically detected from | -//| X2 size | -//| OUTPUT PARAMETERS: | -//| F2 - function values at X2[] | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. Function values are correctly reordered on | -//| return, so F2[I] is always equal to S(X2[I]) independently of | -//| points order. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. However, this subroutine doesn't | -//| require you to specify equal values for the first and last | -//| points - it automatically forces them to be equal by copying | -//| Y[first_point] (corresponds to the leftmost, minimal X[]) to | -//| Y[last_point]. However it is recommended to pass consistent | -//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DConvCubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl,const int boundrtype, - const double boundr,double &cx2[], - const int n2,double &y2[]) - { -//--- create variables - int i=0; - int ylen=0; - double t=0; - double t2=0; - int i_=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double d[]; - double dt[]; - double d1[]; - double d2[]; - int p[]; - int p2[]; - double x[]; - double y[]; - double x2[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(x2,cx2); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2,__FUNCTION__+": N2<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x2)>=n2,__FUNCTION__+": Length(X2)=n2,__FUNCTION__+": internal error!")) - return; -//--- copy - for(i=0;i<=n2-1;i++) - dt[p2[i]]=y2[i]; - for(i_=0;i_<=n2-1;i_++) - y2[i_]=dt[i_]; - } -//+------------------------------------------------------------------+ -//| This function solves following problem: given table y[] of | -//| function values at old nodes x[] and new nodes x2[], it | -//| calculates and returns table of function values y2[] and | -//| derivatives d2[] (calculated at x2[]). | -//| This function yields same result as Spline1DBuildCubic() call | -//| followed by sequence of Spline1DDiff() calls, but it can be | -//| several times faster when called for ordered X[] and X2[]. | -//| INPUT PARAMETERS: | -//| X - old spline nodes | -//| Y - function values | -//| X2 - new spline nodes | -//| OPTIONAL PARAMETERS: | -//| N - points count: | -//| * N>=2 | -//| * if given, only first N points from X/Y are | -//| used | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| N2 - new points count: | -//| * N2>=2 | -//| * if given, only first N2 points from X2 are | -//| used | -//| * if not given, automatically detected from | -//| X2 size | -//| OUTPUT PARAMETERS: | -//| F2 - function values at X2[] | -//| D2 - first derivatives at X2[] | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. Function values are correctly reordered on | -//| return, so F2[I] is always equal to S(X2[I]) independently of | -//| points order. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. However, this subroutine doesn't | -//| require you to specify equal values for the first and last | -//| points - it automatically forces them to be equal by copying | -//| Y[first_point] (corresponds to the leftmost, minimal X[]) to | -//| Y[last_point]. However it is recommended to pass consistent | -//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DConvDiffCubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl,const int boundrtype, - const double boundr,double &cx2[], - const int n2,double &y2[],double &d2[]) - { -//--- create variables - int i=0; - int ylen=0; - double t=0; - double t2=0; - int i_=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double d[]; - double dt[]; - double rt1[]; - int p[]; - int p2[]; - double x[]; - double y[]; - double x2[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(x2,cx2); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2,__FUNCTION__+"Spline1DConvDiffCubic: N2<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x2)>=n2,__FUNCTION__+": Length(X2)=n2,__FUNCTION__+": internal error!")) - return; -//--- copy - for(i=0;i<=n2-1;i++) - dt[p2[i]]=y2[i]; - for(i_=0;i_<=n2-1;i_++) - y2[i_]=dt[i_]; - for(i=0;i<=n2-1;i++) - dt[p2[i]]=d2[i]; - for(i_=0;i_<=n2-1;i_++) - d2[i_]=dt[i_]; - } -//+------------------------------------------------------------------+ -//| This function solves following problem: given table y[] of | -//| function values at old nodes x[] and new nodes x2[], it | -//| calculates and returns table of function values y2[], first and | -//| second derivatives d2[] and dd2[] (calculated at x2[]). | -//| This function yields same result as Spline1DBuildCubic() call | -//| followed by sequence of Spline1DDiff() calls, but it can be | -//| several times faster when called for ordered X[] and X2[]. | -//| INPUT PARAMETERS: | -//| X - old spline nodes | -//| Y - function values | -//| X2 - new spline nodes | -//| OPTIONAL PARAMETERS: | -//| N - points count: | -//| * N>=2 | -//| * if given, only first N points from X/Y are | -//| used | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundLType - boundary condition type for the left boundary| -//| BoundL - left boundary condition (first or second | -//| derivative, depending on the BoundLType) | -//| BoundRType - boundary condition type for the right | -//| boundary | -//| BoundR - right boundary condition (first or second | -//| derivative, depending on the BoundRType) | -//| N2 - new points count: | -//| * N2>=2 | -//| * if given, only first N2 points from X2 are | -//| used | -//| * if not given, automatically detected from | -//| X2 size | -//| OUTPUT PARAMETERS: | -//| F2 - function values at X2[] | -//| D2 - first derivatives at X2[] | -//| DD2 - second derivatives at X2[] | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. Function values are correctly reordered on | -//| return, so F2[I] is always equal to S(X2[I]) independently of | -//| points order. | -//| SETTING BOUNDARY VALUES: | -//| The BoundLType/BoundRType parameters can have the following | -//| values: | -//| * -1, which corresonds to the periodic (cyclic) boundary | -//| conditions. In this case: | -//| * both BoundLType and BoundRType must be equal to -1. | -//| * BoundL/BoundR are ignored | -//| * Y[last] is ignored (it is assumed to be equal to | -//| Y[first]). | -//| * 0, which corresponds to the parabolically terminated | -//| spline (BoundL and/or BoundR are ignored). | -//| * 1, which corresponds to the first derivative boundary | -//| condition | -//| * 2, which corresponds to the second derivative boundary | -//| condition | -//| * by default, BoundType=0 is used | -//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: | -//| Problems with periodic boundary conditions have | -//| Y[first_point]=Y[last_point]. However, this subroutine doesn't | -//| require you to specify equal values for the first and last | -//| points - it automatically forces them to be equal by copying | -//| Y[first_point] (corresponds to the leftmost, minimal X[]) to | -//| Y[last_point]. However it is recommended to pass consistent | -//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DConvDiff2Cubic(double &cx[],double &cy[], - const int n,const int boundltype, - const double boundl, - const int boundrtype, - const double boundr,double &cx2[], - const int n2,double &y2[], - double &d2[],double &dd2[]) - { -//--- create variables - int i=0; - int ylen=0; - double t=0; - double t2=0; - int i_=0; -//--- create arrays - double a1[]; - double a2[]; - double a3[]; - double b[]; - double d[]; - double dt[]; - int p[]; - int p2[]; - double x[]; - double y[]; - double x2[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(x2,cx2); -//--- check correctness of boundary conditions - if(!CAp::Assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2,__FUNCTION__+": incorrect BoundLType!")) - return; -//--- check - if(!CAp::Assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2,__FUNCTION__+": incorrect BoundRType!")) - return; -//--- check - if(!CAp::Assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1),__FUNCTION__+": incorrect BoundLType/BoundRType!")) - return; -//--- check - if(boundltype==1 || boundltype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundl),__FUNCTION__+": BoundL is infinite or NAN!")) - return; - } -//--- check - if(boundrtype==1 || boundrtype==2) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(boundr),__FUNCTION__+": BoundR is infinite or NAN!")) - return; - } -//--- check lengths of arguments - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2,__FUNCTION__+": N2<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x2)>=n2,__FUNCTION__+": Length(X2)=n2,__FUNCTION__+": internal error!")) - return; -//--- copy - for(i=0;i<=n2-1;i++) - dt[p2[i]]=y2[i]; - for(i_=0;i_<=n2-1;i_++) - y2[i_]=dt[i_]; - for(i=0;i<=n2-1;i++) - dt[p2[i]]=d2[i]; - for(i_=0;i_<=n2-1;i_++) - d2[i_]=dt[i_]; - for(i=0;i<=n2-1;i++) - dt[p2[i]]=dd2[i]; - for(i_=0;i_<=n2-1;i_++) - dd2[i_]=dt[i_]; - } -//+------------------------------------------------------------------+ -//| This subroutine builds Catmull-Rom spline interpolant. | -//| INPUT PARAMETERS: | -//| X - spline nodes, array[0..N-1]. | -//| Y - function values, array[0..N-1]. | -//| OPTIONAL PARAMETERS: | -//| N - points count: | -//| * N>=2 | -//| * if given, only first N points are used to | -//| build spline | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| BoundType - boundary condition type: | -//| * -1 for periodic boundary condition | -//| * 0 for parabolically terminated spline | -//| (default) | -//| Tension - tension parameter: | -//| * tension=0 corresponds to classic | -//| Catmull-Rom spline (default) | -//| * 0=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(boundtype==-1 || boundtype==0,__FUNCTION__+": incorrect BoundType!")) - return; -//--- check - if(!CAp::Assert((double)(tension)>=0.0,__FUNCTION__+": Tension<0!")) - return; -//--- check - if(!CAp::Assert((double)(tension)<=(double)(1),__FUNCTION__+": Tension>1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=2 | -//| * if given, only first N points are used to | -//| build spline | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| OUTPUT PARAMETERS: | -//| C - spline interpolant. | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DBuildHermite(double &cx[],double &cy[], - double &cd[],const int n, - CSpline1DInterpolant &c) - { -//--- create variables - int i=0; - double delta=0; - double delta2=0; - double delta3=0; -//--- create arrays - double x[]; - double y[]; - double d[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(d,cd); -//--- check - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(D)=5 | -//| * if given, only first N points are used to | -//| build spline | -//| * if not given, automatically detected from | -//| X/Y sizes (len(X) must be equal to len(Y)) | -//| OUTPUT PARAMETERS: | -//| C - spline interpolant | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DBuildAkima(double &cx[],double &cy[], - const int n,CSpline1DInterpolant &c) - { -//--- create a variable - int i=0; -//--- create arrays - double d[]; - double w[]; - double diff[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- check - if(!CAp::Assert(n>=5,__FUNCTION__+": N<5!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=x) - r=m; - else - l=m; - } -//--- Interpolation - x=x-c.m_x[l]; - m=4*l; -//--- return result - return(c.m_c[m]+x*(c.m_c[m+1]+x*(c.m_c[m+2]+x*c.m_c[m+3]))); - } -//+------------------------------------------------------------------+ -//| This subroutine differentiates the spline. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| X - point | -//| Result: | -//| S - S(x) | -//| DS - S'(x) | -//| D2S - S''(x) | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DDiff(CSpline1DInterpolant &c,double x, - double &s,double &ds,double &d2s) - { -//--- create variables - int l=0; - int r=0; - int m=0; - double t=0; -//--- initialization - s=0; - ds=0; - d2s=0; -//--- check - if(!CAp::Assert(c.m_k==3,__FUNCTION__+": internal error")) - return; -//--- check - if(!CAp::Assert(!CInfOrNaN::IsInfinity(x),__FUNCTION__+": infinite X!")) - return; -//--- special case: NaN - if(CInfOrNaN::IsNaN(x)) - { - //--- change values - s=CInfOrNaN::NaN(); - ds=CInfOrNaN::NaN(); - d2s=CInfOrNaN::NaN(); - //--- exit the function - return; - } -//--- correct if periodic - if(c.m_periodic) - CApServ::ApPeriodicMap(x,c.m_x[0],c.m_x[c.m_n-1],t); -//--- Binary search - l=0; - r=c.m_n-2+1; - while(l!=r-1) - { - m=(l+r)/2; - //--- check - if(c.m_x[m]>=x) - r=m; - else - l=m; - } -//--- Differentiation - x=x-c.m_x[l]; - m=4*l; - s=c.m_c[m]+x*(c.m_c[m+1]+x*(c.m_c[m+2]+x*c.m_c[m+3])); - ds=c.m_c[m+1]+2*x*c.m_c[m+2]+3*CMath::Sqr(x)*c.m_c[m+3]; - d2s=2*c.m_c[m+2]+6*x*c.m_c[m+3]; - } -//+------------------------------------------------------------------+ -//| This subroutine makes the copy of the spline. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| Result: | -//| CC - spline copy | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DCopy(CSpline1DInterpolant &c,CSpline1DInterpolant &cc) - { -//--- create a variable - int i_=0; -//--- change values - cc.m_periodic=c.m_periodic; - cc.m_n=c.m_n; - cc.m_k=c.m_k; -//--- allocation - ArrayResizeAL(cc.m_x,cc.m_n); -//--- copy - for(i_=0;i_<=cc.m_n-1;i_++) - cc.m_x[i_]=c.m_x[i_]; -//--- allocation - ArrayResizeAL(cc.m_c,(cc.m_k+1)*(cc.m_n-1)); -//--- copy - for(i_=0;i_<=(cc.m_k+1)*(cc.m_n-1)-1;i_++) - cc.m_c[i_]=c.m_c[i_]; - } -//+------------------------------------------------------------------+ -//| This subroutine unpacks the spline into the coefficients table. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| X - point | -//| Result: | -//| Tbl - coefficients table, unpacked format, array[0..N-2, | -//| 0..5]. | -//| For I = 0...N-2: | -//| Tbl[I,0] = X[i] | -//| Tbl[I,1] = X[i+1] | -//| Tbl[I,2] = C0 | -//| Tbl[I,3] = C1 | -//| Tbl[I,4] = C2 | -//| Tbl[I,5] = C3 | -//| On [x[i], x[i+1]] spline is equals to: | -//| S(x) = C0 + C1*t + C2*t^2 + C3*t^3 | -//| t = x-x[i] | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DUnpack(CSpline1DInterpolant &c,int &n, - CMatrixDouble &tbl) - { -//--- create variables - int i=0; - int j=0; -//--- allocation - tbl.Resize(c.m_n-2+1,2+c.m_k+1); -//--- initialization - n=c.m_n; -//--- Fill - for(i=0;i<=n-2;i++) - { - tbl[i].Set(0,c.m_x[i]); - tbl[i].Set(1,c.m_x[i+1]); - for(j=0;j<=c.m_k;j++) - tbl[i].Set(2+j,c.m_c[(c.m_k+1)*i+j]); - } - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline | -//| argument. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| A, B- transformation coefficients: x = A*t + B | -//| Result: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DLinTransX(CSpline1DInterpolant &c,const double a, - const double b) - { -//--- create variables - int i=0; - int j=0; - int n=0; - double v=0; - double dv=0; - double d2v=0; -//--- create arrays - double x[]; - double y[]; - double d[]; -//--- initialization - n=c.m_n; -//--- Special case: A=0 - if(a==0.0) - { - v=Spline1DCalc(c,b); - for(i=0;i<=n-2;i++) - { - c.m_c[(c.m_k+1)*i]=v; - for(j=1;j<=c.m_k;j++) - c.m_c[(c.m_k+1)*i+j]=0; - } - //--- exit the function - return; - } -//--- General case: A<>0. -//--- Unpack,X,Y,dY/dX. -//--- Scale and pack again. - if(!CAp::Assert(c.m_k==3,__FUNCTION__+": internal error")) - return; -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,n); - ArrayResizeAL(d,n); -//--- calculation - for(i=0;i<=n-1;i++) - { - x[i]=c.m_x[i]; - Spline1DDiff(c,x[i],v,dv,d2v); - x[i]=(x[i]-b)/a; - y[i]=v; - d[i]=a*dv; - } -//--- function call - Spline1DBuildHermite(x,y,d,n,c); - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| A,B- transformation coefficients: S2(x)=A*S(x) + B | -//| Result: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DLinTransY(CSpline1DInterpolant &c,const double a, - const double b) - { -//--- create variables - int i=0; - int j=0; - int n=0; -//--- initialization - n=c.m_n; -//--- calculation - for(i=0;i<=n-2;i++) - { - c.m_c[(c.m_k+1)*i]=a*c.m_c[(c.m_k+1)*i]+b; - for(j=1;j<=c.m_k;j++) - c.m_c[(c.m_k+1)*i+j]=a*c.m_c[(c.m_k+1)*i+j]; - } - } -//+------------------------------------------------------------------+ -//| This subroutine integrates the spline. | -//| INPUT PARAMETERS: | -//| C - spline interpolant. | -//| X - right bound of the integration interval [a, x], | -//| here 'a' denotes min(x[]) | -//| Result: | -//| integral(S(t)dt,a,x) | -//+------------------------------------------------------------------+ -static double CSpline1D::Spline1DIntegrate(CSpline1DInterpolant &c,double x) - { -//--- create variables - double result=0; - int n=0; - int i=0; - int j=0; - int l=0; - int r=0; - int m=0; - double w=0; - double v=0; - double t=0; - double intab=0; - double additionalterm=0; -//--- initialization - n=c.m_n; -//--- Periodic splines require special treatment. We make -//--- following transformation: -//--- integral(S(t)dt,A,X)=integral(S(t)dt,A,Z)+AdditionalTerm -//--- here X may lie outside of [A,B],Z lies strictly in [A,B], -//--- AdditionalTerm is equals to integral(S(t)dt,A,B) times some -//--- integer number (may be zero). - if(c.m_periodic && (xc.m_x[c.m_n-1])) - { - //--- compute integral(S(x)dx,A,B) - intab=0; - for(i=0;i<=c.m_n-2;i++) - { - w=c.m_x[i+1]-c.m_x[i]; - m=(c.m_k+1)*i; - intab=intab+c.m_c[m]*w; - v=w; - for(j=1;j<=c.m_k;j++) - { - v=v*w; - intab=intab+c.m_c[m+j]*v/(j+1); - } - } - //--- map X into [A,B] - CApServ::ApPeriodicMap(x,c.m_x[0],c.m_x[c.m_n-1],t); - additionalterm=t*intab; - } - else - additionalterm=0; -//--- Binary search in the [ x[0],...,x[n-2] ] (x[n-1] is not included) - l=0; - r=n-2+1; - while(l!=r-1) - { - m=(l+r)/2; - //--- check - if(c.m_x[m]>=x) - r=m; - else - l=m; - } -//--- Integration - result=0; - for(i=0;i<=l-1;i++) - { - w=c.m_x[i+1]-c.m_x[i]; - m=(c.m_k+1)*i; - result=result+c.m_c[m]*w; - v=w; - //--- calculation - for(j=1;j<=c.m_k;j++) - { - v=v*w; - result=result+c.m_c[m+j]*v/(j+1); - } - } -//--- change values - w=x-c.m_x[l]; - m=(c.m_k+1)*l; - v=w; - result=result+c.m_c[m]*w; -//--- calculation - for(j=1;j<=c.m_k;j++) - { - v=v*w; - result=result+c.m_c[m+j]*v/(j+1); - } -//--- return result - return(result+additionalterm); - } -//+------------------------------------------------------------------+ -//| Internal version of Spline1DConvDiff | -//| Converts from Hermite spline given by grid XOld to new grid X2 | -//| INPUT PARAMETERS: | -//| XOld - old grid | -//| YOld - values at old grid | -//| DOld - first derivative at old grid | -//| N - grid size | -//| X2 - new grid | -//| N2 - new grid size | -//| Y - possibly preallocated output array | -//| (reallocate if too small) | -//| NeedY - do we need Y? | -//| D1 - possibly preallocated output array | -//| (reallocate if too small) | -//| NeedD1 - do we need D1? | -//| D2 - possibly preallocated output array | -//| (reallocate if too small) | -//| NeedD2 - do we need D1? | -//| OUTPUT ARRAYS: | -//| Y - values, if needed | -//| D1 - first derivative, if needed | -//| D2 - second derivative, if needed | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DConvDiffInternal(double &xold[],double &yold[], - double &dold[],const int n, - double &x2[],const int n2, - double &y[],const bool needy, - double &d1[],const bool needd1, - double &d2[],const bool needd2) - { -//--- create variables - int intervalindex=0; - int pointindex=0; - bool havetoadvance; - double c0=0; - double c1=0; - double c2=0; - double c3=0; - double a=0; - double b=0; - double w=0; - double w2=0; - double w3=0; - double fa=0; - double fb=0; - double da=0; - double db=0; - double t=0; -//--- Prepare space - if(needy && CAp::Len(y)=n2) - break; - t=x2[pointindex]; - //--- do we need to advance interval? - havetoadvance=false; - //--- check - if(intervalindex==-1) - havetoadvance=true; - else - { - //--- check - if(intervalindex=b; - } - //--- check - if(havetoadvance) - { - //--- change values - intervalindex=intervalindex+1; - a=xold[intervalindex]; - b=xold[intervalindex+1]; - w=b-a; - w2=w*w; - w3=w*w2; - fa=yold[intervalindex]; - fb=yold[intervalindex+1]; - da=dold[intervalindex]; - db=dold[intervalindex+1]; - c0=fa; - c1=da; - c2=(3*(fb-fa)-2*da*w-db*w)/w2; - c3=(2*(fa-fb)+da*w+db*w)/w3; - continue; - } - //--- Calculate spline and its derivatives using power basis - t=t-a; - if(needy) - y[pointindex]=c0+t*(c1+t*(c2+t*c3)); - //--- check - if(needd1) - d1[pointindex]=c1+2*t*c2+3*t*t*c3; - //--- check - if(needd2) - d2[pointindex]=2*c2+6*t*c3; - //--- change value - pointindex=pointindex+1; - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine. Heap sort. | -//+------------------------------------------------------------------+ -static void CSpline1D::HeapSortDPoints(double &x[],double &y[],double &d[], - const int n) - { -//--- create variables - int i=0; - int i_=0; -//--- create arrays - double rbuf[]; - int ibuf[]; - double rbuf2[]; - int ibuf2[]; -//--- allocation - ArrayResizeAL(ibuf,n); - ArrayResizeAL(rbuf,n); - for(i=0;i<=n-1;i++) - ibuf[i]=i; -//--- function call - CTSort::TagSortFastI(x,ibuf,rbuf2,ibuf2,n); -//--- copy - for(i=0;i<=n-1;i++) - rbuf[i]=y[ibuf[i]]; - for(i_=0;i_<=n-1;i_++) - y[i_]=rbuf[i_]; - for(i=0;i<=n-1;i++) - rbuf[i]=d[ibuf[i]]; - for(i_=0;i_<=n-1;i_++) - d[i_]=rbuf[i_]; - } -//+------------------------------------------------------------------+ -//| Internal version of Spline1DGridDiffCubic. | -//| Accepts pre-ordered X/Y, temporary arrays (which may be | -//| preallocated, if you want to save time, or not) and output array | -//| (which may be preallocated too). | -//| Y is passed as var-parameter because we may need to force last | -//| element to be equal to the first one (if periodic boundary | -//| conditions are specified). | -//+------------------------------------------------------------------+ -static void CSpline1D::Spline1DGridDiffCubicInternal(double &x[],double &y[], - const int n,const int boundltype, - const double boundl, - const int boundrtype, - const double boundr, - double &d[],double &a1[], - double &a2[],double &a3[], - double &b[],double &dt[]) - { -//--- create variables - int i=0; - int i_=0; -//--- allocate arrays - if(CAp::Len(d)=0;k--) - x[k]=(d[k]-c[k]*x[k+1])/b[k]; - } -//+------------------------------------------------------------------+ -//| Internal subroutine. Cyclic tridiagonal solver. Solves | -//| ( B[0] C[0] A[0] ) | -//| ( A[1] B[1] C[1] ) | -//| ( A[2] B[2] C[2] ) | -//| ( .......... ) * X=D | -//| ( .......... ) | -//| ( A[N-2] B[N-2] C[N-2] ) | -//| ( C[N-1] A[N-1] B[N-1] ) | -//+------------------------------------------------------------------+ -static void CSpline1D::SolveCyclicTridiagonal(double &a[],double &cb[], - double &c[],double &d[], - const int n,double &x[]) - { -//--- create variables - int k=0; - double alpha=0; - double beta=0; - double gamma=0; -//--- create arrays - double y[]; - double z[]; - double u[]; - double b[]; -//--- copy array - ArrayCopy(b,cb); -//--- check - if(CAp::Len(x)0 | -//| * if given, only leading N elements of X/Y are used | -//| * if not given, automatically determined from sizes | -//| of X/Y | -//| M - number of basis functions (= polynomial_degree + 1), | -//| M>=1 | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearW() subroutine: | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| P - interpolant in barycentric form. | -//| Rep - report, same format as in LSFitLinearW() subroutine. | -//| Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| NOTES: | -//| you can convert P from barycentric form to the power or | -//| Chebyshev basis with PolynomialBar2Pow() or | -//| PolynomialBar2Cheb() functions from POLINT subpackage. | -//+------------------------------------------------------------------+ -static void CLSFit::PolynomialFit(double &x[],double &y[],const int n, - const int m,int &info, - CBarycentricInterpolant &p, - CPolynomialFitReport &rep) - { -//--- create a variable - int i=0; -//--- create arrays - double w[]; - double xc[]; - double yc[]; - int dc[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": M<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)0. | -//| * if given, only leading N elements of X/Y/W are used| -//| * if not given, automatically determined from sizes | -//| of X/Y/W | -//| XC - points where polynomial values/derivatives are | -//| constrained, array[0..K-1]. | -//| YC - values of constraints, array[0..K-1] | -//| DC - array[0..K-1], types of constraints: | -//| * DC[i]=0 means that P(XC[i])=YC[i] | -//| * DC[i]=1 means that P'(XC[i])=YC[i] | -//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS | -//| K - number of constraints, 0<=K=1 | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearW() subroutine: | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| P - interpolant in barycentric form. | -//| Rep - report, same format as in LSFitLinearW() subroutine. | -//| Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//| NOTES: | -//| you can convert P from barycentric form to the power or | -//| Chebyshev basis with PolynomialBar2Pow() or | -//| PolynomialBar2Cheb() functions from POLINT subpackage. | -//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: | -//| Setting constraints can lead to undesired results, like | -//| ill-conditioned behavior, or inconsistency being detected. | -//| From the other side, it allows us to improve quality of the fit. | -//| Here we summarize our experience with constrained regression | -//| splines: | -//| * even simple constraints can be inconsistent, see Wikipedia | -//| article on this subject: | -//| http://en.wikipedia.org/wiki/Birkhoff_interpolation | -//| * the greater is M (given fixed constraints), the more chances | -//| that constraints will be consistent | -//| * in the general case, consistency of constraints is NOT | -//| GUARANTEED. | -//| * in the one special cases, however, we can guarantee | -//| consistency. This case is: M>1 and constraints on the | -//| function values (NOT DERIVATIVES) | -//| Our final recommendation is to use constraints WHEN AND ONLY when| -//| you can't solve your task without them. Anything beyond special | -//| cases given above is not guaranteed and may result in | -//| inconsistency. | -//+------------------------------------------------------------------+ -static void CLSFit::PolynomialFitWC(double &cx[],double &cy[],double &cw[], - const int n,double &cxc[],double &cyc[], - int &dc[],const int k,const int m, - int &info,CBarycentricInterpolant &p, - CPolynomialFitReport &rep) - { -//--- create variables - double xa=0; - double xb=0; - double sa=0; - double sb=0; - int i=0; - int j=0; - double u=0; - double v=0; - double s=0; - int relcnt=0; -//--- create arrays - double xoriginal[]; - double yoriginal[]; - double y2[]; - double w2[]; - double tmp[]; - double tmp2[]; - double bx[]; - double by[]; - double bw[]; - double x[]; - double y[]; - double w[]; - double xc[]; - double yc[]; -//--- object of class - CLSFitReport lrep; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(w,cw); - ArrayCopy(xc,cxc); - ArrayCopy(yc,cyc); -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": M<=0!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(k=M!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(W)=k,__FUNCTION__+": Length(XC)=k,__FUNCTION__+": Length(YC)=k,__FUNCTION__+": Length(DC)0. | -//| XC - points where function values/derivatives are | -//| constrained, array[0..K-1]. | -//| YC - values of constraints, array[0..K-1] | -//| DC - array[0..K-1], types of constraints: | -//| * DC[i]=0 means that S(XC[i])=YC[i] | -//| * DC[i]=1 means that S'(XC[i])=YC[i] | -//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS | -//| K - number of constraints, 0<=K=2. | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearWC() subroutine. | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| -1 means another errors in parameters | -//| passed (N<=0, for example) | -//| B - barycentric interpolant. | -//| Rep - report, same format as in LSFitLinearWC() subroutine.| -//| Following fields are set: | -//| * DBest best value of the D parameter | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroutine doesn't calculate task's condition number | -//| for K<>0. | -//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: | -//| Setting constraints can lead to undesired results, like | -//| ill-conditioned behavior, or inconsistency being detected. From | -//| the other side, it allows us to improve quality of the fit. Here | -//| we summarize our experience with constrained barycentric | -//| interpolants: | -//| * excessive constraints can be inconsistent. Floater-Hormann | -//| basis functions aren't as flexible as splines (although they | -//| are very smooth). | -//| * the more evenly constraints are spread across [min(x),max(x)], | -//| the more chances that they will be consistent | -//| * the greater is M (given fixed constraints), the more chances | -//| that constraints will be consistent | -//| * in the general case, consistency of constraints IS NOT | -//| GUARANTEED. | -//| * in the several special cases, however, we CAN guarantee | -//| consistency. | -//| * one of this cases is constraints on the function VALUES at the | -//| interval boundaries. Note that consustency of the constraints | -//| on the function DERIVATIVES is NOT guaranteed (you can use in | -//| such cases cubic splines which are more flexible). | -//| * another special case is ONE constraint on the function value | -//| (OR, but not AND, derivative) anywhere in the interval | -//| Our final recommendation is to use constraints WHEN AND ONLY | -//| WHEN you can't solve your task without them. Anything beyond | -//| special cases given above is not guaranteed and may result in | -//| inconsistency. | -//+------------------------------------------------------------------+ -static void CLSFit::BarycentricFitFloaterHormannWC(double &x[],double &y[], - double &w[],const int n, - double &xc[],double &yc[], - int &dc[],const int k, - const int m,int &info, - CBarycentricInterpolant &b, - CBarycentricFitReport &rep) - { -//--- create variables - int d=0; - int i=0; - double wrmscur=0; - double wrmsbest=0; - int locinfo=0; -//--- objects of classes - CBarycentricInterpolant locb; - CBarycentricFitReport locrep; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": M<=0!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(k=M!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(W)=k,__FUNCTION__+": Length(XC)=k,__FUNCTION__+": Length(YC)=k,__FUNCTION__+": Length(DC)0,__FUNCTION__+": unexpected result from BarycentricFitWCFixedD!")) - return; - //--- check - if(locinfo>0) - { - //--- Calculate weghted RMS - wrmscur=0; - for(i=0;i<=n-1;i++) - wrmscur=wrmscur+CMath::Sqr(w[i]*(y[i]-CRatInt::BarycentricCalc(locb,x[i]))); - wrmscur=MathSqrt(wrmscur/n); - //--- check - if(wrmscur0. | -//| M - number of basis functions ( = number_of_nodes), M>=2.| -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearWC() subroutine. | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| B - barycentric interpolant. | -//| Rep - report, same format as in LSFitLinearWC() subroutine.| -//| Following fields are set: | -//| * DBest best value of the D parameter | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//+------------------------------------------------------------------+ -static void CLSFit::BarycentricFitFloaterHormann(double &x[],double &y[], - const int n,const int m, - int &info,CBarycentricInterpolant &b, - CBarycentricFitReport &rep) - { -//--- create arrays - double w[]; - double xc[]; - double yc[]; - int dc[]; -//--- create a variable - int i=0; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": M<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)0. | -//| M - number of basis functions ( = number_of_nodes), M>=2.| -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearWC() subroutine. | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| B - barycentric interpolant. | -//| Rep - report, same format as in LSFitLinearWC() subroutine.| -//| Following fields are set: | -//| * DBest best value of the D parameter | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//+------------------------------------------------------------------+ -static void CLSFit::Spline1DFitPenalized(double &cx[],double &cy[], - const int n,const int m, - const double rho,int &info, - CSpline1DInterpolant &s, - CSpline1DFitReport &rep) - { -//--- create a variable - int i=0; -//--- create arrays - double w[]; - double x[]; - double y[]; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)0 | -//| * if given, only first N elements of X/Y/W are | -//| processed | -//| * if not given, automatically determined from X/Y/W | -//| sizes | -//| M - number of basis functions ( = number_of_nodes), M>=4.| -//| Rho - regularization constant passed by user. It penalizes | -//| nonlinearity in the regression spline. It is | -//| logarithmically scaled, i.e. actual value of | -//| regularization constant is calculated as 10^Rho. It | -//| is automatically scaled so that: | -//| * Rho=2.0 corresponds to moderate amount of | -//| nonlinearity | -//| * generally, it should be somewhere in the | -//| [-8.0,+8.0] | -//| If you do not want to penalize nonlineary, | -//| pass small Rho. Values as low as -15 should work. | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearWC() subroutine. | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| or Cholesky decomposition; problem | -//| may be too ill-conditioned (very | -//| rare) | -//| S - spline interpolant. | -//| Rep - Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//| NOTE 1: additional nodes are added to the spline outside of the | -//| fitting interval to force linearity when xmax(x,xc). It is done for consistency - we penalize | -//| non-linearity at [min(x,xc),max(x,xc)], so it is natural to | -//| force linearity outside of this interval. | -//| NOTE 2: function automatically sorts points, so caller may pass | -//| unsorted array. | -//+------------------------------------------------------------------+ -static void CLSFit::Spline1DFitPenalizedW(double &cx[],double &cy[], - double &cw[],const int n, - const int m,double rho, - int &info,CSpline1DInterpolant &s, - CSpline1DFitReport &rep) - { -//--- create variables - int i=0; - int j=0; - int b=0; - double v=0; - double relcnt=0; - double xa=0; - double xb=0; - double sa=0; - double sb=0; - double pdecay=0; - double tdecay=0; - double fdmax=0; - double admax=0; - double fa=0; - double ga=0; - double fb=0; - double gb=0; - double lambdav=0; - int i_=0; - int i1_=0; -//--- create arrays - double xoriginal[]; - double yoriginal[]; - double fcolumn[]; - double y2[]; - double w2[]; - double xc[]; - double yc[]; - int dc[]; - double bx[]; - double by[]; - double bd1[]; - double bd2[]; - double tx[]; - double ty[]; - double td[]; - double rightpart[]; - double c[]; - double tmp0[]; - double x[]; - double y[]; - double w[]; -//--- create matrix - CMatrixDouble fmatrix; - CMatrixDouble amatrix; - CMatrixDouble d2matrix; - CMatrixDouble nmatrix; -//--- objects of classes - CSpline1DInterpolant bs; - CFblsLinCgState cgstate; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(w,cw); -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(W)v) - rho=v; - lambdav=MathPow(10,rho); -//--- Sort X,Y,W - CSpline1D::HeapSortDPoints(x,y,w,n); -//--- Scale X,Y,XC,YC - LSFitScaleXY(x,y,w,n,xc,yc,dc,0,xa,xb,sa,sb,xoriginal,yoriginal); -//--- Allocate space - fmatrix.Resize(n,m); - amatrix.Resize(m,m); - d2matrix.Resize(m,m); - ArrayResizeAL(bx,m); - ArrayResizeAL(by,m); - ArrayResizeAL(fcolumn,n); - nmatrix.Resize(m,m); - ArrayResizeAL(rightpart,m); - ArrayResizeAL(tmp0,MathMax(m,n)); - ArrayResizeAL(c,m); -//--- Fill: -//--- * FMatrix by values of basis functions -//--- * TmpAMatrix by second derivatives of I-th function at J-th point -//--- * CMatrix by constraints - fdmax=0; - for(b=0;b<=m-1;b++) - { - //--- Prepare I-th basis function - for(j=0;j<=m-1;j++) - { - bx[j]=(double)(2*j)/(double)(m-1)-1; - by[j]=0; - } - by[b]=1; - //--- function call - CSpline1D::Spline1DGridDiff2Cubic(bx,by,m,2,0.0,2,0.0,bd1,bd2); - //--- function call - CSpline1D::Spline1DBuildCubic(bx,by,m,2,0.0,2,0.0,bs); - //--- Calculate B-th column of FMatrix - //--- Update FDMax (maximum column norm) - CSpline1D::Spline1DConvCubic(bx,by,m,2,0.0,2,0.0,x,n,fcolumn); - for(i_=0;i_<=n-1;i_++) - fmatrix[i_].Set(b,fcolumn[i_]); - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(w[i]*fcolumn[i]); - fdmax=MathMax(fdmax,v); - //--- Fill temporary with second derivatives of basis function - for(i_=0;i_<=m-1;i_++) - d2matrix[b].Set(i_,bd2[i_]); - } -//--- * calculate penalty matrix A -//--- * calculate max of diagonal elements of A -//--- * calculate PDecay - coefficient before penalty matrix - for(i=0;i<=m-1;i++) - { - for(j=i;j<=m-1;j++) - { - //--- calculate integral(B_i''*B_j'') where B_i and B_j are - //--- i-th and j-th basis splines. - //--- B_i and B_j are piecewise linear functions. - v=0; - for(b=0;b<=m-2;b++) - { - //--- change values - fa=d2matrix[i][b]; - fb=d2matrix[i][b+1]; - ga=d2matrix[j][b]; - gb=d2matrix[j][b+1]; - v=v+(bx[b+1]-bx[b])*(fa*ga+(fa*(gb-ga)+ga*(fb-fa))/2+(fb-fa)*(gb-ga)/3); - } - amatrix[i].Set(j,v); - amatrix[j].Set(i,v); - } - } -//--- change values - admax=0; - for(i=0;i<=m-1;i++) - admax=MathMax(admax,MathAbs(amatrix[i][i])); - pdecay=lambdav*fdmax/admax; -//--- Calculate TDecay for Tikhonov regularization - tdecay=fdmax*(1+pdecay)*10*CMath::m_machineepsilon; -//--- Prepare system -//--- NOTE: FMatrix is spoiled during this process - for(i=0;i<=n-1;i++) - { - v=w[i]; - for(i_=0;i_<=m-1;i_++) - fmatrix[i].Set(i_,v*fmatrix[i][i_]); - } -//--- function call - CAblas::RMatrixGemm(m,m,n,1.0,fmatrix,0,0,1,fmatrix,0,0,0,0.0,nmatrix,0,0); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=m-1;j++) - nmatrix[i].Set(j,nmatrix[i][j]+pdecay*amatrix[i][j]); - } -//--- calculation - for(i=0;i<=m-1;i++) - nmatrix[i].Set(i,nmatrix[i][i]+tdecay); - for(i=0;i<=m-1;i++) - rightpart[i]=0; -//--- change values - for(i=0;i<=n-1;i++) - { - v=y[i]*w[i]; - for(i_=0;i_<=m-1;i_++) - rightpart[i_]=rightpart[i_]+v*fmatrix[i][i_]; - } -//--- Solve system - if(!CTrFac::SPDMatrixCholesky(nmatrix,m,true)) - { - info=-4; - return; - } -//--- function call - CFbls::FblsCholeskySolve(nmatrix,1.0,m,true,rightpart,tmp0); -//--- copy - for(i_=0;i_<=m-1;i_++) - c[i_]=rightpart[i_]; -//--- add nodes to force linearity outside of the fitting interval - CSpline1D::Spline1DGridDiffCubic(bx,c,m,2,0.0,2,0.0,bd1); -//--- allocation - ArrayResizeAL(tx,m+2); - ArrayResizeAL(ty,m+2); - ArrayResizeAL(td,m+2); -//--- copy - i1_=-1; - for(i_=1;i_<=m;i_++) - tx[i_]=bx[i_+i1_]; - i1_=-1; - for(i_=1;i_<=m;i_++) - ty[i_]=rightpart[i_+i1_]; - i1_=-1; - for(i_=1;i_<=m;i_++) - td[i_]=bd1[i_+i1_]; -//--- change values - tx[0]=tx[1]-(tx[2]-tx[1]); - ty[0]=ty[1]-td[1]*(tx[2]-tx[1]); - td[0]=td[1]; - tx[m+1]=tx[m]+(tx[m]-tx[m-1]); - ty[m+1]=ty[m]+td[m]*(tx[m]-tx[m-1]); - td[m+1]=td[m]; -//--- function call - CSpline1D::Spline1DBuildHermite(tx,ty,td,m+2,s); -//--- function call - CSpline1D::Spline1DLinTransX(s,2/(xb-xa),-((xa+xb)/(xb-xa))); -//--- function call - CSpline1D::Spline1DLinTransY(s,sb-sa,sa); -//--- change value - info=1; -//--- Fill report - rep.m_rmserror=0; - rep.m_avgerror=0; - rep.m_avgrelerror=0; - rep.m_maxerror=0; - relcnt=0; -//--- function call - CSpline1D::Spline1DConvCubic(bx,rightpart,m,2,0.0,2,0.0,x,n,fcolumn); -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- change values - v=(sb-sa)*fcolumn[i]+sa; - rep.m_rmserror=rep.m_rmserror+CMath::Sqr(v-yoriginal[i]); - rep.m_avgerror=rep.m_avgerror+MathAbs(v-yoriginal[i]); - //--- check - if(yoriginal[i]!=0.0) - { - rep.m_avgrelerror=rep.m_avgrelerror+MathAbs(v-yoriginal[i])/MathAbs(yoriginal[i]); - relcnt=relcnt+1; - } - rep.m_maxerror=MathMax(rep.m_maxerror,MathAbs(v-yoriginal[i])); - } -//--- change values - rep.m_rmserror=MathSqrt(rep.m_rmserror/n); - rep.m_avgerror=rep.m_avgerror/n; -//--- check - if(relcnt!=0.0) - rep.m_avgrelerror=rep.m_avgrelerror/relcnt; - } -//+------------------------------------------------------------------+ -//| Weighted fitting by cubic spline, with constraints on function | -//| values or derivatives. | -//| Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used | -//| to build basis functions. Basis functions are cubic splines with | -//| continuous second derivatives and non-fixed first derivatives at | -//| interval ends. Small regularizing term is used when solving | -//| constrained tasks (to improve stability). | -//| Task is linear, so linear least squares solver is used. | -//| Complexity of this computational scheme is O(N*M^2), mostly | -//| dominated by least squares solver | -//| SEE ALSO | -//| Spline1DFitHermiteWC() - fitting by Hermite splines (more | -//| flexible, less smooth) | -//| Spline1DFitCubic() - "lightweight" fitting by cubic | -//| splines, without invididual | -//| weights and constraints | -//| INPUT PARAMETERS: | -//| X - points, array[0..N-1]. | -//| Y - function values, array[0..N-1]. | -//| W - weights, array[0..N-1] | -//| Each summand in square sum of approximation | -//| deviations from given values is multiplied by the | -//| square of corresponding weight. Fill it by 1's if you| -//| don't want to solve weighted task. | -//| N - number of points (optional): | -//| * N>0 | -//| * if given, only first N elements of X/Y/W are | -//| processed | -//| * if not given, automatically determined from X/Y/W | -//| sizes | -//| XC - points where spline values/derivatives are | -//| constrained, array[0..K-1]. | -//| YC - values of constraints, array[0..K-1] | -//| DC - array[0..K-1], types of constraints: | -//| * DC[i]=0 means that S(XC[i])=YC[i] | -//| * DC[i]=1 means that S'(XC[i])=YC[i] | -//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS | -//| K - number of constraints (optional): | -//| * 0<=K=4. | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearWC() subroutine. | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| S - spline interpolant. | -//| Rep - report, same format as in LSFitLinearWC() subroutine.| -//| Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//| ORDER OF POINTS | -//| Subroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: | -//| Setting constraints can lead to undesired results, like | -//| ill-conditioned behavior, or inconsistency being detected. From | -//| the other side, it allows us to improve quality of the fit. | -//| Here we summarize our experience with constrained regression | -//| splines: | -//| * excessive constraints can be inconsistent. Splines are | -//| piecewise cubic functions, and it is easy to create an | -//| example, where large number of constraints concentrated in | -//| small area will result in inconsistency. Just because spline | -//| is not flexible enough to satisfy all of them. And same | -//| constraints spread across the [min(x),max(x)] will be | -//| perfectly consistent. | -//| * the more evenly constraints are spread across [min(x),max(x)], | -//| the more chances that they will be consistent | -//| * the greater is M (given fixed constraints), the more chances | -//| that constraints will be consistent | -//| * in the general case, consistency of constraints IS NOT | -//| GUARANTEED. | -//| * in the several special cases, however, we CAN guarantee | -//| consistency. | -//| * one of this cases is constraints on the function values | -//| AND/OR its derivatives at the interval boundaries. | -//| * another special case is ONE constraint on the function value | -//| (OR, but not AND, derivative) anywhere in the interval | -//| Our final recommendation is to use constraints WHEN AND ONLY WHEN| -//| you can't solve your task without them. Anything beyond special | -//| cases given above is not guaranteed and may result in | -//| inconsistency. | -//+------------------------------------------------------------------+ -static void CLSFit::Spline1DFitCubicWC(double &x[],double &y[],double &w[], - const int n,double &xc[],double &yc[], - int &dc[],const int k,const int m, - int &info,CSpline1DInterpolant &s, - CSpline1DFitReport &rep) - { -//--- create a variable - int i=0; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(k=M!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(W)=k,__FUNCTION__+": Length(XC)=k,__FUNCTION__+": Length(YC)=k,__FUNCTION__+": Length(DC)0 | -//| * if given, only first N elements of X/Y/W are | -//| processed | -//| * if not given, automatically determined from X/Y/W | -//| sizes | -//| XC - points where spline values/derivatives are | -//| constrained, array[0..K-1]. | -//| YC - values of constraints, array[0..K-1] | -//| DC - array[0..K-1], types of constraints: | -//| * DC[i]=0 means that S(XC[i])=YC[i] | -//| * DC[i]=1 means that S'(XC[i])=YC[i] | -//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS | -//| K - number of constraints (optional): | -//| * 0<=K=4, | -//| M IS EVEN! | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearW() subroutine: | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| -2 means odd M was passed (which is not | -//| supported) | -//| -1 means another errors in parameters | -//| passed (N<=0, for example) | -//| S - spline interpolant. | -//| Rep - report, same format as in LSFitLinearW() subroutine. | -//| Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//| IMPORTANT: | -//| this subroitine supports only even M's | -//| ORDER OF POINTS | -//| ubroutine automatically sorts points, so caller may pass | -//| unsorted array. | -//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: | -//| Setting constraints can lead to undesired results, like | -//| ill-conditioned behavior, or inconsistency being detected. From | -//| the other side, it allows us to improve quality of the fit. Here | -//| we summarize our experience with constrained regression splines:| -//| * excessive constraints can be inconsistent. Splines are | -//| piecewise cubic functions, and it is easy to create an example,| -//| where large number of constraints concentrated in small area | -//| will result in inconsistency. Just because spline is not | -//| flexible enough to satisfy all of them. And same constraints | -//| spread across the [min(x),max(x)] will be perfectly consistent.| -//| * the more evenly constraints are spread across [min(x),max(x)], | -//| the more chances that they will be consistent | -//| * the greater is M (given fixed constraints), the more chances | -//| that constraints will be consistent | -//| * in the general case, consistency of constraints is NOT | -//| GUARANTEED. | -//| * in the several special cases, however, we can guarantee | -//| consistency. | -//| * one of this cases is M>=4 and constraints on the function | -//| value (AND/OR its derivative) at the interval boundaries. | -//| * another special case is M>=4 and ONE constraint on the | -//| function value (OR, BUT NOT AND, derivative) anywhere in | -//| [min(x),max(x)] | -//| Our final recommendation is to use constraints WHEN AND ONLY when| -//| you can't solve your task without them. Anything beyond special | -//| cases given above is not guaranteed and may result in | -//| inconsistency. | -//+------------------------------------------------------------------+ -static void CLSFit::Spline1DFitHermiteWC(double &x[],double &y[],double &w[], - const int n,double &xc[],double &yc[], - int &dc[],const int k,const int m, - int &info,CSpline1DInterpolant &s, - CSpline1DFitReport &rep) - { -//--- create a variable - int i=0; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(m%2==0,__FUNCTION__+": M is odd!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(k=M!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=n,__FUNCTION__+": Length(W)=k,__FUNCTION__+": Length(XC)=k,__FUNCTION__+": Length(YC)=k,__FUNCTION__+": Length(DC)=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=4,__FUNCTION__+": M<4!")) - return; -//--- check - if(!CAp::Assert(m%2==0,__FUNCTION__+": M is odd!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(Y)=1. | -//| M - number of basis functions, M>=1. | -//| OUTPUT PARAMETERS: | -//| Info - error code: | -//| * -4 internal SVD decomposition subroutine | -//| failed (very rare and for degenerate | -//| systems only) | -//| * -1 incorrect N/M were specified | -//| * 1 task is solved | -//| C - decomposition coefficients, array[0..M-1] | -//| Rep - fitting report. Following fields are set: | -//| * Rep.TaskRCond reciprocal of condition | -//| number | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the| -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE | -//| CALCULATED | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix, - const int n,const int m,int &info, - double &c[],CLSFitReport &rep) - { -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": length(W)=n,__FUNCTION__+": rows(FMatrix)=m,__FUNCTION__+": cols(FMatrix)=1. | -//| M - number of basis functions, M>=1. | -//| K - number of constraints, 0 <= K < M | -//| K=0 corresponds to absence of constraints. | -//| OUTPUT PARAMETERS: | -//| Info - error code: | -//| * -4 internal SVD decomposition subroutine | -//| failed (very rare and for degenerate | -//| systems only) | -//| * -3 either too many constraints (M or more), | -//| degenerate constraints (some constraints | -//| are repetead twice) or inconsistent | -//| constraints were specified. | -//| * 1 task is solved | -//| C - decomposition coefficients, array[0..M-1] | -//| Rep - fitting report. Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the| -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE | -//| CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitLinearWC(double &cy[],double &w[],CMatrixDouble &fmatrix, - CMatrixDouble &ccmatrix,const int n, - const int m,const int k,int &info, - double &c[],CLSFitReport &rep) - { -//--- create variables - int i=0; - int j=0; - double v=0; - int i_=0; -//--- create arrays - double tau[]; - double tmp[]; - double c0[]; - double y[]; -//--- create matrix - CMatrixDouble q; - CMatrixDouble f2; - CMatrixDouble cmatrix; -//--- copy array - ArrayCopy(y,cy); -//--- copy matrix - cmatrix=ccmatrix; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": length(W)=n,__FUNCTION__+": rows(FMatrix)=m,__FUNCTION__+": cols(FMatrix)=k,__FUNCTION__+": rows(CMatrix)=m+1 || k==0,__FUNCTION__+": cols(CMatrix)=m) - { - info=-3; - return; - } -//--- Solve - if(k==0) - { - //--- no constraints - LSFitLinearInternal(y,w,fmatrix,n,m,info,c,rep); - } - else - { - //--- First,find general form solution of constraints system: - //--- * factorize C=L*Q - //--- * unpack Q - //--- * fill upper part of C with zeros (for RCond) - //--- We got C=C0+Q2'*y where Q2 is lower M-K rows of Q. - COrtFac::RMatrixLQ(cmatrix,k,m,tau); - COrtFac::RMatrixLQUnpackQ(cmatrix,k,m,tau,m,q); - for(i=0;i<=k-1;i++) - { - for(j=i+1;j<=m-1;j++) - cmatrix[i].Set(j,0.0); - } - //--- check - if(CRCond::RMatrixLURCondInf(cmatrix,k)<1000*CMath::m_machineepsilon) - { - info=-3; - return; - } - //--- allocation - ArrayResizeAL(tmp,k); - //--- calculation - for(i=0;i<=k-1;i++) - { - //--- check - if(i>0) - { - v=0.0; - for(i_=0;i_<=i-1;i_++) - v+=cmatrix[i][i_]*tmp[i_]; - } - else - v=0; - //--- change values - tmp[i]=(cmatrix[i][m]-v)/cmatrix[i][i]; - } - //--- allocation - ArrayResizeAL(c0,m); - //--- calculation - for(i=0;i<=m-1;i++) - c0[i]=0; - for(i=0;i<=k-1;i++) - { - v=tmp[i]; - for(i_=0;i_<=m-1;i_++) - c0[i_]=c0[i_]+v*q[i][i_]; - } - //--- Second,prepare modified matrix F2=F*Q2' and solve modified task - ArrayResizeAL(tmp,MathMax(n,m)+1); - f2.Resize(n,m-k); - //--- function call - CBlas::MatrixVectorMultiply(fmatrix,0,n-1,0,m-1,false,c0,0,m-1,-1.0,y,0,n-1,1.0); - //--- function call - CBlas::MatrixMatrixMultiply(fmatrix,0,n-1,0,m-1,false,q,k,m-1,0,m-1,true,1.0,f2,0,n-1,0,m-k-1,0.0,tmp); - //--- function call - LSFitLinearInternal(y,w,f2,n,m-k,info,tmp,rep); - rep.m_taskrcond=-1; - //--- check - if(info<=0) - return; - //--- then,convert back to original answer: C=C0 + Q2'*Y0 - ArrayResizeAL(c,m); - for(i_=0;i_<=m-1;i_++) - c[i_]=c0[i_]; - //--- function call - CBlas::MatrixVectorMultiply(q,k,m-1,0,m-1,true,tmp,0,m-k-1,1.0,c,0,m-1,1.0); - } - } -//+------------------------------------------------------------------+ -//| Linear least squares fitting. | -//| QR decomposition is used to reduce task to MxM, then triangular | -//| solver or SVD-based solver is used depending on condition number | -//| of the system. It allows to maximize speed and retain decent | -//| accuracy. | -//| INPUT PARAMETERS: | -//| Y - array[0..N-1] Function values in N points. | -//| FMatrix - a table of basis functions values, | -//| array[0..N-1, 0..M-1]. | -//| FMatrix[I, J] - value of J-th basis function in | -//| I-th point. | -//| N - number of points used. N>=1. | -//| M - number of basis functions, M>=1. | -//| OUTPUT PARAMETERS: | -//| Info - error code: | -//| * -4 internal SVD decomposition subroutine | -//| failed (very rare and for degenerate | -//| systems only) | -//| * 1 task is solved | -//| C - decomposition coefficients, array[0..M-1] | -//| Rep - fitting report. Following fields are set: | -//| * Rep.TaskRCond reciprocal of condition | -//| number | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the| -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE | -//| CALCULATED | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitLinear(double &y[],CMatrixDouble &fmatrix, - const int n,const int m,int &info, - double &c[],CLSFitReport &rep) - { -//--- create a variable - int i=0; -//--- create array - double w[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": rows(FMatrix)=m,__FUNCTION__+": cols(FMatrix)=1. | -//| M - number of basis functions, M>=1. | -//| K - number of constraints, 0 <= K < M | -//| K=0 corresponds to absence of constraints. | -//| OUTPUT PARAMETERS: | -//| Info - error code: | -//| * -4 internal SVD decomposition subroutine | -//| failed (very rare and for degenerate | -//| systems only) | -//| * -3 either too many constraints (M or more), | -//| degenerate constraints (some constraints | -//| are repetead twice) or inconsistent | -//| constraints were specified. | -//| * 1 task is solved | -//| C - decomposition coefficients, array[0..M-1] | -//| Rep - fitting report. Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the| -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE | -//| CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number | -//| for K<>0. | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitLinearC(double &cy[],CMatrixDouble &fmatrix, - CMatrixDouble &cmatrix,const int n, - const int m,const int k,int &info, - double &c[],CLSFitReport &rep) - { -//--- create a variable - int i=0; -//--- create arrays - double w[]; - double y[]; -//--- copy array - ArrayCopy(y,cy); -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(y)>=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": rows(FMatrix)=m,__FUNCTION__+": cols(FMatrix)=k,__FUNCTION__+": rows(CMatrix)=m+1 || k==0,__FUNCTION__+": cols(CMatrix)1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| DiffStep- numerical differentiation step; | -//| should not be very small or large; | -//| large = loss of accuracy | -//| small = growth of round-off errors | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[], - double &c[],const int n,const int m, - const int k,const double diffstep, - CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": length(W)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)0.0,__FUNCTION__+": DiffStep<=0!")) - return; -//--- initialization - state.m_npoints=n; - state.m_nweights=n; - state.m_wkind=1; - state.m_m=m; - state.m_k=k; -//--- function call - LSFitSetCond(state,0.0,0.0,0); -//--- function call - LSFitSetStpMax(state,0.0); -//--- function call - LSFitSetXRep(state,false); -//--- allocation - state.m_taskx.Resize(n,m); - ArrayResizeAL(state.m_tasky,n); - ArrayResizeAL(state.m_w,n); - ArrayResizeAL(state.m_c,k); - ArrayResizeAL(state.m_x,m); -//--- copy - for(i_=0;i_<=k-1;i_++) - state.m_c[i_]=c[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_w[i_]=w[i_]; - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=m-1;i_++) - state.m_taskx[i].Set(i_,x[i][i_]); - state.m_tasky[i]=y[i]; - } -//--- allocation - ArrayResizeAL(state.m_s,k); - ArrayResizeAL(state.m_bndl,k); - ArrayResizeAL(state.m_bndu,k); -//--- change values - for(i=0;i<=k-1;i++) - { - state.m_s[i]=1.0; - state.m_bndl[i]=CInfOrNaN::NegativeInfinity(); - state.m_bndu[i]=CInfOrNaN::PositiveInfinity(); - } -//--- change values - state.m_optalgo=0; - state.m_prevnpt=-1; - state.m_prevalgo=-1; -//--- function call - CMinLM::MinLMCreateV(k,n,state.m_c,diffstep,state.m_optstate); -//--- function call - LSFitClearRequestFields(state); -//--- allocation - ArrayResizeAL(state.m_rstate.ia,5); - ArrayResizeAL(state.m_rstate.ra,3); - state.m_rstate.stage=-1; - } -//+------------------------------------------------------------------+ -//| Nonlinear least squares fitting using function values only. | -//| Combination of numerical differentiation and secant updates is | -//| used to obtain function Jacobian. | -//| Nonlinear task min(F(c)) is solved, where | -//| F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, | -//| * N is a number of points, | -//| * M is a dimension of a space points belong to, | -//| * K is a dimension of a space of parameters being fitted, | -//| * w is an N-dimensional vector of weight coefficients, | -//| * x is a set of N points, each of them is an M-dimensional | -//| vector, | -//| * c is a K-dimensional vector of parameters being fitted | -//| This subroutine uses only f(c,x[i]). | -//| INPUT PARAMETERS: | -//| X - array[0..N-1,0..M-1], points (one row = one | -//| point) | -//| Y - array[0..N-1], function values. | -//| C - array[0..K-1], initial approximation to the | -//| solution, | -//| N - number of points, N>1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| DiffStep- numerical differentiation step; | -//| should not be very small or large; | -//| large = loss of accuracy | -//| small = growth of round-off errors | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateF(CMatrixDouble &x,double &y[],double &c[], - const int n,const int m,const int k, - const double diffstep,CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)0.0,__FUNCTION__+": DiffStep<=0!")) - return; -//--- initialization - state.m_npoints=n; - state.m_wkind=0; - state.m_m=m; - state.m_k=k; -//--- function call - LSFitSetCond(state,0.0,0.0,0); -//--- function call - LSFitSetStpMax(state,0.0); -//--- function call - LSFitSetXRep(state,false); -//--- allocation - state.m_taskx.Resize(n,m); - ArrayResizeAL(state.m_tasky,n); - ArrayResizeAL(state.m_c,k); - ArrayResizeAL(state.m_x,m); -//--- copy - for(i_=0;i_<=k-1;i_++) - state.m_c[i_]=c[i_]; - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=m-1;i_++) - state.m_taskx[i].Set(i_,x[i][i_]); - state.m_tasky[i]=y[i]; - } -//--- allocation - ArrayResizeAL(state.m_s,k); - ArrayResizeAL(state.m_bndl,k); - ArrayResizeAL(state.m_bndu,k); -//--- change values - for(i=0;i<=k-1;i++) - { - state.m_s[i]=1.0; - state.m_bndl[i]=CInfOrNaN::NegativeInfinity(); - state.m_bndu[i]=CInfOrNaN::PositiveInfinity(); - } -//--- change values - state.m_optalgo=0; - state.m_prevnpt=-1; - state.m_prevalgo=-1; -//--- function call - CMinLM::MinLMCreateV(k,n,state.m_c,diffstep,state.m_optstate); -//--- function call - LSFitClearRequestFields(state); -//--- allocation - ArrayResizeAL(state.m_rstate.ia,5); - ArrayResizeAL(state.m_rstate.ra,3); - state.m_rstate.stage=-1; - } -//+------------------------------------------------------------------+ -//| Weighted nonlinear least squares fitting using gradient only. | -//| Nonlinear task min(F(c)) is solved, where | -//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + | -//| + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, | -//| * N is a number of points, | -//| * M is a dimension of a space points belong to, | -//| * K is a dimension of a space of parameters being fitted, | -//| * w is an N-dimensional vector of weight coefficients, | -//| * x is a set of N points, each of them is an M-dimensional | -//| vector, | -//| * c is a K-dimensional vector of parameters being fitted | -//| This subroutine uses only f(c,x[i]) and its gradient. | -//| INPUT PARAMETERS: | -//| X - array[0..N-1,0..M-1], points (one row = one | -//| point) | -//| Y - array[0..N-1], function values. | -//| W - weights, array[0..N-1] | -//| C - array[0..K-1], initial approximation to the | -//| solution, | -//| N - number of points, N>1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| CheapFG - boolean flag, which is: | -//| * True if both function and gradient calculation | -//| complexity are less than O(M^2). An | -//| improved algorithm can be used which | -//| corresponds to FGJ scheme from MINLM unit.| -//| * False otherwise. | -//| Standard Jacibian-bases | -//| Levenberg-Marquardt algo will be used (FJ | -//| scheme). | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| See also: | -//| LSFitResults | -//| LSFitCreateFG (fitting without weights) | -//| LSFitCreateWFGH (fitting using Hessian) | -//| LSFitCreateFGH (fitting using Hessian, without weights) | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[], - double &c[],const int n,const int m, - const int k,bool cheapfg,CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": length(W)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| CheapFG - boolean flag, which is: | -//| * True if both function and gradient calculation| -//| complexity are less than O(M^2). An | -//| improved algorithm can be used which | -//| corresponds to FGJ scheme from MINLM | -//| unit. | -//| * False otherwise. | -//| Standard Jacibian-bases | -//| Levenberg-Marquardt algo will be used | -//| (FJ scheme). | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[], - const int n,const int m,const int k, - const bool cheapfg,CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[], - double &c[],const int n,const int m, - const int k,CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": length(W)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)1 | -//| M - dimension of space | -//| K - number of parameters being fitted | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[], - const int n,const int m,const int k, - CLSFitState &state) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(k>=1,__FUNCTION__+": K<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(c)>=k,__FUNCTION__+": length(C)=n,__FUNCTION__+": length(Y)=n,__FUNCTION__+": rows(X)=m,__FUNCTION__+": cols(X)=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by LSFitSetScale()| -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. Only | -//| Levenberg-Marquardt iterations are counted | -//| (L-BFGS/CG iterations are NOT counted because | -//| their cost is very low compared to that of LM). | -//| NOTE | -//| Passing EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to| -//| automatic stopping criterion selection (according to the scheme | -//| used by MINLM unit). | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitSetCond(CLSFitState &state,const double epsf, - const double epsx,const int maxits) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite!")) - return; -//--- check - if(!CAp::Assert((double)(epsf)>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite!")) - return; -//--- check - if(!CAp::Assert((double)(epsx)>=0.0,__FUNCTION__+": negative EpsX!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- change values - state.m_epsf=epsf; - state.m_epsx=epsx; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//| NOTE: non-zero StpMax leads to moderate performance degradation | -//| because intermediate step of preconditioned L-BFGS optimization | -//| is incompatible with limits on step size. | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitSetStpMax(CLSFitState &state,const double stpmax) - { -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| When reports are needed, State.C (current parameters) and State. | -//| F (current value of fitting function) are reported. | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitSetXRep(CLSFitState &state,const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for underlying optimizer.| -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Generally, scale is NOT considered to be a form of | -//| preconditioner. But LM optimizer is unique in that it uses | -//| scaling matrix both in the stopping condition tests and as | -//| Marquardt damping factor. | -//| Proper scaling is very important for the algorithm performance. | -//| It is less important for the quality of results, but still has | -//| some influence (it is easier to converge when variables are | -//| properly scaled, so premature stopping is possible when very | -//| badly scalled variables are combined with relaxed stopping | -//| conditions). | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitSetScale(CLSFitState &state,double &s[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(s)>=state.m_k,__FUNCTION__+": Length(S)=k,__FUNCTION__+": Length(BndL)=k,__FUNCTION__+": Length(BndU)BndU[i]")) - return; - } - //--- change values - state.m_bndl[i]=bndl[i]; - state.m_bndu[i]=bndu[i]; - } - } -//+------------------------------------------------------------------+ -//| Nonlinear least squares fitting results. | -//| Called after return from LSFitFit(). | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| Info - completetion code: | -//| * 1 relative function improvement is no | -//| more than EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient norm is no more than EpsG | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible | -//| C - array[0..K-1], solution | -//| Rep - optimization report. Following fields are set: | -//| * Rep.TerminationType completetion code: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the| -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE | -//| CALCULATED | -//| * WRMSError weighted rms error on the | -//| (X,Y). | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitResults(CLSFitState &state,int &info,double &c[], - CLSFitReport &rep) - { -//--- create a variable - int i_=0; -//--- initialization - info=state.m_repterminationtype; -//--- check - if(info>0) - { - //--- allocation - ArrayResizeAL(c,state.m_k); - for(i_=0;i_<=state.m_k-1;i_++) - c[i_]=state.m_c[i_]; - //--- change values - rep.m_rmserror=state.m_reprmserror; - rep.m_wrmserror=state.m_repwrmserror; - rep.m_avgerror=state.m_repavgerror; - rep.m_avgrelerror=state.m_repavgrelerror; - rep.m_maxerror=state.m_repmaxerror; - rep.m_iterationscount=state.m_repiterationscount; - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine: automatic scaling for LLS tasks. | -//| NEVER CALL IT DIRECTLY! | -//| Maps abscissas to [-1,1], standartizes ordinates and | -//| correspondingly scales constraints. It also scales weights so | -//| that max(W[i])=1 | -//| Transformations performed: | -//| * X, XC [XA,XB] => [-1,+1] | -//| transformation makes min(X)=-1, max(X)=+1 | -//| * Y [SA,SB] => [0,1] | -//| transformation makes mean(Y)=0, stddev(Y)=1 | -//| * YC transformed accordingly to SA, SB, DC[I] | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitScaleXY(double &x[],double &y[],double &w[], - const int n,double &xc[],double &yc[], - int &dc[],const int k,double &xa, - double &xb,double &sa,double &sb, - double &xoriginal[],double &yoriginal[]) - { -//--- create variables - double xmin=0; - double xmax=0; - int i=0; - double mx=0; - int i_=0; -//--- initialization - xa=0; - xb=0; - sa=0; - sb=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": incorrect N")) - return; -//--- check - if(!CAp::Assert(k>=0,__FUNCTION__+": incorrect K")) - return; -//--- Calculate xmin/xmax. -//--- Force xmin<>xmax. - xmin=x[0]; - xmax=x[0]; - for(i=1;i<=n-1;i++) - { - xmin=MathMin(xmin,x[i]); - xmax=MathMax(xmax,x[i]); - } - for(i=0;i<=k-1;i++) - { - xmin=MathMin(xmin,xc[i]); - xmax=MathMax(xmax,xc[i]); - } -//--- check - if(xmin==xmax) - { - //--- check - if(xmin==0.0) - { - xmin=-1; - xmax=1; - } - else - { - //--- check - if(xmin>0.0) - xmin=0.5*xmin; - else - xmax=0.5*xmax; - } - } -//--- Transform abscissas: map [XA,XB] to [0,1] -//--- Store old X[] in XOriginal[] (it will be used -//--- to calculate relative error). - ArrayResizeAL(xoriginal,n); - for(i_=0;i_<=n-1;i_++) - xoriginal[i_]=x[i_]; -//--- change values - xa=xmin; - xb=xmax; - for(i=0;i<=n-1;i++) - x[i]=2*(x[i]-0.5*(xa+xb))/(xb-xa); -//--- calculation - for(i=0;i<=k-1;i++) - { - //--- check - if(!CAp::Assert(dc[i]>=0,__FUNCTION__+": internal error!")) - return; - xc[i]=2*(xc[i]-0.5*(xa+xb))/(xb-xa); - yc[i]=yc[i]*MathPow(0.5*(xb-xa),dc[i]); - } -//--- Transform function values: map [SA,SB] to [0,1] -//--- SA=mean(Y), -//--- SB=SA+stddev(Y). -//--- Store old Y[] in YOriginal[] (it will be used -//--- to calculate relative error). - ArrayResizeAL(yoriginal,n); - for(i_=0;i_<=n-1;i_++) - yoriginal[i_]=y[i_]; - sa=0; - for(i=0;i<=n-1;i++) - sa=sa+y[i]; - sa=sa/n; -//--- change value - sb=0; - for(i=0;i<=n-1;i++) - sb=sb+CMath::Sqr(y[i]-sa); - sb=MathSqrt(sb/n)+sa; -//--- check - if(sb==sa) - sb=2*sa; -//--- check - if(sb==sa) - sb=sa+1; - for(i=0;i<=n-1;i++) - y[i]=(y[i]-sa)/(sb-sa); - for(i=0;i<=k-1;i++) - { - //--- check - if(dc[i]==0) - yc[i]=(yc[i]-sa)/(sb-sa); - else - yc[i]=yc[i]/(sb-sa); - } -//--- Scale weights - mx=0; - for(i=0;i<=n-1;i++) - mx=MathMax(mx,MathAbs(w[i])); -//--- check - if(mx!=0.0) - { - for(i=0;i<=n-1;i++) - w[i]=w[i]/mx; - } - } -//+------------------------------------------------------------------+ -//| Internal spline fitting subroutine | -//+------------------------------------------------------------------+ -static void CLSFit::Spline1DFitInternal(const int st,double &cx[],double &cy[], - double &cw[],const int n,double &cxc[], - double &cyc[],int &dc[],const int k, - const int m,int &info, - CSpline1DInterpolant &s, - CSpline1DFitReport &rep) - { -//--- create variables - double v0=0; - double v1=0; - double v2=0; - double mx=0; - int i=0; - int j=0; - int relcnt=0; - double xa=0; - double xb=0; - double sa=0; - double sb=0; - double bl=0; - double br=0; - double decay=0; - int i_=0; -//--- create arrays - double y2[]; - double w2[]; - double sx[]; - double sy[]; - double sd[]; - double tmp[]; - double xoriginal[]; - double yoriginal[]; - double x[]; - double y[]; - double w[]; - double xc[]; - double yc[]; -//--- create matrix - CMatrixDouble fmatrix; - CMatrixDouble cmatrix; -//--- objects of classes - CLSFitReport lrep; - CSpline1DInterpolant s2; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(w,cw); - ArrayCopy(xc,cxc); - ArrayCopy(yc,cyc); -//--- initialization - info=0; -//--- check - if(!CAp::Assert(st==0 || st==1,__FUNCTION__+": internal error!")) - return; -//--- check - if(st==0 && m<4) - { - info=-1; - return; - } -//--- check - if(st==1 && m<4) - { - info=-1; - return; - } -//--- check - if((n<1 || k<0) || k>=m) - { - info=-1; - return; - } - for(i=0;i<=k-1;i++) - { - info=0; - //--- check - if(dc[i]<0) - info=-1; - //--- check - if(dc[i]>1) - info=-1; - //--- check - if(info<0) - return; - } -//--- check - if(st==1 && m%2!=0) - { - //--- Hermite fitter must have even number of basis functions - info=-2; - return; - } -//--- weight decay for correct handling of task which becomes -//--- degenerate after constraints are applied - decay=10000*CMath::m_machineepsilon; -//--- Scale X,Y,XC,YC - LSFitScaleXY(x,y,w,n,xc,yc,dc,k,xa,xb,sa,sb,xoriginal,yoriginal); -//--- allocate space,initialize: -//--- * SX - grid for basis functions -//--- * SY - values of basis functions at grid points -//--- * FMatrix- values of basis functions at X[] -//--- * CMatrix- values (derivatives) of basis functions at XC[] - ArrayResizeAL(y2,n+m); - ArrayResizeAL(w2,n+m); - fmatrix.Resize(n+m,m); -//--- check - if(k>0) - cmatrix.Resize(k,m+1); -//--- check - if(st==0) - { - //--- allocate space for cubic spline - ArrayResizeAL(sx,m-2); - ArrayResizeAL(sy,m-2); - for(j=0;j<=m-2-1;j++) - sx[j]=(double)(2*j)/(double)(m-2-1)-1; - } -//--- check - if(st==1) - { - //--- allocate space for Hermite spline - ArrayResizeAL(sx,m/2); - ArrayResizeAL(sy,m/2); - ArrayResizeAL(sd,m/2); - for(j=0;j<=m/2-1;j++) - sx[j]=(double)(2*j)/(double)(m/2-1)-1; - } -//--- Prepare design and constraints matrices: -//--- * fill constraints matrix -//--- * fill first N rows of design matrix with values -//--- * fill next M rows of design matrix with regularizing term -//--- * append M zeros to Y -//--- * append M elements,mean(abs(W)) each,to W - for(j=0;j<=m-1;j++) - { - //--- prepare Jth basis function - if(st==0) - { - //--- cubic spline basis - for(i=0;i<=m-2-1;i++) - sy[i]=0; - bl=0; - br=0; - //--- check - if(j=0 && dc[i]<=2,__FUNCTION__+": internal error!")) - return; - //--- function call - CSpline1D::Spline1DDiff(s2,xc[i],v0,v1,v2); - //--- check - if(dc[i]==0) - cmatrix[i].Set(j,v0); - //--- check - if(dc[i]==1) - cmatrix[i].Set(j,v1); - //--- check - if(dc[i]==2) - cmatrix[i].Set(j,v2); - } - } -//--- calculation - for(i=0;i<=k-1;i++) - cmatrix[i].Set(m,yc[i]); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=m-1;j++) - { - //--- check - if(i==j) - fmatrix[n+i].Set(j,decay); - else - fmatrix[n+i].Set(j,0); - } - } -//--- allocation - ArrayResizeAL(y2,n+m); - ArrayResizeAL(w2,n+m); -//--- copy - for(i_=0;i_<=n-1;i_++) - y2[i_]=y[i_]; - for(i_=0;i_<=n-1;i_++) - w2[i_]=w[i_]; -//--- change value - mx=0; - for(i=0;i<=n-1;i++) - mx=mx+MathAbs(w[i]); - mx=mx/n; - for(i=0;i<=m-1;i++) - { - y2[n+i]=0; - w2[n+i]=mx; - } -//--- Solve constrained task - if(k>0) - { - //--- solve using regularization - LSFitLinearWC(y2,w2,fmatrix,cmatrix,n+m,m,k,info,tmp,lrep); - } - else - { - //--- no constraints,no regularization needed - LSFitLinearWC(y,w,fmatrix,cmatrix,n,m,k,info,tmp,lrep); - } -//--- check - if(info<0) - return; -//--- Generate spline and scale it - if(st==0) - { - //--- cubic spline basis - for(i_=0;i_<=m-2-1;i_++) - sy[i_]=tmp[i_]; - //--- function call - CSpline1D::Spline1DBuildCubic(sx,sy,m-2,1,tmp[m-2],1,tmp[m-1],s); - } -//--- check - if(st==1) - { - //--- Hermite basis - for(i=0;i<=m/2-1;i++) - { - sy[i]=tmp[2*i]; - sd[i]=tmp[2*i+1]; - } - //--- function call - CSpline1D::Spline1DBuildHermite(sx,sy,sd,m/2,s); - } -//--- function call - CSpline1D::Spline1DLinTransX(s,2/(xb-xa),-((xa+xb)/(xb-xa))); -//--- function call - CSpline1D::Spline1DLinTransY(s,sb-sa,sa); -//--- Scale absolute errors obtained from LSFitLinearW. -//--- Relative error should be calculated separately -//--- (because of shifting/scaling of the task) - rep.m_taskrcond=lrep.m_taskrcond; - rep.m_rmserror=lrep.m_rmserror*(sb-sa); - rep.m_avgerror=lrep.m_avgerror*(sb-sa); - rep.m_maxerror=lrep.m_maxerror*(sb-sa); - rep.m_avgrelerror=0; - relcnt=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(yoriginal[i]!=0.0) - { - rep.m_avgrelerror=rep.m_avgrelerror+MathAbs(CSpline1D::Spline1DCalc(s,xoriginal[i])-yoriginal[i])/MathAbs(yoriginal[i]); - relcnt=relcnt+1; - } - } -//--- check - if(relcnt!=0) - rep.m_avgrelerror=rep.m_avgrelerror/relcnt; - } -//+------------------------------------------------------------------+ -//| Internal fitting subroutine | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitLinearInternal(double &y[],double &w[], - CMatrixDouble &fmatrix,const int n, - const int m,int &info,double &c[], - CLSFitReport &rep) - { -//--- create variables - double threshold=0; - int i=0; - int j=0; - double v=0; - int relcnt=0; - int i_=0; -//--- create arrays - double b[]; - double wmod[]; - double tau[]; - double sv[]; - double tmp[]; - double utb[]; - double sutb[]; -//--- create matrix - CMatrixDouble ft; - CMatrixDouble q; - CMatrixDouble l; - CMatrixDouble r; - CMatrixDouble u; - CMatrixDouble vt; -//--- initialization - info=0; -//--- check - if(n<1 || m<1) - { - info=-1; - return; - } -//--- initialization - info=1; - threshold=MathSqrt(CMath::m_machineepsilon); -//--- Degenerate case,needs special handling - if(n=M. Generate design matrix and reduce to N=M using -//--- QR decomposition. - ft.Resize(n,m); - ArrayResizeAL(b,n); - for(j=0;j<=n-1;j++) - { - v=w[j]; - for(i_=0;i_<=m-1;i_++) - ft[j].Set(i_,v*fmatrix[j][i_]); - b[j]=w[j]*y[j]; - } -//--- function call - COrtFac::RMatrixQR(ft,n,m,tau); -//--- function call - COrtFac::RMatrixQRUnpackQ(ft,n,m,tau,m,q); -//--- function call - COrtFac::RMatrixQRUnpackR(ft,n,m,r); -//--- allocation - ArrayResizeAL(tmp,m); - for(i=0;i<=m-1;i++) - tmp[i]=0; -//--- calculation - for(i=0;i<=n-1;i++) - { - v=b[i]; - for(i_=0;i_<=m-1;i_++) - tmp[i_]=tmp[i_]+v*q[i][i_]; - } -//--- allocation - ArrayResizeAL(b,m); -//--- copy - for(i_=0;i_<=m-1;i_++) - b[i_]=tmp[i_]; -//--- R contains reduced MxM design upper triangular matrix, -//--- B contains reduced Mx1 right part. -//--- Determine system condition number and decide -//--- should we use triangular solver (faster) or -//--- SVD-based solver (more stable). -//--- We can use LU-based RCond estimator for this task. - rep.m_taskrcond=CRCond::RMatrixLURCondInf(r,m); -//--- check - if(rep.m_taskrcond>threshold) - { - //--- use QR-based solver - ArrayResizeAL(c,m); - c[m-1]=b[m-1]/r[m-1][m-1]; - //--- calculation - for(i=m-2;i>=0;i--) - { - v=0.0; - for(i_=i+1;i_<=m-1;i_++) - v+=r[i][i_]*c[i_]; - c[i]=(b[i]-v)/r[i][i]; - } - } - else - { - //--- use SVD-based solver - if(!CSingValueDecompose::RMatrixSVD(r,m,m,1,1,2,sv,u,vt)) - { - info=-4; - return; - } - //--- allocation - ArrayResizeAL(utb,m); - ArrayResizeAL(sutb,m); - for(i=0;i<=m-1;i++) - utb[i]=0; - //--- calculation - for(i=0;i<=m-1;i++) - { - v=b[i]; - for(i_=0;i_<=m-1;i_++) - utb[i_]=utb[i_]+v*u[i][i_]; - } - //--- check - if(sv[0]>0.0) - { - rep.m_taskrcond=sv[m-1]/sv[0]; - for(i=0;i<=m-1;i++) - { - //--- check - if(sv[i]>threshold*sv[0]) - sutb[i]=utb[i]/sv[i]; - else - sutb[i]=0; - } - } - else - { - //--- change values - rep.m_taskrcond=0; - for(i=0;i<=m-1;i++) - sutb[i]=0; - } - //--- allocation - ArrayResizeAL(c,m); - for(i=0;i<=m-1;i++) - c[i]=0; - //--- calculation - for(i=0;i<=m-1;i++) - { - v=sutb[i]; - for(i_=0;i_<=m-1;i_++) - c[i_]=c[i_]+v*vt[i][i_]; - } - } -//--- calculate errors - rep.m_rmserror=0; - rep.m_avgerror=0; - rep.m_avgrelerror=0; - rep.m_maxerror=0; - relcnt=0; -//--- calculation - for(i=0;i<=n-1;i++) - { - v=0.0; - for(i_=0;i_<=m-1;i_++) - v+=fmatrix[i][i_]*c[i_]; - //--- change values - rep.m_rmserror=rep.m_rmserror+CMath::Sqr(v-y[i]); - rep.m_avgerror=rep.m_avgerror+MathAbs(v-y[i]); - //--- check - if(y[i]!=0.0) - { - rep.m_avgrelerror=rep.m_avgrelerror+MathAbs(v-y[i])/MathAbs(y[i]); - relcnt=relcnt+1; - } - rep.m_maxerror=MathMax(rep.m_maxerror,MathAbs(v-y[i])); - } -//--- change values - rep.m_rmserror=MathSqrt(rep.m_rmserror/n); - rep.m_avgerror=rep.m_avgerror/n; -//--- check - if(relcnt!=0) - rep.m_avgrelerror=rep.m_avgrelerror/relcnt; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CLSFit::LSFitClearRequestFields(CLSFitState &state) - { -//--- change values - state.m_needf=false; - state.m_needfg=false; - state.m_needfgh=false; - state.m_xupdated=false; - } -//+------------------------------------------------------------------+ -//| Internal subroutine, calculates barycentric basis functions. | -//| Used for efficient simultaneous calculation of N basis functions.| -//+------------------------------------------------------------------+ -static void CLSFit::BarycentricCalcBasis(CBarycentricInterpolant &b, - const double t,double &y[]) - { -//--- create variables - double s2=0; - double s=0; - double v=0; - int i=0; - int j=0; - int i_=0; -//--- special case: N=1 - if(b.m_n==1) - { - y[0]=1; - return; - } -//--- Here we assume that task is normalized,i.m_e.: -//--- 1. abs(Y[i])<=1 -//--- 2. abs(W[i])<=1 -//--- 3. X[] is ordered -//--- First,we decide: should we use "safe" formula (guarded -//--- against overflow) or fast one? - s=MathAbs(t-b.m_x[0]); - for(i=0;i<=b.m_n-1;i++) - { - v=b.m_x[i]; - //--- check - if(v==t) - { - for(j=0;j<=b.m_n-1;j++) - y[j]=0; - y[i]=1; - //--- exit the function - return; - } - //--- change value - v=MathAbs(t-v); - //--- check - if(v0. | -//| XC - points where polynomial values/derivatives are | -//| constrained, array[0..K-1]. | -//| YC - values of constraints, array[0..K-1] | -//| DC - array[0..K-1], types of constraints: | -//| * DC[i]=0 means that P(XC[i])=YC[i] | -//| * DC[i]=1 means that P'(XC[i])=YC[i] | -//| K - number of constraints, 0<=K=1 | -//| OUTPUT PARAMETERS: | -//| Info- same format as in LSFitLinearW() subroutine: | -//| * Info>0 task is solved | -//| * Info<=0 an error occured: | -//| -4 means inconvergence of internal SVD | -//| -3 means inconsistent constraints | -//| C - interpolant in Chebyshev form; [-1,+1] is used as | -//| base interval | -//| Rep - report, same format as in LSFitLinearW() subroutine. | -//| Following fields are set: | -//| * RMSError rms error on the (X,Y). | -//| * AvgError average error on the (X,Y). | -//| * AvgRelError average relative error on the | -//| non-zero Y | -//| * MaxError maximum error | -//| NON-WEIGHTED ERRORS ARE CALCULATED | -//| IMPORTANT: | -//| this subroitine doesn't calculate task's condition number for| -//| K<>0. | -//+------------------------------------------------------------------+ -static void CLSFit::InternalChebyshevFit(double &x[],double &y[],double &w[], - const int n,double &cxc[],double &cyc[], - int &dc[],const int k,const int m, - int &info,double &c[],CLSFitReport &rep) - { -//--- create variables - int i=0; - int j=0; - double mx=0; - double decay=0; - int i_=0; -//--- create arrays - double y2[]; - double w2[]; - double tmp[]; - double tmp2[]; - double tmpdiff[]; - double bx[]; - double by[]; - double bw[]; - double xc[]; - double yc[]; -//--- create matrix - CMatrixDouble fmatrix; - CMatrixDouble cmatrix; -//--- copy arrays - ArrayCopy(xc,cxc); - ArrayCopy(yc,cyc); -//--- initialization - info=0; -//--- weight decay for correct handling of task which becomes -//--- degenerate after constraints are applied - decay=10000*CMath::m_machineepsilon; -//--- allocate space,initialize/fill: -//--- * FMatrix- values of basis functions at X[] -//--- * CMatrix- values (derivatives) of basis functions at XC[] -//--- * fill constraints matrix -//--- * fill first N rows of design matrix with values -//--- * fill next M rows of design matrix with regularizing term -//--- * append M zeros to Y -//--- * append M elements,mean(abs(W)) each,to W - ArrayResizeAL(y2,n+m); - ArrayResizeAL(w2,n+m); - ArrayResizeAL(tmp,m); - ArrayResizeAL(tmpdiff,m); - fmatrix.Resize(n+m,m); -//--- check - if(k>0) - cmatrix.Resize(k,m+1); -//--- Fill design matrix,Y2,W2: -//--- * first N rows with basis functions for original points -//--- * next M rows with decay terms - for(i=0;i<=n-1;i++) - { - //--- prepare Ith row - //--- use Tmp for calculations to avoid multidimensional arrays overhead - for(j=0;j<=m-1;j++) - { - //--- check - if(j==0) - tmp[j]=1; - else - { - //--- check - if(j==1) - tmp[j]=x[i]; - else - tmp[j]=2*x[i]*tmp[j-1]-tmp[j-2]; - } - } - //--- copy - for(i_=0;i_<=m-1;i_++) - fmatrix[i].Set(i_,tmp[i_]); - } -//--- calculation - for(i=0;i<=m-1;i++) - { - for(j=0;j<=m-1;j++) - { - //--- check - if(i==j) - fmatrix[n+i].Set(j,decay); - else - fmatrix[n+i].Set(j,0); - } - } -//--- copy - for(i_=0;i_<=n-1;i_++) - y2[i_]=y[i_]; - for(i_=0;i_<=n-1;i_++) - w2[i_]=w[i_]; -//--- change value - mx=0; - for(i=0;i<=n-1;i++) - mx=mx+MathAbs(w[i]); - mx=mx/n; -//--- change values - for(i=0;i<=m-1;i++) - { - y2[n+i]=0; - w2[n+i]=mx; - } -//--- fill constraints matrix - for(i=0;i<=k-1;i++) - { - //--- prepare Ith row - //--- use Tmp for basis function values, - //--- TmpDiff for basos function derivatives - for(j=0;j<=m-1;j++) - { - //--- check - if(j==0) - { - tmp[j]=1; - tmpdiff[j]=0; - } - else - { - //--- check - if(j==1) - { - tmp[j]=xc[i]; - tmpdiff[j]=1; - } - else - { - tmp[j]=2*xc[i]*tmp[j-1]-tmp[j-2]; - tmpdiff[j]=2*(tmp[j-1]+xc[i]*tmpdiff[j-1])-tmpdiff[j-2]; - } - } - } - //--- check - if(dc[i]==0) - { - for(i_=0;i_<=m-1;i_++) - cmatrix[i].Set(i_,tmp[i_]); - } - //--- check - if(dc[i]==1) - { - for(i_=0;i_<=m-1;i_++) - cmatrix[i].Set(i_,tmpdiff[i_]); - } - cmatrix[i].Set(m,yc[i]); - } -//--- Solve constrained task - if(k>0) - { - //--- solve using regularization - LSFitLinearWC(y2,w2,fmatrix,cmatrix,n+m,m,k,info,c,rep); - } - else - { - //--- no constraints,no regularization needed - LSFitLinearWC(y,w,fmatrix,cmatrix,n,m,0,info,c,rep); - } -//--- check - if(info<0) - return; - } -//+------------------------------------------------------------------+ -//| Internal Floater-Hormann fitting subroutine for fixed D | -//+------------------------------------------------------------------+ -static void CLSFit::BarycentricFitWCFixedD(double &cx[],double &cy[], - double &cw[],const int n, - double &cxc[],double &cyc[], - int &dc[],const int k,const int m, - const int d,int &info, - CBarycentricInterpolant &b, - CBarycentricFitReport &rep) - { -//--- create variables - double v0=0; - double v1=0; - double mx=0; - int i=0; - int j=0; - int relcnt=0; - double xa=0; - double xb=0; - double sa=0; - double sb=0; - double decay=0; - int i_=0; -//--- create arrays - double y2[]; - double w2[]; - double sx[]; - double sy[]; - double sbf[]; - double xoriginal[]; - double yoriginal[]; - double tmp[]; - double x[]; - double y[]; - double w[]; - double xc[]; - double yc[]; -//--- create matrix - CMatrixDouble fmatrix; - CMatrixDouble cmatrix; -//--- objects of classes - CLSFitReport lrep; - CBarycentricInterpolant b2; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); - ArrayCopy(w,cw); - ArrayCopy(xc,cxc); - ArrayCopy(yc,cyc); -//--- initialization - info=0; -//--- check - if(((n<1 || m<2) || k<0) || k>=m) - { - info=-1; - return; - } - for(i=0;i<=k-1;i++) - { - info=0; - //--- check - if(dc[i]<0) - info=-1; - //--- check - if(dc[i]>1) - info=-1; - //--- check - if(info<0) - return; - } -//--- weight decay for correct handling of task which becomes -//--- degenerate after constraints are applied - decay=10000*CMath::m_machineepsilon; -//--- Scale X,Y,XC,YC - LSFitScaleXY(x,y,w,n,xc,yc,dc,k,xa,xb,sa,sb,xoriginal,yoriginal); -//--- allocate space,initialize: -//--- * FMatrix- values of basis functions at X[] -//--- * CMatrix- values (derivatives) of basis functions at XC[] - ArrayResizeAL(y2,n+m); - ArrayResizeAL(w2,n+m); - fmatrix.Resize(n+m,m); -//--- check - if(k>0) - cmatrix.Resize(k,m+1); -//--- allocation - ArrayResizeAL(y2,n+m); - ArrayResizeAL(w2,n+m); -//--- Prepare design and constraints matrices: -//--- * fill constraints matrix -//--- * fill first N rows of design matrix with values -//--- * fill next M rows of design matrix with regularizing term -//--- * append M zeros to Y -//--- * append M elements,mean(abs(W)) each,to W - ArrayResizeAL(sx,m); - ArrayResizeAL(sy,m); - ArrayResizeAL(sbf,m); - for(j=0;j<=m-1;j++) - sx[j]=(double)(2*j)/(double)(m-1)-1; - for(i=0;i<=m-1;i++) - sy[i]=1; -//--- function call - CRatInt::BarycentricBuildFloaterHormann(sx,sy,m,d,b2); -//--- change value - mx=0; -//--- calculation - for(i=0;i<=n-1;i++) - { - //--- function call - BarycentricCalcBasis(b2,x[i],sbf); - for(i_=0;i_<=m-1;i_++) - fmatrix[i].Set(i_,sbf[i_]); - //--- change values - y2[i]=y[i]; - w2[i]=w[i]; - mx=mx+MathAbs(w[i])/n; - } -//--- calculation - for(i=0;i<=m-1;i++) - { - for(j=0;j<=m-1;j++) - { - //--- check - if(i==j) - fmatrix[n+i].Set(j,decay); - else - fmatrix[n+i].Set(j,0); - } - //--- change values - y2[n+i]=0; - w2[n+i]=mx; - } -//--- check - if(k>0) - { - for(j=0;j<=m-1;j++) - { - for(i=0;i<=m-1;i++) - sy[i]=0; - sy[j]=1; - //--- function call - CRatInt::BarycentricBuildFloaterHormann(sx,sy,m,d,b2); - //--- calculation - for(i=0;i<=k-1;i++) - { - //--- check - if(!CAp::Assert(dc[i]>=0 && dc[i]<=1,__FUNCTION__+": internal error!")) - return; - //--- function call - CRatInt::BarycentricDiff1(b2,xc[i],v0,v1); - //--- check - if(dc[i]==0) - cmatrix[i].Set(j,v0); - //--- check - if(dc[i]==1) - cmatrix[i].Set(j,v1); - } - } - for(i=0;i<=k-1;i++) - cmatrix[i].Set(m,yc[i]); - } -//--- Solve constrained task - if(k>0) - { - //--- solve using regularization - LSFitLinearWC(y2,w2,fmatrix,cmatrix,n+m,m,k,info,tmp,lrep); - } - else - { - //--- no constraints,no regularization needed - LSFitLinearWC(y,w,fmatrix,cmatrix,n,m,k,info,tmp,lrep); - } -//--- check - if(info<0) - return; -//--- Generate interpolant and scale it - for(i_=0;i_<=m-1;i_++) - sy[i_]=tmp[i_]; -//--- function call - CRatInt::BarycentricBuildFloaterHormann(sx,sy,m,d,b); -//--- function call - CRatInt::BarycentricLinTransX(b,2/(xb-xa),-((xa+xb)/(xb-xa))); -//--- function call - CRatInt::BarycentricLinTransY(b,sb-sa,sa); -//--- Scale absolute errors obtained from LSFitLinearW. -//--- Relative error should be calculated separately -//--- (because of shifting/scaling of the task) - rep.m_taskrcond=lrep.m_taskrcond; - rep.m_rmserror=lrep.m_rmserror*(sb-sa); - rep.m_avgerror=lrep.m_avgerror*(sb-sa); - rep.m_maxerror=lrep.m_maxerror*(sb-sa); - rep.m_avgrelerror=0; - relcnt=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(yoriginal[i]!=0.0) - { - rep.m_avgrelerror=rep.m_avgrelerror+MathAbs(CRatInt::BarycentricCalc(b,xoriginal[i])-yoriginal[i])/MathAbs(yoriginal[i]); - relcnt=relcnt+1; - } - } -//--- check - if(relcnt!=0) - rep.m_avgrelerror=rep.m_avgrelerror/relcnt; - } -//+------------------------------------------------------------------+ -//| NOTES: | -//| 1. this algorithm is somewhat unusual because it works with | -//| parameterized function f(C,X), where X is a function argument | -//| (we have many points which are characterized by different | -//| argument values), and C is a parameter to fit. | -//| For example, if we want to do linear fit by f(c0,c1,x) = | -//| = c0*x+c1, then x will be argument, and {c0,c1} will be | -//| parameters. | -//| It is important to understand that this algorithm finds | -//| minimum in the space of function PARAMETERS (not arguments), | -//| so it needs derivatives of f() with respect to C, not X. | -//| In the example above it will need f=c0*x+c1 and | -//| {df/dc0,df/dc1} = {x,1} instead of {df/dx} = {c0}. | -//| 2. Callback functions accept C as the first parameter, and X as | -//| the second | -//| 3. If state was created with LSFitCreateFG(), algorithm needs | -//| just function and its gradient, but if state was created with | -//| LSFitCreateFGH(), algorithm will need function, gradient and | -//| Hessian. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with LSFitCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when algorithm| -//| will request Hessian, there will be no callback to call. In | -//| this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static bool CLSFit::LSFitIteration(CLSFitState &state) - { -//--- create variables - int n=0; - int m=0; - int k=0; - int i=0; - int j=0; - double v=0; - double vv=0; - double relcnt=0; - int i_=0; -//--- Reverse communication preparations -//--- I know it looks ugly,but it works the same way -//--- anywhere from C++ to Python. -// -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - m=state.m_rstate.ia[1]; - k=state.m_rstate.ia[2]; - i=state.m_rstate.ia[3]; - j=state.m_rstate.ia[4]; - v=state.m_rstate.ra[0]; - vv=state.m_rstate.ra[1]; - relcnt=state.m_rstate.ra[2]; - } - else - { - //--- initialization - n=-983; - m=-989; - k=-834; - i=900; - j=-287; - v=364; - vv=214; - relcnt=-338; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needf=false; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_optstate.m_fi[i]=vv*(state.m_f-state.m_tasky[i]); - i=i+1; - //--- function call, return result - return(Func_lbl_11(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change value - state.m_needf=false; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_optstate.m_f=state.m_optstate.m_f+CMath::Sqr(vv*(state.m_f-state.m_tasky[i])); - i=i+1; - //--- function call, return result - return(Func_lbl_16(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change value - state.m_needfg=false; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_optstate.m_f=state.m_optstate.m_f+CMath::Sqr(vv*(state.m_f-state.m_tasky[i])); - v=CMath::Sqr(vv)*2*(state.m_f-state.m_tasky[i]); - for(i_=0;i_<=k-1;i_++) - state.m_optstate.m_g[i_]=state.m_optstate.m_g[i_]+v*state.m_g[i_]; - i=i+1; - //--- function call, return result - return(Func_lbl_21(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change value - state.m_needfg=false; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_optstate.m_fi[i]=vv*(state.m_f-state.m_tasky[i]); - for(i_=0;i_<=k-1;i_++) - state.m_optstate.m_j[i].Set(i_,vv*state.m_g[i_]); - i=i+1; - //--- function call, return result - return(Func_lbl_26(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change value - state.m_needfgh=false; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_optstate.m_f=state.m_optstate.m_f+CMath::Sqr(vv*(state.m_f-state.m_tasky[i])); - v=CMath::Sqr(vv)*2*(state.m_f-state.m_tasky[i]); - for(i_=0;i_<=k-1;i_++) - state.m_optstate.m_g[i_]=state.m_optstate.m_g[i_]+v*state.m_g[i_]; - //--- calculation - for(j=0;j<=k-1;j++) - { - v=2*CMath::Sqr(vv)*state.m_g[j]; - for(i_=0;i_<=k-1;i_++) - state.m_optstate.m_h[j].Set(i_,state.m_optstate.m_h[j][i_]+v*state.m_g[i_]); - v=2*CMath::Sqr(vv)*(state.m_f-state.m_tasky[i]); - for(i_=0;i_<=k-1;i_++) - state.m_optstate.m_h[j].Set(i_,state.m_optstate.m_h[j][i_]+v*state.m_h[j][i_]); - } - i=i+1; - //--- function call, return result - return(Func_lbl_31(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change values - state.m_needf=false; - v=state.m_f; - //--- check - if(state.m_wkind==1) - vv=state.m_w[i]; - else - vv=1.0; - //--- change values - state.m_reprmserror=state.m_reprmserror+CMath::Sqr(v-state.m_tasky[i]); - state.m_repwrmserror=state.m_repwrmserror+CMath::Sqr(vv*(v-state.m_tasky[i])); - state.m_repavgerror=state.m_repavgerror+MathAbs(v-state.m_tasky[i]); - //--- check - if(state.m_tasky[i]!=0.0) - { - state.m_repavgrelerror=state.m_repavgrelerror+MathAbs(v-state.m_tasky[i])/MathAbs(state.m_tasky[i]); - relcnt=relcnt+1; - } - //--- change values - state.m_repmaxerror=MathMax(state.m_repmaxerror,MathAbs(v-state.m_tasky[i])); - i=i+1; - //--- function call, return result - return(Func_lbl_38(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- Routine body -//--- init - if(state.m_wkind==1) - { - //--- check - if(!CAp::Assert(state.m_npoints==state.m_nweights,__FUNCTION__+": number of points is not equal to the number of weights")) - return(false); - } -//--- change values - n=state.m_npoints; - m=state.m_m; - k=state.m_k; -//--- function call - CMinLM::MinLMSetCond(state.m_optstate,0.0,state.m_epsf,state.m_epsx,state.m_maxits); -//--- function call - CMinLM::MinLMSetStpMax(state.m_optstate,state.m_stpmax); -//--- function call - CMinLM::MinLMSetXRep(state.m_optstate,state.m_xrep); -//--- function call - CMinLM::MinLMSetScale(state.m_optstate,state.m_s); -//--- function call - CMinLM::MinLMSetBC(state.m_optstate,state.m_bndl,state.m_bndu); -//--- Optimize - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CLSFit::Func_lbl_rcomm(CLSFitState &state,int n,int m,int k,int i, - int j,double v,double vv,double relcnt) - { -//--- Saving state - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=m; - state.m_rstate.ia[2]=k; - state.m_rstate.ia[3]=i; - state.m_rstate.ia[4]=j; - state.m_rstate.ra[0]=v; - state.m_rstate.ra[1]=vv; - state.m_rstate.ra[2]=relcnt; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_7(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(!CMinLM::MinLMIteration(state.m_optstate)) - { - //--- function call - CMinLM::MinLMResults(state.m_optstate,state.m_c,state.m_optrep); - //--- change values - state.m_repterminationtype=state.m_optrep.m_terminationtype; - state.m_repiterationscount=state.m_optrep.m_iterationscount; - //--- calculate errors - if(state.m_repterminationtype<=0) - return(false); - //--- change values - state.m_reprmserror=0; - state.m_repwrmserror=0; - state.m_repavgerror=0; - state.m_repavgrelerror=0; - state.m_repmaxerror=0; - relcnt=0; - i=0; - //--- function call, return result - return(Func_lbl_38(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- check - if(!state.m_optstate.m_needfi) - { - //--- check - if(!state.m_optstate.m_needf) - return(Func_lbl_14(state,n,m,k,i,j,v,vv,relcnt)); - //--- calculate F=sum (wi*(f(xi,c)-yi))^2 - state.m_optstate.m_f=0; - i=0; - //--- function call, return result - return(Func_lbl_16(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- calculate f[]=wi*(f(xi,c)-yi) - i=0; -//--- function call, return result - return(Func_lbl_11(state,n,m,k,i,j,v,vv,relcnt)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_11(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needf=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_14(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(!state.m_optstate.m_needfg) - { - //--- check - if(!state.m_optstate.m_needfij) - return(Func_lbl_24(state,n,m,k,i,j,v,vv,relcnt)); - //--- calculate Fi/jac(Fi) - i=0; - //--- function call, return result - return(Func_lbl_26(state,n,m,k,i,j,v,vv,relcnt)); - } -//--- calculate F/gradF - state.m_optstate.m_f=0; - for(i=0;i<=k-1;i++) - state.m_optstate.m_g[i]=0; - i=0; -//--- function call, return result - return(Func_lbl_21(state,n,m,k,i,j,v,vv,relcnt)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_16(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needf=true; - state.m_rstate.stage=1; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_21(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_24(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(!state.m_optstate.m_needfgh) - return(Func_lbl_29(state,n,m,k,i,j,v,vv,relcnt)); -//--- calculate F/grad(F)/hess(F) - state.m_optstate.m_f=0; - for(i=0;i<=k-1;i++) - state.m_optstate.m_g[i]=0; - for(i=0;i<=k-1;i++) - { - for(j=0;j<=k-1;j++) - state.m_optstate.m_h[i].Set(j,0); - } -//--- change value - i=0; -//--- function call, return result - return(Func_lbl_31(state,n,m,k,i,j,v,vv,relcnt)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_26(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=3; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_29(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(!state.m_optstate.m_xupdated) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- Report new iteration - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - state.m_f=state.m_optstate.m_f; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=5; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_31(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - return(Func_lbl_7(state,n,m,k,i,j,v,vv,relcnt)); -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_optstate.m_x[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needfgh=true; - state.m_rstate.stage=4; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for LSFitIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CLSFit::Func_lbl_38(CLSFitState &state,int &n,int &m,int &k,int &i, - int &j,double &v,double &vv,double &relcnt) - { -//--- check - if(i>n-1) - { - //--- change values - state.m_reprmserror=MathSqrt(state.m_reprmserror/n); - state.m_repwrmserror=MathSqrt(state.m_repwrmserror/n); - state.m_repavgerror=state.m_repavgerror/n; - //--- check - if(relcnt!=0.0) - state.m_repavgrelerror=state.m_repavgrelerror/relcnt; - //--- return result - return(false); - } -//--- copy - for(int i_=0;i_<=k-1;i_++) - state.m_c[i_]=state.m_c[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_x[i_]=state.m_taskx[i][i_]; - state.m_pointindex=i; -//--- function call - LSFitClearRequestFields(state); -//--- change values - state.m_needf=true; - state.m_rstate.stage=6; -//--- Saving state - Func_lbl_rcomm(state,n,m,k,i,j,v,vv,relcnt); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Parametric spline inteprolant: 2-dimensional curve. | -//| You should not try to access its members directly - use | -//| PSpline2XXXXXXXX() functions instead. | -//+------------------------------------------------------------------+ -class CPSpline2Interpolant - { -public: - //--- variables - int m_n; - bool m_periodic; - CSpline1DInterpolant m_x; - CSpline1DInterpolant m_y; - //--- array - double m_p[]; - //--- constructor, destructor - CPSpline2Interpolant(void); - ~CPSpline2Interpolant(void); - //--- copy - void Copy(CPSpline2Interpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPSpline2Interpolant::CPSpline2Interpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPSpline2Interpolant::~CPSpline2Interpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CPSpline2Interpolant::Copy(CPSpline2Interpolant &obj) - { -//--- copy variables - m_n=obj.m_n; - m_periodic=obj.m_periodic; - m_x.Copy(obj.m_x); - m_y.Copy(obj.m_y); -//--- copy array - ArrayCopy(m_p,obj.m_p); - } -//+------------------------------------------------------------------+ -//| Parametric spline inteprolant: 2-dimensional curve. | -//| You should not try to access its members directly - use | -//| PSpline2XXXXXXXX() functions instead. | -//+------------------------------------------------------------------+ -class CPSpline2InterpolantShell - { -private: - CPSpline2Interpolant m_innerobj; -public: - //--- constructors, destructor - CPSpline2InterpolantShell(void); - CPSpline2InterpolantShell(CPSpline2Interpolant &obj); - ~CPSpline2InterpolantShell(void); - //--- method - CPSpline2Interpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPSpline2InterpolantShell::CPSpline2InterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CPSpline2InterpolantShell::CPSpline2InterpolantShell(CPSpline2Interpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPSpline2InterpolantShell::~CPSpline2InterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CPSpline2Interpolant *CPSpline2InterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Parametric spline inteprolant: 3-dimensional curve. | -//| You should not try to access its members directly - use | -//| PSpline3XXXXXXXX() functions instead. | -//+------------------------------------------------------------------+ -class CPSpline3Interpolant - { -public: - //--- variables - int m_n; - bool m_periodic; - CSpline1DInterpolant m_x; - CSpline1DInterpolant m_y; - CSpline1DInterpolant m_z; - //--- array - double m_p[]; - //--- constructor, destructor - CPSpline3Interpolant(void); - ~CPSpline3Interpolant(void); - //--- copy - void Copy(CPSpline3Interpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPSpline3Interpolant::CPSpline3Interpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPSpline3Interpolant::~CPSpline3Interpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CPSpline3Interpolant::Copy(CPSpline3Interpolant &obj) - { -//--- copy variables - m_n=obj.m_n; - m_periodic=obj.m_periodic; - m_x.Copy(obj.m_x); - m_y.Copy(obj.m_y); - m_z.Copy(obj.m_z); -//--- copy array - ArrayCopy(m_p,obj.m_p); - } -//+------------------------------------------------------------------+ -//| Parametric spline inteprolant: 3-dimensional curve. | -//| You should not try to access its members directly - use | -//| PSpline3XXXXXXXX() functions instead. | -//+------------------------------------------------------------------+ -class CPSpline3InterpolantShell - { -private: - CPSpline3Interpolant m_innerobj; -public: - //--- constructors, destructor - CPSpline3InterpolantShell(void); - CPSpline3InterpolantShell(CPSpline3Interpolant &obj); - ~CPSpline3InterpolantShell(void); - //--- method - CPSpline3Interpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPSpline3InterpolantShell::CPSpline3InterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CPSpline3InterpolantShell::CPSpline3InterpolantShell(CPSpline3Interpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPSpline3InterpolantShell::~CPSpline3InterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CPSpline3Interpolant *CPSpline3InterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Parametric spline | -//+------------------------------------------------------------------+ -class CPSpline - { -private: - //--- private methods - static void PSpline2Par(CMatrixDouble &xy,const int n,const int pt,double &p[]); - static void PSpline3Par(CMatrixDouble &xy,const int n,const int pt,double &p[]); -public: - //--- constructor, destructor - CPSpline(void); - ~CPSpline(void); - //--- public methods - static void PSpline2Build(CMatrixDouble &cxy,const int n,const int st,const int pt,CPSpline2Interpolant &p); - static void PSpline3Build(CMatrixDouble &cxy,const int n,const int st,const int pt,CPSpline3Interpolant &p); - static void PSpline2BuildPeriodic(CMatrixDouble &cxy,const int n,const int st,const int pt,CPSpline2Interpolant &p); - static void PSpline3BuildPeriodic(CMatrixDouble &cxy,const int n,const int st,const int pt,CPSpline3Interpolant &p); - static void PSpline2ParameterValues(CPSpline2Interpolant &p,int &n,double &t[]); - static void PSpline3ParameterValues(CPSpline3Interpolant &p,int &n,double &t[]); - static void PSpline2Calc(CPSpline2Interpolant &p,double t,double &x,double &y); - static void PSpline3Calc(CPSpline3Interpolant &p,double t,double &x,double &y,double &z); - static void PSpline2Tangent(CPSpline2Interpolant &p,double t,double &x,double &y); - static void PSpline3Tangent(CPSpline3Interpolant &p,double t,double &x,double &y,double &z); - static void PSpline2Diff(CPSpline2Interpolant &p,double t,double &x,double &dx,double &y,double &dy); - static void PSpline3Diff(CPSpline3Interpolant &p,double t,double &x,double &dx,double &y,double &dy,double &z,double &dz); - static void PSpline2Diff2(CPSpline2Interpolant &p,double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y); - static void PSpline3Diff2(CPSpline3Interpolant &p,double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y,double &z,double &dz,double &d2z); - static double PSpline2ArcLength(CPSpline2Interpolant &p,const double a,const double b); - static double PSpline3ArcLength(CPSpline3Interpolant &p,const double a,const double b); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPSpline::CPSpline(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPSpline::~CPSpline(void) - { - - } -//+------------------------------------------------------------------+ -//| This function builds non-periodic 2-dimensional parametric | -//| spline which starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). | -//| INPUT PARAMETERS: | -//| XY - points, array[0..N-1,0..1]. | -//| XY[I,0:1] corresponds to the Ith point. | -//| Order of points is important! | -//| N - points count, N>=5 for Akima splines, N>=2 for other | -//| types of splines. | -//| ST - spline type: | -//| * 0 Akima spline | -//| * 1 parabolically terminated Catmull-Rom spline | -//| (Tension=0) | -//| * 2 parabolically terminated cubic spline | -//| PT - parameterization type: | -//| * 0 uniform | -//| * 1 chord length | -//| * 2 centripetal | -//| OUTPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| NOTES: | -//| * this function assumes that there all consequent points are | -//| distinct. I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), | -//| (x2,y2)<>(x3,y3) and so on. However, non-consequent points may | -//| coincide, i.e. we can have (x0,y0) = (x2,y2). | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Build(CMatrixDouble &cxy,const int n, - const int st,const int pt, - CPSpline2Interpolant &p) - { -//--- create a variable - int i_=0; -//--- create array - double tmp[]; -//--- copy matrix - CMatrixDouble xy; - xy=cxy; -//--- check - if(!CAp::Assert(st>=0 && st<=2,__FUNCTION__+": incorrect spline type!")) - return; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": incorrect parameterization type!")) - return; -//--- check - if(st==0) - { - //--- check - if(!CAp::Assert(n>=5,__FUNCTION__+": N<5 (minimum value for Akima splines)!")) - return; - } - else - { - //--- check - if(!CAp::Assert(n>=2,__FUNCTION__+": N<2!")) - return; - } -//--- Prepare - p.m_n=n; - p.m_periodic=false; -//--- allocation - ArrayResizeAL(tmp,n); -//--- Build parameterization,check that all parameters are distinct - PSpline2Par(xy,n,pt,p.m_p); -//--- check - if(!CAp::Assert(CApServ::AreDistinct(p.m_p,n),__FUNCTION__+": consequent points are too close!")) - return; -//--- Build splines - if(st==0) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildAkima(p.m_p,tmp,n,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildAkima(p.m_p,tmp,n,p.m_y); - } -//--- check - if(st==1) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n,0,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n,0,0.0,p.m_y); - } -//--- check - if(st==2) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n,0,0.0,0,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n,0,0.0,0,0.0,p.m_y); - } - } -//+------------------------------------------------------------------+ -//| This function builds non-periodic 3-dimensional parametric spline| -//| which starts at (X[0],Y[0],Z[0]) and ends at | -//| (X[N-1],Y[N-1],Z[N-1]). | -//| Same as PSpline2Build() function, but for 3D, so we won't | -//| duplicate its description here. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Build(CMatrixDouble &cxy,const int n, - const int st,const int pt, - CPSpline3Interpolant &p) - { -//--- create a variable - int i_=0; -//--- create array - double tmp[]; -//--- copy matrix - CMatrixDouble xy; - xy=cxy; -//--- check - if(!CAp::Assert(st>=0 && st<=2,__FUNCTION__+": incorrect spline type!")) - return; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": incorrect parameterization type!")) - return; -//--- check - if(st==0) - { - //--- check - if(!CAp::Assert(n>=5,__FUNCTION__+": N<5 (minimum value for Akima splines)!")) - return; - } - else - { - //--- check - if(!CAp::Assert(n>=2,__FUNCTION__+"PSpline3Build: N<2!")) - return; - } -//--- Prepare - p.m_n=n; - p.m_periodic=false; -//--- allocation - ArrayResizeAL(tmp,n); -//--- Build parameterization,check that all parameters are distinct - PSpline3Par(xy,n,pt,p.m_p); -//--- check - if(!CAp::Assert(CApServ::AreDistinct(p.m_p,n),__FUNCTION__+": consequent points are too close!")) - return; -//--- Build splines - if(st==0) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildAkima(p.m_p,tmp,n,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildAkima(p.m_p,tmp,n,p.m_y); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][2]; - //--- function call - CSpline1D::Spline1DBuildAkima(p.m_p,tmp,n,p.m_z); - } -//--- check - if(st==1) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n,0,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n,0,0.0,p.m_y); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][2]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n,0,0.0,p.m_z); - } -//--- check - if(st==2) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n,0,0.0,0,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n,0,0.0,0,0.0,p.m_y); - //--- copy - for(i_=0;i_<=n-1;i_++) - tmp[i_]=xy[i_][2]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n,0,0.0,0,0.0,p.m_z); - } - } -//+------------------------------------------------------------------+ -//| This function builds periodic 2-dimensional parametric spline | -//| which starts at (X[0],Y[0]), goes through all points to | -//| (X[N-1],Y[N-1]) and then back to (X[0],Y[0]). | -//| INPUT PARAMETERS: | -//| XY - points, array[0..N-1,0..1]. | -//| XY[I,0:1] corresponds to the Ith point. | -//| XY[N-1,0:1] must be different from XY[0,0:1]. | -//| Order of points is important! | -//| N - points count, N>=3 for other types of splines. | -//| ST - spline type: | -//| * 1 Catmull-Rom spline (Tension=0) with cyclic | -//| boundary conditions | -//| * 2 cubic spline with cyclic boundary conditions | -//| PT - parameterization type: | -//| * 0 uniform | -//| * 1 chord length | -//| * 2 centripetal | -//| OUTPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| NOTES: | -//| * this function assumes that there all consequent points are | -//| distinct. I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), | -//| (x2,y2)<>(x3,y3) and so on. However, non-consequent points may | -//| coincide, i.e. we can have (x0,y0) = (x2,y2). | -//| * last point of sequence is NOT equal to the first point. You | -//| shouldn't make curve "explicitly periodic" by making them | -//| equal. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2BuildPeriodic(CMatrixDouble &cxy,const int n, - const int st,const int pt, - CPSpline2Interpolant &p) - { -//--- create a variable - int i_=0; -//--- create array - double tmp[]; -//--- create matrix - CMatrixDouble xyp; - CMatrixDouble xy; -//--- copy matrix - xy=cxy; -//--- check - if(!CAp::Assert(st>=1 && st<=2,__FUNCTION__+": incorrect spline type!")) - return; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": incorrect parameterization type!")) - return; -//--- check - if(!CAp::Assert(n>=3,__FUNCTION__+": N<3!")) - return; -//--- Prepare - p.m_n=n; - p.m_periodic=true; -//--- allocation - ArrayResizeAL(tmp,n+1); - xyp.Resize(n+1,2); -//--- change values - for(i_=0;i_<=n-1;i_++) - xyp[i_].Set(0,xy[i_][0]); - for(i_=0;i_<=n-1;i_++) - xyp[i_].Set(1,xy[i_][1]); - for(i_=0;i_<=1;i_++) - xyp[n].Set(i_,xy[0][i_]); -//--- Build parameterization,check that all parameters are distinct - PSpline2Par(xyp,n+1,pt,p.m_p); -//--- check - if(!CAp::Assert(CApServ::AreDistinct(p.m_p,n+1),__FUNCTION__+": consequent (or first and last) points are too close!")) - return; -//--- Build splines - if(st==1) - { - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n+1,-1,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n+1,-1,0.0,p.m_y); - } -//--- check - if(st==2) - { - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n+1,-1,0.0,-1,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n+1,-1,0.0,-1,0.0,p.m_y); - } - } -//+------------------------------------------------------------------+ -//| This function builds periodic 3-dimensional parametric spline | -//| which starts at (X[0],Y[0],Z[0]), goes through all points to | -//| (X[N-1],Y[N-1],Z[N-1]) and then back to (X[0],Y[0],Z[0]). | -//| Same as PSpline2Build() function, but for 3D, so we won't | -//| duplicate its description here. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3BuildPeriodic(CMatrixDouble &cxy,const int n, - const int st,const int pt, - CPSpline3Interpolant &p) - { -//--- create a variable - int i_=0; -//--- create array - double tmp[]; -//--- create matrix - CMatrixDouble xyp; - CMatrixDouble xy; -//--- copy matrix - xy=cxy; -//--- check - if(!CAp::Assert(st>=1 && st<=2,__FUNCTION__+": incorrect spline type!")) - return; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": incorrect parameterization type!")) - return; -//--- check - if(!CAp::Assert(n>=3,__FUNCTION__+": N<3!")) - return; -//--- Prepare - p.m_n=n; - p.m_periodic=true; -//--- allocation - ArrayResizeAL(tmp,n+1); - xyp.Resize(n+1,3); -//--- change values - for(i_=0;i_<=n-1;i_++) - xyp[i_].Set(0,xy[i_][0]); - for(i_=0;i_<=n-1;i_++) - xyp[i_].Set(1,xy[i_][1]); - for(i_=0;i_<=n-1;i_++) - xyp[i_].Set(2,xy[i_][2]); - for(i_=0;i_<=2;i_++) - xyp[n].Set(i_,xy[0][i_]); -//--- Build parameterization,check that all parameters are distinct - PSpline3Par(xyp,n+1,pt,p.m_p); -//--- check - if(!CAp::Assert(CApServ::AreDistinct(p.m_p,n+1),__FUNCTION__+": consequent (or first and last) points are too close!")) - return; -//--- Build splines - if(st==1) - { - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n+1,-1,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n+1,-1,0.0,p.m_y); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][2]; - //--- function call - CSpline1D::Spline1DBuildCatmullRom(p.m_p,tmp,n+1,-1,0.0,p.m_z); - } -//--- check - if(st==2) - { - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][0]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n+1,-1,0.0,-1,0.0,p.m_x); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][1]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n+1,-1,0.0,-1,0.0,p.m_y); - //--- copy - for(i_=0;i_<=n;i_++) - tmp[i_]=xyp[i_][2]; - //--- function call - CSpline1D::Spline1DBuildCubic(p.m_p,tmp,n+1,-1,0.0,-1,0.0,p.m_z); - } - } -//+------------------------------------------------------------------+ -//| This function returns vector of parameter values correspoding to | -//| points. | -//| I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and | -//| U=TValues(P) we have | -//| (X[0],Y[0]) = PSpline2Calc(P,U[0]), | -//| (X[1],Y[1]) = PSpline2Calc(P,U[1]), | -//| (X[2],Y[2]) = PSpline2Calc(P,U[2]), | -//| ... | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| OUTPUT PARAMETERS: | -//| N - array size | -//| T - array[0..N-1] | -//| NOTES: | -//| * for non-periodic splines U[0]=0, U[0]=2,__FUNCTION__+": internal error!")) - return; -//--- initialization - n=p.m_n; -//--- allocation - ArrayResizeAL(t,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - t[i_]=p.m_p[i_]; - t[0]=0; -//--- check - if(!p.m_periodic) - t[n-1]=1; - } -//+------------------------------------------------------------------+ -//| This function returns vector of parameter values correspoding to | -//| points. | -//| Same as PSpline2ParameterValues(), but for 3D. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3ParameterValues(CPSpline3Interpolant &p, - int &n,double &t[]) - { -//--- create a variable - int i_=0; -//--- initialization - n=0; -//--- check - if(!CAp::Assert(p.m_n>=2,__FUNCTION__+": internal error!")) - return; -//--- initialization - n=p.m_n; -//--- allocation - ArrayResizeAL(t,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - t[i_]=p.m_p[i_]; - t[0]=0; -//--- check - if(!p.m_periodic) - t[n-1]=1; - } -//+------------------------------------------------------------------+ -//| This function calculates the value of the parametric spline for a| -//| given value of parameter T | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-position | -//| Y - Y-position | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Calc(CPSpline2Interpolant &p,double t, - double &x,double &y) - { -//--- initialization - x=0; - y=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - x=CSpline1D::Spline1DCalc(p.m_x,t); -//--- function call - y=CSpline1D::Spline1DCalc(p.m_y,t); - } -//+------------------------------------------------------------------+ -//| This function calculates the value of the parametric spline for a| -//| given value of parameter T. | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond | -//| to parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-position | -//| Y - Y-position | -//| Z - Z-position | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Calc(CPSpline3Interpolant &p,double t, - double &x,double &y,double &z) - { -//--- initialization - x=0; - y=0; - z=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - x=CSpline1D::Spline1DCalc(p.m_x,t); -//--- function call - y=CSpline1D::Spline1DCalc(p.m_y,t); -//--- function call - z=CSpline1D::Spline1DCalc(p.m_z,t); - } -//+------------------------------------------------------------------+ -//| This function calculates tangent vector for a given value of | -//| parameter T | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-component of tangent vector (normalized) | -//| Y - Y-component of tangent vector (normalized) | -//| NOTE: | -//| X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Tangent(CPSpline2Interpolant &p,double t, - double &x,double &y) - { -//--- create variables - double v=0; - double v0=0; - double v1=0; -//--- initialization - x=0; - y=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - PSpline2Diff(p,t,v0,x,v1,y); -//--- check - if(x!=0.0 || y!=0.0) - { - //--- this code is a bit more complex than X^2+Y^2 to avoid - //--- overflow for large values of X and Y. - v=CApServ::SafePythag2(x,y); - x=x/v; - y=y/v; - } - } -//+------------------------------------------------------------------+ -//| This function calculates tangent vector for a given value of | -//| parameter T | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-component of tangent vector (normalized) | -//| Y - Y-component of tangent vector (normalized) | -//| Z - Z-component of tangent vector (normalized) | -//| NOTE: | -//| X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Tangent(CPSpline3Interpolant &p,double t, - double &x,double &y,double &z) - { -//--- create variables - double v=0; - double v0=0; - double v1=0; - double v2=0; -//--- initialization - x=0; - y=0; - z=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - PSpline3Diff(p,t,v0,x,v1,y,v2,z); -//--- check - if((x!=0.0 || y!=0.0) || z!=0.0) - { - //--- function call - v=CApServ::SafePythag3(x,y,z); - //--- change values - x=x/v; - y=y/v; - z=z/v; - } - } -//+------------------------------------------------------------------+ -//| This function calculates derivative, i.e. it returns | -//| (dX/dT,dY/dT). | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-value | -//| DX - X-derivative | -//| Y - Y-value | -//| DY - Y-derivative | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Diff(CPSpline2Interpolant &p,double t, - double &x,double &dx,double &y, - double &dy) - { -//--- create a variable - double d2s=0; -//--- change values - x=0; - dx=0; - y=0; - dy=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - CSpline1D::Spline1DDiff(p.m_x,t,x,dx,d2s); -//--- function call - CSpline1D::Spline1DDiff(p.m_y,t,y,dy,d2s); - } -//+------------------------------------------------------------------+ -//| This function calculates derivative, i.e. it returns | -//| (dX/dT,dY/dT,dZ/dT). | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-value | -//| DX - X-derivative | -//| Y - Y-value | -//| DY - Y-derivative | -//| Z - Z-value | -//| DZ - Z-derivative | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Diff(CPSpline3Interpolant &p,double t, - double &x,double &dx,double &y, - double &dy,double &z,double &dz) - { -//--- create a variable - double d2s=0; -//--- initialization - x=0; - dx=0; - y=0; - dy=0; - z=0; - dz=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - CSpline1D::Spline1DDiff(p.m_x,t,x,dx,d2s); -//--- function call - CSpline1D::Spline1DDiff(p.m_y,t,y,dy,d2s); -//--- function call - CSpline1D::Spline1DDiff(p.m_z,t,z,dz,d2s); - } -//+------------------------------------------------------------------+ -//| This function calculates first and second derivative with respect| -//| to T. | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-value | -//| DX - derivative | -//| D2X - second derivative | -//| Y - Y-value | -//| DY - derivative | -//| D2Y - second derivative | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Diff2(CPSpline2Interpolant &p,double t, - double &x,double &dx,double &d2x, - double &y,double &dy,double &d2y) - { -//--- initialization - x=0; - dx=0; - d2x=0; - y=0; - dy=0; - d2y=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - CSpline1D::Spline1DDiff(p.m_x,t,x,dx,d2x); -//--- function call - CSpline1D::Spline1DDiff(p.m_y,t,y,dy,d2y); - } -//+------------------------------------------------------------------+ -//| This function calculates first and second derivative with respect| -//| to T. | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| T - point: | -//| * T in [0,1] corresponds to interval spanned by | -//| points | -//| * for non-periodic splines T<0 (or T>1) correspond to| -//| parts of the curve before the first (after the | -//| last) point | -//| * for periodic splines T<0 (or T>1) are projected | -//| into [0,1] by making T=T-floor(T). | -//| OUTPUT PARAMETERS: | -//| X - X-value | -//| DX - derivative | -//| D2X - second derivative | -//| Y - Y-value | -//| DY - derivative | -//| D2Y - second derivative | -//| Z - Z-value | -//| DZ - derivative | -//| D2Z - second derivative | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Diff2(CPSpline3Interpolant &p,double t, - double &x,double &dx,double &d2x, - double &y,double &dy,double &d2y, - double &z,double &dz,double &d2z) - { -//--- initialization - x=0; - dx=0; - d2x=0; - y=0; - dy=0; - d2y=0; - z=0; - dz=0; - d2z=0; -//--- check - if(p.m_periodic) - t=t-(int)MathFloor(t); -//--- function call - CSpline1D::Spline1DDiff(p.m_x,t,x,dx,d2x); -//--- function call - CSpline1D::Spline1DDiff(p.m_y,t,y,dy,d2y); -//--- function call - CSpline1D::Spline1DDiff(p.m_z,t,z,dz,d2z); - } -//+------------------------------------------------------------------+ -//| This function calculates arc length, i.e. length of curve between| -//| t=a and t=b. | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| A,B - parameter values corresponding to arc ends: | -//| * B>A will result in positive length returned | -//| * B0,__FUNCTION__+": internal error!")) - return(EMPTY_VALUE); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| This function calculates arc length, i.e. length of curve between| -//| t=a and t=b. | -//| INPUT PARAMETERS: | -//| P - parametric spline interpolant | -//| A,B - parameter values corresponding to arc ends: | -//| * B>A will result in positive length returned | -//| * B0,__FUNCTION__+": internal error!")) - return(EMPTY_VALUE); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Builds non-periodic parameterization for 2-dimensional spline | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline2Par(CMatrixDouble &xy,const int n,const int pt, - double &p[]) - { -//--- create variables - double v=0; - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": internal error!")) - return; -//--- Build parameterization: -//--- * fill by non-normalized values -//--- * normalize them so we have P[0]=0,P[N-1]=1. - ArrayResizeAL(p,n); -//--- check - if(pt==0) - { - for(i=0;i<=n-1;i++) - p[i]=i; - } -//--- check - if(pt==1) - { - p[0]=0; - //--- calculation - for(i=1;i<=n-1;i++) - p[i]=p[i-1]+CApServ::SafePythag2(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1]); - } -//--- check - if(pt==2) - { - p[0]=0; - //--- calculation - for(i=1;i<=n-1;i++) - p[i]=p[i-1]+MathSqrt(CApServ::SafePythag2(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1])); - } -//--- change value - v=1/p[n-1]; -//--- calculation - for(i_=0;i_<=n-1;i_++) - p[i_]=v*p[i_]; - } -//+------------------------------------------------------------------+ -//| Builds non-periodic parameterization for 3-dimensional spline | -//+------------------------------------------------------------------+ -static void CPSpline::PSpline3Par(CMatrixDouble &xy,const int n,const int pt, - double &p[]) - { -//--- create variables - double v=0; - int i=0; - int i_=0; -//--- check - if(!CAp::Assert(pt>=0 && pt<=2,__FUNCTION__+": internal error!")) - return; -//--- Build parameterization: -//--- * fill by non-normalized values -//--- * normalize them so we have P[0]=0,P[N-1]=1. - ArrayResizeAL(p,n); -//--- check - if(pt==0) - { - for(i=0;i<=n-1;i++) - p[i]=i; - } -//--- check - if(pt==1) - { - p[0]=0; - //--- calculation - for(i=1;i<=n-1;i++) - p[i]=p[i-1]+CApServ::SafePythag3(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1],xy[i][2]-xy[i-1][2]); - } -//--- check - if(pt==2) - { - p[0]=0; - //--- calculation - for(i=1;i<=n-1;i++) - p[i]=p[i-1]+MathSqrt(CApServ::SafePythag3(xy[i][0]-xy[i-1][0],xy[i][1]-xy[i-1][1],xy[i][2]-xy[i-1][2])); - } -//--- change value - v=1/p[n-1]; -//--- calculation - for(i_=0;i_<=n-1;i_++) - p[i_]=v*p[i_]; - } -//+------------------------------------------------------------------+ -//| 2-dimensional spline inteprolant | -//+------------------------------------------------------------------+ -class CSpline2DInterpolant - { -public: - //--- variable - int m_k; - //--- array - double m_c[]; - //--- constructor, destructor - CSpline2DInterpolant(void); - ~CSpline2DInterpolant(void); - //--- copy - void Copy(CSpline2DInterpolant &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline2DInterpolant::CSpline2DInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline2DInterpolant::~CSpline2DInterpolant(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CSpline2DInterpolant::Copy(CSpline2DInterpolant &obj) - { -//--- copy variable - m_k=obj.m_k; -//--- copy array - ArrayCopy(m_c,obj.m_c); - } -//+------------------------------------------------------------------+ -//| 2-dimensional spline inteprolant | -//+------------------------------------------------------------------+ -class CSpline2DInterpolantShell - { -private: - CSpline2DInterpolant m_innerobj; -public: - //--- constructors, destructor - CSpline2DInterpolantShell(void); - CSpline2DInterpolantShell(CSpline2DInterpolant &obj); - ~CSpline2DInterpolantShell(void); - //--- method - CSpline2DInterpolant *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline2DInterpolantShell::CSpline2DInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CSpline2DInterpolantShell::CSpline2DInterpolantShell(CSpline2DInterpolant &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline2DInterpolantShell::~CSpline2DInterpolantShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CSpline2DInterpolant *CSpline2DInterpolantShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| 2-dimensional spline interpolation | -//+------------------------------------------------------------------+ -class CSpline2D - { -private: - //--- private method - static void BicubicCalcDerivatives(CMatrixDouble &a,double &x[],double &y[],const int m,const int n,CMatrixDouble &dx,CMatrixDouble &dy,CMatrixDouble &dxy); -public: - //--- constructor, destructor - CSpline2D(void); - ~CSpline2D(void); - //--- public methods - static void Spline2DBuildBilinear(double &cx[],double &cy[],CMatrixDouble &cf,const int m,const int n,CSpline2DInterpolant &c); - static void Spline2DBuildBicubic(double &cx[],double &cy[],CMatrixDouble &cf,const int m,const int n,CSpline2DInterpolant &c); - static double Spline2DCalc(CSpline2DInterpolant &c,const double x,const double y); - static void Spline2DDiff(CSpline2DInterpolant &c,const double x,const double y,double &f,double &fx,double &fy,double &fxy); - static void Spline2DUnpack(CSpline2DInterpolant &c,int &m,int &n,CMatrixDouble &tbl); - static void Spline2DLinTransXY(CSpline2DInterpolant &c,double ax,double bx,double ay,double by); - static void Spline2DLinTransF(CSpline2DInterpolant &c,const double a,const double b); - static void Spline2DCopy(CSpline2DInterpolant &c,CSpline2DInterpolant &cc); - static void Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth); - static void Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSpline2D::CSpline2D(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSpline2D::~CSpline2D(void) - { - - } -//+------------------------------------------------------------------+ -//| This subroutine builds bilinear spline coefficients table. | -//| Input parameters: | -//| X - spline abscissas, array[0..N-1] | -//| Y - spline ordinates, array[0..M-1] | -//| F - function values, array[0..M-1,0..N-1] | -//| M,N - grid size, M>=2, N>=2 | -//| Output parameters: | -//| C - spline interpolant | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DBuildBilinear(double &cx[],double &cy[], - CMatrixDouble &cf,const int m, - const int n,CSpline2DInterpolant &c) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int tblsize=0; - int shift=0; - double t=0; -//--- create arrays - double x[]; - double y[]; -//--- create matrix - CMatrixDouble dx; - CMatrixDouble dy; - CMatrixDouble dxy; - CMatrixDouble f; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- copy matrix - f=cf; -//--- check - if(!CAp::Assert(n>=2 && m>=2,__FUNCTION__+": N<2 or M<2!")) - return; -//--- Sort points - for(j=0;j<=n-1;j++) - { - k=j; - for(i=j+1;i<=n-1;i++) - { - //--- check - if(x[i]=2, N>=2 | -//| Output parameters: | -//| C - spline interpolant | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DBuildBicubic(double &cx[],double &cy[], - CMatrixDouble &cf,const int m, - const int n,CSpline2DInterpolant &c) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int tblsize=0; - int shift=0; - double t=0; -//--- create arrays - double x[]; - double y[]; -//--- create matrix - CMatrixDouble dx; - CMatrixDouble dy; - CMatrixDouble dxy; - CMatrixDouble f; -//--- copy arrays - ArrayCopy(x,cx); - ArrayCopy(y,cy); -//--- copy matrix - f=cf; -//--- check - if(!CAp::Assert(n>=2 && m>=2,__FUNCTION__+": N<2 or M<2!")) - return; -//--- Sort points - for(j=0;j<=n-1;j++) - { - k=j; - for(i=j+1;i<=n-1;i++) - { - //--- check - if(x[i]=x) - r=h; - else - l=h; - } -//--- change values - t=(x-c.m_c[l])/(c.m_c[l+1]-c.m_c[l]); - dt=1.0/(c.m_c[l+1]-c.m_c[l]); - ix=l-4; -//--- Binary search in the [ y[0],...,y[m-2] ] (y[m-1] is not included) - l=4+n; - r=4+n+(m-2)+1; - while(l!=r-1) - { - h=(l+r)/2; - //--- check - if(c.m_c[h]>=y) - r=h; - else - l=h; - } -//--- change values - u=(y-c.m_c[l])/(c.m_c[l+1]-c.m_c[l]); - du=1.0/(c.m_c[l+1]-c.m_c[l]); - iy=l-(4+n); -//--- Prepare F,dF/dX,dF/dY,d2F/dXdY - f=0; - fx=0; - fy=0; - fxy=0; -//--- Bilinear interpolation - if((int)MathRound(c.m_c[1])==-1) - { - //--- calculation - shift1=4+n+m; - y1=c.m_c[shift1+n*iy+ix]; - y2=c.m_c[shift1+n*iy+(ix+1)]; - y3=c.m_c[shift1+n*(iy+1)+(ix+1)]; - y4=c.m_c[shift1+n*(iy+1)+ix]; - f=(1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - fx=(-((1-u)*y1)+(1-u)*y2+u*y3-u*y4)*dt; - fy=(-((1-t)*y1)-t*y2+t*y3+(1-t)*y4)*du; - fxy=(y1-y2+y3-y4)*du*dt; - //--- exit the function - return; - } -//--- Bicubic interpolation - if((int)MathRound(c.m_c[1])==-3) - { - //--- Prepare info - t0=1; - t1=t; - t2=CMath::Sqr(t); - t3=t*t2; - u0=1; - u1=u; - u2=CMath::Sqr(u); - u3=u*u2; - sf=4+n+m; - sfx=4+n+m+n*m; - sfy=4+n+m+2*n*m; - sfxy=4+n+m+3*n*m; - s1=n*iy+ix; - s2=n*iy+(ix+1); - s3=n*(iy+1)+(ix+1); - s4=n*(iy+1)+ix; - //--- Calculate - v=1*c.m_c[sf+s1]; - f=f+v*t0*u0; - v=1*c.m_c[sfy+s1]/du; - f=f+v*t0*u1; - fy=fy+1*v*t0*u0*du; - v=-(3*c.m_c[sf+s1])+3*c.m_c[sf+s4]-2*c.m_c[sfy+s1]/du-1*c.m_c[sfy+s4]/du; - f=f+v*t0*u2; - fy=fy+2*v*t0*u1*du; - v=2*c.m_c[sf+s1]-2*c.m_c[sf+s4]+1*c.m_c[sfy+s1]/du+1*c.m_c[sfy+s4]/du; - f=f+v*t0*u3; - fy=fy+3*v*t0*u2*du; - v=1*c.m_c[sfx+s1]/dt; - f=f+v*t1*u0; - fx=fx+1*v*t0*u0*dt; - v=1*c.m_c[sfxy+s1]/(dt*du); - f=f+v*t1*u1; - fx=fx+1*v*t0*u1*dt; - fy=fy+1*v*t1*u0*du; - fxy=fxy+1*v*t0*u0*dt*du; - v=-(3*c.m_c[sfx+s1]/dt)+3*c.m_c[sfx+s4]/dt-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t1*u2; - fx=fx+1*v*t0*u2*dt; - fy=fy+2*v*t1*u1*du; - fxy=fxy+2*v*t0*u1*dt*du; - v=2*c.m_c[sfx+s1]/dt-2*c.m_c[sfx+s4]/dt+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t1*u3; - fx=fx+1*v*t0*u3*dt; - fy=fy+3*v*t1*u2*du; - fxy=fxy+3*v*t0*u2*dt*du; - v=-(3*c.m_c[sf+s1])+3*c.m_c[sf+s2]-2*c.m_c[sfx+s1]/dt-1*c.m_c[sfx+s2]/dt; - f=f+v*t2*u0; - fx=fx+2*v*t1*u0*dt; - v=-(3*c.m_c[sfy+s1]/du)+3*c.m_c[sfy+s2]/du-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s2]/(dt*du); - f=f+v*t2*u1; - fx=fx+2*v*t1*u1*dt; - fy=fy+1*v*t2*u0*du; - fxy=fxy+2*v*t1*u0*dt*du; - v=9*c.m_c[sf+s1]-9*c.m_c[sf+s2]+9*c.m_c[sf+s3]-9*c.m_c[sf+s4]+6*c.m_c[sfx+s1]/dt+3*c.m_c[sfx+s2]/dt-3*c.m_c[sfx+s3]/dt-6*c.m_c[sfx+s4]/dt+6*c.m_c[sfy+s1]/du-6*c.m_c[sfy+s2]/du-3*c.m_c[sfy+s3]/du+3*c.m_c[sfy+s4]/du+4*c.m_c[sfxy+s1]/(dt*du)+2*c.m_c[sfxy+s2]/(dt*du)+1*c.m_c[sfxy+s3]/(dt*du)+2*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t2*u2; - fx=fx+2*v*t1*u2*dt; - fy=fy+2*v*t2*u1*du; - fxy=fxy+4*v*t1*u1*dt*du; - v=-(6*c.m_c[sf+s1])+6*c.m_c[sf+s2]-6*c.m_c[sf+s3]+6*c.m_c[sf+s4]-4*c.m_c[sfx+s1]/dt-2*c.m_c[sfx+s2]/dt+2*c.m_c[sfx+s3]/dt+4*c.m_c[sfx+s4]/dt-3*c.m_c[sfy+s1]/du+3*c.m_c[sfy+s2]/du+3*c.m_c[sfy+s3]/du-3*c.m_c[sfy+s4]/du-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s2]/(dt*du)-1*c.m_c[sfxy+s3]/(dt*du)-2*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t2*u3; - fx=fx+2*v*t1*u3*dt; - fy=fy+3*v*t2*u2*du; - fxy=fxy+6*v*t1*u2*dt*du; - v=2*c.m_c[sf+s1]-2*c.m_c[sf+s2]+1*c.m_c[sfx+s1]/dt+1*c.m_c[sfx+s2]/dt; - f=f+v*t3*u0; - fx=fx+3*v*t2*u0*dt; - v=2*c.m_c[sfy+s1]/du-2*c.m_c[sfy+s2]/du+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s2]/(dt*du); - f=f+v*t3*u1; - fx=fx+3*v*t2*u1*dt; - fy=fy+1*v*t3*u0*du; - fxy=fxy+3*v*t2*u0*dt*du; - v=-(6*c.m_c[sf+s1])+6*c.m_c[sf+s2]-6*c.m_c[sf+s3]+6*c.m_c[sf+s4]-3*c.m_c[sfx+s1]/dt-3*c.m_c[sfx+s2]/dt+3*c.m_c[sfx+s3]/dt+3*c.m_c[sfx+s4]/dt-4*c.m_c[sfy+s1]/du+4*c.m_c[sfy+s2]/du+2*c.m_c[sfy+s3]/du-2*c.m_c[sfy+s4]/du-2*c.m_c[sfxy+s1]/(dt*du)-2*c.m_c[sfxy+s2]/(dt*du)-1*c.m_c[sfxy+s3]/(dt*du)-1*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t3*u2; - fx=fx+3*v*t2*u2*dt; - fy=fy+2*v*t3*u1*du; - fxy=fxy+6*v*t2*u1*dt*du; - v=4*c.m_c[sf+s1]-4*c.m_c[sf+s2]+4*c.m_c[sf+s3]-4*c.m_c[sf+s4]+2*c.m_c[sfx+s1]/dt+2*c.m_c[sfx+s2]/dt-2*c.m_c[sfx+s3]/dt-2*c.m_c[sfx+s4]/dt+2*c.m_c[sfy+s1]/du-2*c.m_c[sfy+s2]/du-2*c.m_c[sfy+s3]/du+2*c.m_c[sfy+s4]/du+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s2]/(dt*du)+1*c.m_c[sfxy+s3]/(dt*du)+1*c.m_c[sfxy+s4]/(dt*du); - f=f+v*t3*u3; - fx=fx+3*v*t2*u3*dt; - fy=fy+3*v*t3*u2*du; - fxy=fxy+9*v*t2*u2*dt*du; - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| This subroutine unpacks two-dimensional spline into the | -//| coefficients table | -//| Input parameters: | -//| C - spline interpolant. | -//| Result: | -//| M, N- grid size (x-axis and y-axis) | -//| Tbl - coefficients table, unpacked format, | -//| [0..(N-1)*(M-1)-1, 0..19]. | -//| For I = 0...M-2, J=0..N-2: | -//| K = I*(N-1)+J | -//| Tbl[K,0] = X[j] | -//| Tbl[K,1] = X[j+1] | -//| Tbl[K,2] = Y[i] | -//| Tbl[K,3] = Y[i+1] | -//| Tbl[K,4] = C00 | -//| Tbl[K,5] = C01 | -//| Tbl[K,6] = C02 | -//| Tbl[K,7] = C03 | -//| Tbl[K,8] = C10 | -//| Tbl[K,9] = C11 | -//| ... | -//| Tbl[K,19] = C33 | -//| On each grid square spline is equals to: | -//| S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3) | -//| t = x-x[j] | -//| u = y-y[i] | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DUnpack(CSpline2DInterpolant &c,int &m, - int &n,CMatrixDouble &tbl) - { -//--- create variables - int i=0; - int j=0; - int ci=0; - int cj=0; - int k=0; - int p=0; - int shift=0; - int s1=0; - int s2=0; - int s3=0; - int s4=0; - int sf=0; - int sfx=0; - int sfy=0; - int sfxy=0; - double y1=0; - double y2=0; - double y3=0; - double y4=0; - double dt=0; - double du=0; -//--- initialization - m=0; - n=0; -//--- check - if(!CAp::Assert((int)MathRound(c.m_c[1])==-3 || (int)MathRound(c.m_c[1])==-1,__FUNCTION__+": incorrect C!")) - return; -//--- initialization - n=(int)MathRound(c.m_c[2]); - m=(int)MathRound(c.m_c[3]); -//--- allocation - tbl.Resize((n-1)*(m-1),20); -//--- Fill - for(i=0;i<=m-2;i++) - { - for(j=0;j<=n-2;j++) - { - //--- calculation - p=i*(n-1)+j; - tbl[p].Set(0,c.m_c[4+j]); - tbl[p].Set(1,c.m_c[4+j+1]); - tbl[p].Set(2,c.m_c[4+n+i]); - tbl[p].Set(3,c.m_c[4+n+i+1]); - dt=1/(tbl[p][1]-tbl[p][0]); - du=1/(tbl[p][3]-tbl[p][2]); - //--- Bilinear interpolation - if((int)MathRound(c.m_c[1])==-1) - { - for(k=4;k<=19;k++) - tbl[p].Set(k,0); - //--- calculation - shift=4+n+m; - y1=c.m_c[shift+n*i+j]; - y2=c.m_c[shift+n*i+(j+1)]; - y3=c.m_c[shift+n*(i+1)+(j+1)]; - y4=c.m_c[shift+n*(i+1)+j]; - tbl[p].Set(4,y1); - tbl[p].Set(4+1*4+0,y2-y1); - tbl[p].Set(4+0*4+1,y4-y1); - tbl[p].Set(4+1*4+1,y3-y2-y4+y1); - } - //--- Bicubic interpolation - if((int)MathRound(c.m_c[1])==-3) - { - //--- change values - sf=4+n+m; - sfx=4+n+m+n*m; - sfy=4+n+m+2*n*m; - sfxy=4+n+m+3*n*m; - s1=n*i+j; - s2=n*i+(j+1); - s3=n*(i+1)+(j+1); - s4=n*(i+1)+j; - //--- change values - tbl[p].Set(4+0*4+0,1*c.m_c[sf+s1]); - tbl[p].Set(4+0*4+1,1*c.m_c[sfy+s1]/du); - tbl[p].Set(4+0*4+2,-(3*c.m_c[sf+s1])+3*c.m_c[sf+s4]-2*c.m_c[sfy+s1]/du-1*c.m_c[sfy+s4]/du); - tbl[p].Set(4+0*4+3,2*c.m_c[sf+s1]-2*c.m_c[sf+s4]+1*c.m_c[sfy+s1]/du+1*c.m_c[sfy+s4]/du); - tbl[p].Set(4+1*4+0,1*c.m_c[sfx+s1]/dt); - tbl[p].Set(4+1*4+1,1*c.m_c[sfxy+s1]/(dt*du)); - tbl[p].Set(4+1*4+2,-(3*c.m_c[sfx+s1]/dt)+3*c.m_c[sfx+s4]/dt-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s4]/(dt*du)); - tbl[p].Set(4+1*4+3,2*c.m_c[sfx+s1]/dt-2*c.m_c[sfx+s4]/dt+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s4]/(dt*du)); - tbl[p].Set(4+2*4+0,-(3*c.m_c[sf+s1])+3*c.m_c[sf+s2]-2*c.m_c[sfx+s1]/dt-1*c.m_c[sfx+s2]/dt); - tbl[p].Set(4+2*4+1,-(3*c.m_c[sfy+s1]/du)+3*c.m_c[sfy+s2]/du-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s2]/(dt*du)); - tbl[p].Set(4+2*4+2,9*c.m_c[sf+s1]-9*c.m_c[sf+s2]+9*c.m_c[sf+s3]-9*c.m_c[sf+s4]+6*c.m_c[sfx+s1]/dt+3*c.m_c[sfx+s2]/dt-3*c.m_c[sfx+s3]/dt-6*c.m_c[sfx+s4]/dt+6*c.m_c[sfy+s1]/du-6*c.m_c[sfy+s2]/du-3*c.m_c[sfy+s3]/du+3*c.m_c[sfy+s4]/du+4*c.m_c[sfxy+s1]/(dt*du)+2*c.m_c[sfxy+s2]/(dt*du)+1*c.m_c[sfxy+s3]/(dt*du)+2*c.m_c[sfxy+s4]/(dt*du)); - tbl[p].Set(4+2*4+3,-(6*c.m_c[sf+s1])+6*c.m_c[sf+s2]-6*c.m_c[sf+s3]+6*c.m_c[sf+s4]-4*c.m_c[sfx+s1]/dt-2*c.m_c[sfx+s2]/dt+2*c.m_c[sfx+s3]/dt+4*c.m_c[sfx+s4]/dt-3*c.m_c[sfy+s1]/du+3*c.m_c[sfy+s2]/du+3*c.m_c[sfy+s3]/du-3*c.m_c[sfy+s4]/du-2*c.m_c[sfxy+s1]/(dt*du)-1*c.m_c[sfxy+s2]/(dt*du)-1*c.m_c[sfxy+s3]/(dt*du)-2*c.m_c[sfxy+s4]/(dt*du)); - tbl[p].Set(4+3*4+0,2*c.m_c[sf+s1]-2*c.m_c[sf+s2]+1*c.m_c[sfx+s1]/dt+1*c.m_c[sfx+s2]/dt); - tbl[p].Set(4+3*4+1,2*c.m_c[sfy+s1]/du-2*c.m_c[sfy+s2]/du+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s2]/(dt*du)); - tbl[p].Set(4+3*4+2,-(6*c.m_c[sf+s1])+6*c.m_c[sf+s2]-6*c.m_c[sf+s3]+6*c.m_c[sf+s4]-3*c.m_c[sfx+s1]/dt-3*c.m_c[sfx+s2]/dt+3*c.m_c[sfx+s3]/dt+3*c.m_c[sfx+s4]/dt-4*c.m_c[sfy+s1]/du+4*c.m_c[sfy+s2]/du+2*c.m_c[sfy+s3]/du-2*c.m_c[sfy+s4]/du-2*c.m_c[sfxy+s1]/(dt*du)-2*c.m_c[sfxy+s2]/(dt*du)-1*c.m_c[sfxy+s3]/(dt*du)-1*c.m_c[sfxy+s4]/(dt*du)); - tbl[p].Set(4+3*4+3,4*c.m_c[sf+s1]-4*c.m_c[sf+s2]+4*c.m_c[sf+s3]-4*c.m_c[sf+s4]+2*c.m_c[sfx+s1]/dt+2*c.m_c[sfx+s2]/dt-2*c.m_c[sfx+s3]/dt-2*c.m_c[sfx+s4]/dt+2*c.m_c[sfy+s1]/du-2*c.m_c[sfy+s2]/du-2*c.m_c[sfy+s3]/du+2*c.m_c[sfy+s4]/du+1*c.m_c[sfxy+s1]/(dt*du)+1*c.m_c[sfxy+s2]/(dt*du)+1*c.m_c[sfxy+s3]/(dt*du)+1*c.m_c[sfxy+s4]/(dt*du)); - } - //--- Rescale Cij - for(ci=0;ci<=3;ci++) - { - for(cj=0;cj<=3;cj++) - tbl[p].Set(4+ci*4+cj,tbl[p][4+ci*4+cj]*MathPow(dt,ci)*MathPow(du,cj)); - } - } - } - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline | -//| argument. | -//| Input parameters: | -//| C - spline interpolant | -//| AX, BX - transformation coefficients: x = A*t + B | -//| AY, BY - transformation coefficients: y = A*u + B | -//| Result: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DLinTransXY(CSpline2DInterpolant &c,double ax, - double bx,double ay,double by) - { -//--- create variables - int i=0; - int j=0; - int n=0; - int m=0; - double v=0; - int typec=0; -//--- create arrays - double x[]; - double y[]; -//--- create matrix - CMatrixDouble f; -//--- initialization - typec=(int)MathRound(c.m_c[1]); -//--- check - if(!CAp::Assert(typec==-3 || typec==-1,__FUNCTION__+": incorrect C!")) - return; -//--- initialization - n=(int)MathRound(c.m_c[2]); - m=(int)MathRound(c.m_c[3]); -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,m); - f.Resize(m,n); -//--- copy - for(j=0;j<=n-1;j++) - x[j]=c.m_c[4+j]; - for(i=0;i<=m-1;i++) - y[i]=c.m_c[4+n+i]; - for(i=0;i<=m-1;i++) - { - for(j=0;j<=n-1;j++) - f[i].Set(j,c.m_c[4+n+m+i*n+j]); - } -//--- Special case: AX=0 or AY=0 - if(ax==0.0) - { - //--- change values - for(i=0;i<=m-1;i++) - { - v=Spline2DCalc(c,bx,y[i]); - for(j=0;j<=n-1;j++) - f[i].Set(j,v); - } - //--- check - if(typec==-3) - Spline2DBuildBicubic(x,y,f,m,n,c); - //--- check - if(typec==-1) - Spline2DBuildBilinear(x,y,f,m,n,c); - //--- change values - ax=1; - bx=0; - } -//--- check - if(ay==0.0) - { - //--- change values - for(j=0;j<=n-1;j++) - { - v=Spline2DCalc(c,x[j],by); - for(i=0;i<=m-1;i++) - f[i].Set(j,v); - } - //--- check - if(typec==-3) - Spline2DBuildBicubic(x,y,f,m,n,c); - //--- check - if(typec==-1) - Spline2DBuildBilinear(x,y,f,m,n,c); - //--- change values - ay=1; - by=0; - } -//--- General case: AX<>0,AY<>0 -//--- Unpack,scale and pack again. - for(j=0;j<=n-1;j++) - x[j]=(x[j]-bx)/ax; - for(i=0;i<=m-1;i++) - y[i]=(y[i]-by)/ay; -//--- check - if(typec==-3) - Spline2DBuildBicubic(x,y,f,m,n,c); -//--- check - if(typec==-1) - Spline2DBuildBilinear(x,y,f,m,n,c); - } -//+------------------------------------------------------------------+ -//| This subroutine performs linear transformation of the spline. | -//| Input parameters: | -//| C - spline interpolant. | -//| A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B | -//| Output parameters: | -//| C - transformed spline | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DLinTransF(CSpline2DInterpolant &c,const double a, - const double b) - { -//--- create variables - int i=0; - int j=0; - int n=0; - int m=0; - int typec=0; -//--- create arrays - double x[]; - double y[]; -//--- create matrix - CMatrixDouble f; -//--- initialization - typec=(int)MathRound(c.m_c[1]); -//--- check - if(!CAp::Assert(typec==-3 || typec==-1,__FUNCTION__+": incorrect C!")) - return; -//--- initialization - n=(int)MathRound(c.m_c[2]); - m=(int)MathRound(c.m_c[3]); -//--- allocation - ArrayResizeAL(x,n); - ArrayResizeAL(y,m); - f.Resize(m,n); -//--- copy - for(j=0;j<=n-1;j++) - x[j]=c.m_c[4+j]; - for(i=0;i<=m-1;i++) - y[i]=c.m_c[4+n+i]; - for(i=0;i<=m-1;i++) - { - for(j=0;j<=n-1;j++) - f[i].Set(j,a*c.m_c[4+n+m+i*n+j]+b); - } -//--- check - if(typec==-3) - Spline2DBuildBicubic(x,y,f,m,n,c); -//--- check - if(typec==-1) - Spline2DBuildBilinear(x,y,f,m,n,c); - } -//+------------------------------------------------------------------+ -//| This subroutine makes the copy of the spline model. | -//| Input parameters: | -//| C - spline interpolant | -//| Output parameters: | -//| CC - spline copy | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DCopy(CSpline2DInterpolant &c,CSpline2DInterpolant &cc) - { -//--- create variables - int n=0; - int i_=0; -//--- check - if(!CAp::Assert(c.m_k==1 || c.m_k==3,__FUNCTION__+": incorrect C!")) - return; -//--- change values - cc.m_k=c.m_k; - n=(int)MathRound(c.m_c[0]); -//--- allocation - ArrayResizeAL(cc.m_c,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - cc.m_c[i_]=c.m_c[i_]; - } -//+------------------------------------------------------------------+ -//| Bicubic spline resampling | -//| Input parameters: | -//| A - function values at the old grid, | -//| array[0..OldHeight-1, 0..OldWidth-1] | -//| OldHeight - old grid height, OldHeight>1 | -//| OldWidth - old grid width, OldWidth>1 | -//| NewHeight - new grid height, NewHeight>1 | -//| NewWidth - new grid width, NewWidth>1 | -//| Output parameters: | -//| B - function values at the new grid, | -//| array[0..NewHeight-1, 0..NewWidth-1] | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight, - const int oldwidth,CMatrixDouble &b, - const int newheight,const int newwidth) - { -//--- create variables - int i=0; - int j=0; - int mw=0; - int mh=0; -//--- create arrays - double x[]; - double y[]; -//--- create matrix - CMatrixDouble buf; -//--- object of class - CSpline1DInterpolant c; -//--- check - if(!CAp::Assert(oldwidth>1 && oldheight>1,__FUNCTION__+": width/height less than 1")) - return; -//--- check - if(!CAp::Assert(newwidth>1 && newheight>1,__FUNCTION__+": width/height less than 1")) - return; -//--- Prepare - mw=MathMax(oldwidth,newwidth); - mh=MathMax(oldheight,newheight); -//--- allocation - b.Resize(newheight,newwidth); - buf.Resize(oldheight,newwidth); - ArrayResizeAL(x,MathMax(mw,mh)); - ArrayResizeAL(y,MathMax(mw,mh)); -//--- Horizontal interpolation - for(i=0;i<=oldheight-1;i++) - { - //--- Fill X,Y - for(j=0;j<=oldwidth-1;j++) - { - x[j]=(double)j/(double)(oldwidth-1); - y[j]=a[i][j]; - } - //--- Interpolate and place result into temporary matrix - CSpline1D::Spline1DBuildCubic(x,y,oldwidth,0,0.0,0,0.0,c); - for(j=0;j<=newwidth-1;j++) - buf[i].Set(j,CSpline1D::Spline1DCalc(c,(double)j/(double)(newwidth-1))); - } -//--- Vertical interpolation - for(j=0;j<=newwidth-1;j++) - { - //--- Fill X,Y - for(i=0;i<=oldheight-1;i++) - { - x[i]=(double)i/(double)(oldheight-1); - y[i]=buf[i][j]; - } - //--- Interpolate and place result into B - CSpline1D::Spline1DBuildCubic(x,y,oldheight,0,0.0,0,0.0,c); - for(i=0;i<=newheight-1;i++) - b[i].Set(j,CSpline1D::Spline1DCalc(c,(double)i/(double)(newheight-1))); - } - } -//+------------------------------------------------------------------+ -//| Bilinear spline resampling | -//| Input parameters: | -//| A - function values at the old grid, | -//| array[0..OldHeight-1, 0..OldWidth-1] | -//| OldHeight - old grid height, OldHeight>1 | -//| OldWidth - old grid width, OldWidth>1 | -//| NewHeight - new grid height, NewHeight>1 | -//| NewWidth - new grid width, NewWidth>1 | -//| Output parameters: | -//| B - function values at the new grid, | -//| array[0..NewHeight-1, 0..NewWidth-1] | -//+------------------------------------------------------------------+ -static void CSpline2D::Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight, - const int oldwidth,CMatrixDouble &b, - const int newheight,const int newwidth) - { -//--- create variables - int i=0; - int j=0; - int l=0; - int c=0; - double t=0; - double u=0; -//--- allocation - b.Resize(newheight,newwidth); - for(i=0;i<=newheight-1;i++) - { - for(j=0;j<=newwidth-1;j++) - { - //--- calculation - l=i*(oldheight-1)/(newheight-1); - //--- check - if(l==oldheight-1) - l=oldheight-2; - //--- calculation - u=(double)i/(double)(newheight-1)*(oldheight-1)-l; - c=j*(oldwidth-1)/(newwidth-1); - //--- check - if(c==oldwidth-1) - c=oldwidth-2; - //--- calculation - t=(double)(j*(oldwidth-1))/(double)(newwidth-1)-c; - b[i].Set(j,(1-t)*(1-u)*a[l][c]+t*(1-u)*a[l][c+1]+t*u*a[l+1][c+1]+(1-t)*u*a[l+1][c]); - } - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine. | -//| Calculation of the first derivatives and the cross-derivative. | -//+------------------------------------------------------------------+ -static void CSpline2D::BicubicCalcDerivatives(CMatrixDouble &a,double &x[], - double &y[],const int m, - const int n,CMatrixDouble &dx, - CMatrixDouble &dy,CMatrixDouble &dxy) - { -//--- create variables - int i=0; - int j=0; - double s=0; - double ds=0; - double d2s=0; -//--- create arrays - double xt[]; - double ft[]; -//--- object of class - CSpline1DInterpolant c; -//--- allocation - dx.Resize(m,n); - dy.Resize(m,n); - dxy.Resize(m,n); -//--- dF/dX - ArrayResizeAL(xt,n); - ArrayResizeAL(ft,n); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=n-1;j++) - { - xt[j]=x[j]; - ft[j]=a[i][j]; - } - //--- function call - CSpline1D::Spline1DBuildCubic(xt,ft,n,0,0.0,0,0.0,c); - for(j=0;j<=n-1;j++) - { - //--- function call - CSpline1D::Spline1DDiff(c,x[j],s,ds,d2s); - dx[i].Set(j,ds); - } - } -//--- dF/dY - ArrayResizeAL(xt,m); - ArrayResizeAL(ft,m); - for(j=0;j<=n-1;j++) - { - for(i=0;i<=m-1;i++) - { - xt[i]=y[i]; - ft[i]=a[i][j]; - } - //--- function call - CSpline1D::Spline1DBuildCubic(xt,ft,m,0,0.0,0,0.0,c); - for(i=0;i<=m-1;i++) - { - //--- function call - CSpline1D::Spline1DDiff(c,y[i],s,ds,d2s); - dy[i].Set(j,ds); - } - } -//--- d2F/dXdY - ArrayResizeAL(xt,n); - ArrayResizeAL(ft,n); - for(i=0;i<=m-1;i++) - { - for(j=0;j<=n-1;j++) - { - xt[j]=x[j]; - ft[j]=dy[i][j]; - } - //--- function call - CSpline1D::Spline1DBuildCubic(xt,ft,n,0,0.0,0,0.0,c); - for(j=0;j<=n-1;j++) - { - //--- function call - CSpline1D::Spline1DDiff(c,x[j],s,ds,d2s); - dxy[i].Set(j,ds); - } - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/linalg.mqh b/Include/Math/Alglib/linalg.mqh deleted file mode 100644 index ee3617b..0000000 --- a/Include/Math/Alglib/linalg.mqh +++ /dev/null @@ -1,20339 +0,0 @@ -//+------------------------------------------------------------------+ -//| linalg.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY;without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "alglibinternal.mqh" -#include "alglibmisc.mqh" -//+------------------------------------------------------------------+ -//| Work with matrix forms | -//+------------------------------------------------------------------+ -class CAblas - { -private: - //--- split lenght - static void AblasInternalSplitLength(const int n,const int nb,int &n1,int &n2); - //--- real numbers - static void RMatrixSyrk2(const int n,const int k,const double alpha,const CMatrixDouble &a,const int ia,const int ja,const int optypea,const double beta,CMatrixDouble &c,const int ic,const int jc,const bool isUpper); - static void RMatrixGemmK(const int m,const int n,const int k,const double alpha,const CMatrixDouble &a,const int ia,const int ja,const int optypea,const CMatrixDouble &b,const int ib,const int jb,const int optypeb,const double beta,CMatrixDouble &c,const int ic,const int jc); - static void RMatrixRightTrsM2(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixDouble &x,const int i2,const int j2); - static void RMatrixLeftTrsM2(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixDouble &x,const int i2,const int j2); - //--- complex numbers - static void CMatrixSyrk2(const int n,const int k,const double alpha,const CMatrixComplex &a,const int ia,const int ja,const int optypea,const double beta,CMatrixComplex &c,const int ic,const int jc,const bool isUpper); - static void CMatrixGemmk(const int m,const int n,const int k,al_complex &alpha,const CMatrixComplex &a,const int ia,const int ja,const int optypea,const CMatrixComplex &b,const int ib,const int jb,const int optypeb,al_complex &beta,CMatrixComplex &c,const int ic,const int jc); - static void CMatrixRightTrsM2(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixComplex &x,const int i2,const int j2); - static void CMatrixLeftTrsM2(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixComplex &x,const int i2,const int j2); -public: - CAblas(void); - ~CAblas(void); - //--- size - static int AblasBlockSize(void) { return(32);} - static int AblasMicroBlockSize(void) { return(8); } - static int AblasComplexBlockSize(void) { return(24);} - //--- split lenght - static void AblasSplitLength(const CMatrixDouble &a,const int n,int &n1,int &n2); - static void AblasComplexSplitLength(const CMatrixComplex &a,const int n,int &n1,int &n2); - //--- real numbers - static void RMatrixSyrk(const int n,const int k,const double alpha,const CMatrixDouble &a,const int ia,const int ja,const int optypea,const double beta,CMatrixDouble &c,const int ic,const int jc,const bool isUpper); - static void RMatrixGemm(const int m,const int n,const int k,const double alpha,const CMatrixDouble &a,const int ia,const int ja,const int optypea,const CMatrixDouble &b,const int ib,const int jb,const int optypeb,const double beta,CMatrixDouble &c,const int ic,const int jc); - static void RMatrixTranspose(const int m,const int n,const CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb); - static void RMatrixCopy(const int m,const int n,const CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb); - static void RMatrixRank1(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,const double &u[],const int iu,const double &v[],const int iv); - static void RMatrixMVect(const int m,const int n,const CMatrixDouble &a,const int ia,const int ja,const int opa,const double &x[],const int ix,double &y[],const int iy); - static void RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixDouble &x,const int i2,const int j2); - static void RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixDouble &x,const int i2,const int j2); - //--- complex numbers - static void CMatrixSyrk(const int n,const int k,const double alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,const double beta,CMatrixComplex &c,const int ic,const int jc,const bool isUpper); - static void CMatrixGemm(const int m,const int n,const int k,al_complex &alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,CMatrixComplex &b,const int ib,const int jb,const int optypeb,al_complex &beta,CMatrixComplex &c,const int ic,const int jc); - static void CMatrixTranspose(const int m,const int n,const CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb); - static void CMatrixCopy(const int m,const int n,const CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb); - static void CMatrixRank1(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,const al_complex &u[],const int iu,const al_complex &v[],const int iv); - static void CMatrixMVect(const int m,const int n,const CMatrixComplex &a,const int ia,const int ja,const int opa,const al_complex &x[],const int ix,al_complex &y[],const int iy); - static void CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixComplex &x,const int i2,const int j2); - static void CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isUpper,const bool isUnit,const int optype,CMatrixComplex &x,const int i2,const int j2); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CAblas::CAblas(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CAblas::~CAblas(void) - { - - } -//+------------------------------------------------------------------+ -//| Same as CMatrixSYRK, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixSyrk(const int n,const int k,const double alpha, - const CMatrixDouble &a,const int ia,const int ja, - const int optypea,const double beta,CMatrixDouble &c, - const int ic,const int jc,const bool isUpper) - { -//--- create variables - int s1=0; - int s2=0; - int bs=0; -//--- calculation size - bs=AblasBlockSize(); -//--- check - if(n<=bs && k<=bs) - { - RMatrixSyrk2(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - return; - } -//--- check - if(k>=n) - { - //--- Split K - AblasSplitLength(a,k,s1,s2); - //--- check - if(optypea==0) - { - RMatrixSyrk(n,s1,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixSyrk(n,s2,alpha,a,ia,ja+s1,optypea,1.0,c,ic,jc,isUpper); - } - else - { - RMatrixSyrk(n,s1,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixSyrk(n,s2,alpha,a,ia+s1,ja,optypea,1.0,c,ic,jc,isUpper); - } - } - else - { - //--- Split N - AblasSplitLength(a,n,s1,s2); - //--- check - if(optypea==0 && isUpper) - { - RMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixGemm(s1,s2,k,alpha,a,ia,ja,0,a,ia+s1,ja,1,beta,c,ic,jc+s1); - RMatrixSyrk(s2,k,alpha,a,ia+s1,ja,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea==0 && !isUpper) - { - RMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixGemm(s2,s1,k,alpha,a,ia+s1,ja,0,a,ia,ja,1,beta,c,ic+s1,jc); - RMatrixSyrk(s2,k,alpha,a,ia+s1,ja,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea!=0 && isUpper) - { - RMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixGemm(s1,s2,k,alpha,a,ia,ja,1,a,ia,ja+s1,0,beta,c,ic,jc+s1); - RMatrixSyrk(s2,k,alpha,a,ia,ja+s1,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea!=0 && !isUpper) - { - RMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - RMatrixGemm(s2,s1,k,alpha,a,ia,ja+s1,1,a,ia,ja,0,beta,c,ic+s1,jc); - RMatrixSyrk(s2,k,alpha,a,ia,ja+s1,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Splits matrix length in two parts, left part should match ABLAS | -//| block size | -//| INPUT PARAMETERS | -//| A - real matrix, is passed to ensure that we didn't split| -//| complex matrix using real splitting subroutine. | -//| matrix itself is not changed. | -//| N - length, N>0 | -//| OUTPUT PARAMETERS | -//| N1 - length | -//| N2 - length | -//| N1+N2=N, N1>=N2, N2 may be zero | -//+------------------------------------------------------------------+ -static void CAblas::AblasSplitLength(const CMatrixDouble &a,const int n, - int &n1,int &n2) - { -//--- initialization - n1=0; - n2=0; -//--- check - if(n>AblasBlockSize()) - AblasInternalSplitLength(n,AblasBlockSize(),n1,n2); - else - AblasInternalSplitLength(n,AblasMicroBlockSize(),n1,n2); -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Complex ABLASSplitLength | -//+------------------------------------------------------------------+ -static void CAblas::AblasComplexSplitLength(const CMatrixComplex &a,const int n, - int &n1,int &n2) - { -//--- check - if(n>AblasComplexBlockSize()) - AblasInternalSplitLength(n,AblasComplexBlockSize(),n1,n2); - else - AblasInternalSplitLength(n,AblasMicroBlockSize(),n1,n2); - } -//+------------------------------------------------------------------+ -//| Same as CMatrixGEMM, but for real numbers. | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixGemm(const int m,const int n,const int k,const double alpha, - const CMatrixDouble &a,const int ia,const int ja, - const int optypea,const CMatrixDouble &b, - const int ib,const int jb,const int optypeb, - const double beta,CMatrixDouble &c,const int ic, - const int jc) - { -//--- create variables - int s1=0; - int s2=0; - int bs; -//--- calculation size - bs=AblasBlockSize(); -//--- check - if(m<=bs && n<=bs && k<=bs) - { - RMatrixGemmK(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - return; - } -//--- check - if(m>=n && m>=k) - { - //--- A*B = (A1 A2)^T*B - AblasSplitLength(a,m,s1,s2); - //--- check - if(optypea==0) - { - RMatrixGemm(s1,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(s2,n,k,alpha,a,ia+s1,ja,optypea,b,ib,jb,optypeb,beta,c,ic+s1,jc); - } - else - { - RMatrixGemm(s1,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(s2,n,k,alpha,a,ia,ja+s1,optypea,b,ib,jb,optypeb,beta,c,ic+s1,jc); - } - return; - } -//--- check - if(n>=m && n>=k) - { - //--- A*B = A*(B1 B2) - AblasSplitLength(a,n,s1,s2); - //--- check - if(optypeb==0) - { - RMatrixGemm(m,s1,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,s2,k,alpha,a,ia,ja,optypea,b,ib,jb+s1,optypeb,beta,c,ic,jc+s1); - } - else - { - RMatrixGemm(m,s1,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,s2,k,alpha,a,ia,ja,optypea,b,ib+s1,jb,optypeb,beta,c,ic,jc+s1); - } - return; - } -//--- check - if(k>=m && k>=n) - { - //--- A*B = (A1 A2)*(B1 B2)^T - AblasSplitLength(a,k,s1,s2); - //--- check - if(optypea==0 && optypeb==0) - { - RMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,n,s2,alpha,a,ia,ja+s1,optypea,b,ib+s1,jb,optypeb,1.0,c,ic,jc); - } - //--- check - if(optypea==0 && optypeb!=0) - { - RMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,n,s2,alpha,a,ia,ja+s1,optypea,b,ib,jb+s1,optypeb,1.0,c,ic,jc); - } - //--- check - if(optypea!=0 && optypeb==0) - { - RMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,n,s2,alpha,a,ia+s1,ja,optypea,b,ib+s1,jb,optypeb,1.0,c,ic,jc); - } - //--- check - if(optypea!=0 && optypeb!=0) - { - RMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - RMatrixGemm(m,n,s2,alpha,a,ia+s1,ja,optypea,b,ib,jb+s1,optypeb,1.0,c,ic,jc); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Level 2 subrotuine | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixSyrk2(const int n,const int k,const double alpha, - const CMatrixDouble &a,const int ia,const int ja, - const int optypea,const double beta,CMatrixDouble &c, - const int ic,const int jc,const bool isUpper) - { -//--- check - if((alpha==0.0 || k==0.0) && beta==1.0) - return; -//--- create variables - int i=0; - int j=0; - int j1=0; - int j2=0; - double v=0; - int i_=0; - int i1_=0; -//--- check - if(optypea==0) - { - //--- C=alpha*A*A^H+beta*C - for(i=0;i0) - { - v=0.0; - for(i_=ja;i_n) - { - //--- split - AblasComplexSplitLength(a,m,s1,s2); - //--- function call - CMatrixTranspose(s1,n,a,ia,ja,b,ib,jb); - CMatrixTranspose(s2,n,a,ia+s1,ja,b,ib,jb+s1); - } - else - { - //--- split - AblasComplexSplitLength(a,n,s1,s2); - //--- function call - CMatrixTranspose(m,s1,a,ia,ja,b,ib,jb); - CMatrixTranspose(m,s2,a,ia,ja+s1,b,ib+s1,jb); - } - } - } -//+------------------------------------------------------------------+ -//| Cache-oblivous real "copy-and-transpose" | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| A - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixTranspose(const int m,const int n,const CMatrixDouble &a, - const int ia,const int ja,CMatrixDouble &b, - const int ib,const int jb) - { -//--- create variables - int i=0; - int s1=0; - int s2=0; - int i_=0; - int i1_=0; -//--- check - if(m<=2*AblasBlockSize() && n<=2*AblasBlockSize()) - { - //--- base case - for(i=0;in) - { - //--- split - AblasSplitLength(a,m,s1,s2); - //--- function call - RMatrixTranspose(s1,n,a,ia,ja,b,ib,jb); - RMatrixTranspose(s2,n,a,ia+s1,ja,b,ib,jb+s1); - } - else - { - //--- split - AblasSplitLength(a,n,s1,s2); - //--- function call - RMatrixTranspose(m,s1,a,ia,ja,b,ib,jb); - RMatrixTranspose(m,s2,a,ia,ja+s1,b,ib+s1,jb); - } - } - } -//+------------------------------------------------------------------+ -//| Copy | -//| Input parameters: | -//| M - number of rows | -//| N - number of columns | -//| A - source matrix, MxN submatrix is copied and transposed| -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| B - destination matrix | -//| IB - submatrix offset (row index) | -//| JB - submatrix offset (column index) | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixCopy(const int m,const int n,const CMatrixComplex &a, - const int ia,const int ja,CMatrixComplex &b, - const int ib,const int jb) - { -//--- create variables - int i=0; - int i_=0; - int i1_=0; -//--- copy - for(i=0;i=0 | -//| N - number of columns of op(A) | -//| N>=0 | -//| A - target matrix | -//| IA - submatrix offset (row index) | -//| JA - submatrix offset (column index) | -//| OpA - operation type: | -//| * OpA=0 => op(A) = A | -//| * OpA=1 => op(A) = A^T | -//| * OpA=2 => op(A) = A^H | -//| X - input vector | -//| IX - subvector offset | -//| IY - subvector offset | -//| OUTPUT PARAMETERS: | -//| Y - vector which stores result | -//| if M=0, then subroutine does nothing. | -//| if N=0, Y is filled by zeros. | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixMVect(const int m,const int n,const CMatrixComplex &a, - const int ia,const int ja,const int opa, - const al_complex &x[],const int ix,al_complex &y[], - const int iy) - { -//--- create variables - int i=0; - al_complex v=0; - int i_=0; - int i1_=0; -//--- check - if(m==0) - return; -//--- check - if(n==0) - { - for(i=0;i op(A) = A | -//| * OpA=1 => op(A) = A^T | -//| X - input vector | -//| IX - subvector offset | -//| IY - subvector offset | -//| OUTPUT PARAMETERS: | -//| Y - vector which stores result | -//| if M=0, then subroutine does nothing. | -//| if N=0, Y is filled by zeros. | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixMVect(const int m,const int n,const CMatrixDouble &a, - const int ia,const int ja,const int opa, - const double &x[],const int ix,double &y[], - const int iy) - { -//--- create variables - int i=0; - double v=0; - int i_=0; - int i1_=0; -//--- check - if(m==0) - return; -//--- check - if(n==0) - { - for(i=0;i=0 | -//| M - matrix size, N>=0 | -//| A - matrix, actial matrix is stored in | -//| A[I1:I1+N-1,J1:J1+N-1] | -//| I1 - submatrix offset | -//| J1 - submatrix offset | -//| IsUpper - whether matrix is upper triangular | -//| IsUnit - whether matrix is unitriangular | -//| OpType - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| C - matrix, actial matrix is stored in | -//| C[I2:I2+M-1,J2:J2+N-1] | -//| I2 - submatrix offset | -//| J2 - submatrix offset | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a, - const int i1,const int j1,const bool isUpper, - const bool isUnit,const int optype, - CMatrixComplex &x,const int i2,const int j2) - { -//--- create variables - al_complex Alpha(-1,0); - al_complex Beta(1,0); - int s1=0; - int s2=0; - int bs=AblasComplexBlockSize(); -//--- check - if(m<=bs && n<=bs) - { - //--- basic algorithm - CMatrixRightTrsM2(m,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } -//--- check - if(m>=n) - { - //--- Split X: X*A = (X1 X2)^T*A - AblasComplexSplitLength(a,m,s1,s2); - CMatrixRightTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixRightTrsM(s2,n,a,i1,j1,isUpper,isUnit,optype,x,i2+s1,j2); - } - else - { - //--- Split A: - //--- (A1 A12) - //--- X*op(A) = X*op( ) - //--- ( A2) - //--- - //--- Different variants depending on - //--- IsUpper/OpType combinations - AblasComplexSplitLength(a,n,s1,s2); - //--- check - if(isUpper && optype==0) - { - //--- (A1 A12)-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- ( A2) - CMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixGemm(m,s2,s1,Alpha,x,i2,j2,0,a,i1,j1+s1,0,Beta,x,i2,j2+s1); - CMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - //--- exit the function - return; - } - //--- check - if(isUpper && optype!=0) - { - //--- (A1' )-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- (A12' A2') - CMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - CMatrixGemm(m,s1,s2,Alpha,x,i2,j2+s1,0,a,i1,j1+s1,optype,Beta,x,i2,j2); - CMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype==0) - { - //--- (A1 )-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- (A21 A2) - CMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - CMatrixGemm(m,s1,s2,Alpha,x,i2,j2+s1,0,a,i1+s1,j1,0,Beta,x,i2,j2); - CMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype!=0) - { - //--- (A1' A21')-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- ( A2') - CMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixGemm(m,s2,s1,Alpha,x,i2,j2,0,a,i1+s1,j1,optype,Beta,x,i2,j2+s1); - CMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates op(A^-1)*X where: | -//| * X is MxN general matrix | -//| * A is MxM upper/lower triangular/unitriangular matrix | -//| * "op" may be identity transformation, transposition, conjugate | -//| transposition | -//| Multiplication result replaces X. | -//| Cache-oblivious algorithm is used. | -//| INPUT PARAMETERS | -//| N - matrix size, N>=0 | -//| M - matrix size, N>=0 | -//| A - matrix, actial matrix is stored in | -//| A[I1:I1+M-1,J1:J1+M-1] | -//| I1 - submatrix offset | -//| J1 - submatrix offset | -//| IsUpper - whether matrix is upper triangular | -//| IsUnit - whether matrix is unitriangular | -//| OpType - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| C - matrix, actial matrix is stored in | -//| C[I2:I2+M-1,J2:J2+N-1] | -//| I2 - submatrix offset | -//| J2 - submatrix offset | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a, - const int i1,const int j1,const bool isUpper, - const bool isUnit,const int optype, - CMatrixComplex &x,const int i2,const int j2) - { -//--- create variables - al_complex Alpha(-1,0); - al_complex Beta(1,0); - int s1=0; - int s2=0; - int bs=AblasComplexBlockSize(); -//--- check - if(m<=bs && n<=bs) - { - //--- basic algorithm - CMatrixLeftTrsM2(m,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } -//--- check - if(n>=m) - { - //--- Split X: op(A)^-1*X = op(A)^-1*(X1 X2) - AblasComplexSplitLength(x,n,s1,s2); - CMatrixLeftTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixLeftTrsM(m,s2,a,i1,j1,isUpper,isUnit,optype,x,i2,j2+s1); - } - else - { - //--- Split A - AblasComplexSplitLength(a,m,s1,s2); - //--- check - if(isUpper && optype==0) - { - //--- (A1 A12)-1 ( X1 ) - //--- A^-1*X* = ( ) *( ) - //--- ( A2) ( X2 ) - CMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - CMatrixGemm(s1,n,s2,Alpha,a,i1,j1+s1,0,x,i2+s1,j2,0,Beta,x,i2,j2); - CMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(isUpper && optype!=0) - { - //--- (A1' )-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- (A12' A2') ( X2 ) - CMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixGemm(s2,n,s1,Alpha,a,i1,j1+s1,optype,x,i2,j2,0,Beta,x,i2+s1,j2); - CMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype==0) - { - //--- (A1 )-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- (A21 A2) ( X2 ) - CMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - CMatrixGemm(s2,n,s1,Alpha,a,i1+s1,j1,0,x,i2,j2,0,Beta,x,i2+s1,j2); - CMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype!=0) - { - //--- (A1' A21')-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- ( A2') ( X2 ) - CMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - CMatrixGemm(s1,n,s2,Alpha,a,i1+s1,j1,optype,x,i2+s1,j2,0,Beta,x,i2,j2); - CMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixRightTRSM, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a, - const int i1,const int j1,const bool isUpper, - const bool isUnit,const int optype, - CMatrixDouble &x,const int i2,const int j2) - { -//--- create variables - int s1=0; - int s2=0; - int bs=AblasBlockSize(); -//--- check - if(m<=bs && n<=bs) - { - //--- basic algorithm - RMatrixRightTrsM2(m,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } -//--- check - if(m>=n) - { - //--- Split X: X*A = (X1 X2)^T*A - AblasSplitLength(a,m,s1,s2); - RMatrixRightTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixRightTrsM(s2,n,a,i1,j1,isUpper,isUnit,optype,x,i2+s1,j2); - } - else - { - //--- Split A: - //--- (A1 A12) - //--- X*op(A) = X*op( ) - //--- ( A2) - //--- Different variants depending on - //--- IsUpper/OpType combinations - AblasSplitLength(a,n,s1,s2); - //--- check - if(isUpper && optype==0) - { - //--- (A1 A12)-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- ( A2) - RMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixGemm(m,s2,s1,-1.0,x,i2,j2,0,a,i1,j1+s1,0,1.0,x,i2,j2+s1); - RMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - //--- exit the function - return; - } - //--- check - if(isUpper && optype!=0) - { - //--- (A1' )-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- (A12' A2') - RMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - RMatrixGemm(m,s1,s2,-1.0,x,i2,j2+s1,0,a,i1,j1+s1,optype,1.0,x,i2,j2); - RMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype==0) - { - //--- (A1 )-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- (A21 A2) - RMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - RMatrixGemm(m,s1,s2,-1.0,x,i2,j2+s1,0,a,i1+s1,j1,0,1.0,x,i2,j2); - RMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype!=0) - { - //--- (A1' A21')-1 - //--- X*A^-1 = (X1 X2)*( ) - //--- ( A2') - RMatrixRightTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixGemm(m,s2,s1,-1.0,x,i2,j2,0,a,i1+s1,j1,optype,1.0,x,i2,j2+s1); - RMatrixRightTrsM(m,s2,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2,j2+s1); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Same as CMatrixLeftTRSM, but for real matrices | -//| OpType may be only 0 or 1. | -//+------------------------------------------------------------------+ -static void CAblas::RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a, - const int i1,const int j1,const bool isUpper, - const bool isUnit,const int optype, - CMatrixDouble &x,const int i2,const int j2) - { -//--- create variables - int s1=0; - int s2=0; - int bs=AblasBlockSize(); -//--- check - if(m<=bs && n<=bs) - { - //--- basic algorithm - RMatrixLeftTrsM2(m,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } -//--- check - if(n>=m) - { - //--- Split X: op(A)^-1*X = op(A)^-1*(X1 X2) - AblasSplitLength(x,n,s1,s2); - RMatrixLeftTrsM(m,s1,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixLeftTrsM(m,s2,a,i1,j1,isUpper,isUnit,optype,x,i2,j2+s1); - } - else - { - //--- Split A - AblasSplitLength(a,m,s1,s2); - //--- check - if(isUpper && optype==0) - { - //--- (A1 A12)-1 ( X1 ) - //--- A^-1*X* = ( ) *( ) - //--- ( A2) ( X2 ) - RMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - RMatrixGemm(s1,n,s2,-1.0,a,i1,j1+s1,0,x,i2+s1,j2,0,1.0,x,i2,j2); - RMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - //--- exit the function - return; - } - //--- check - if(isUpper && optype!=0) - { - //--- (A1' )-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- (A12' A2') ( X2 ) - RMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixGemm(s2,n,s1,-1.0,a,i1,j1+s1,optype,x,i2,j2,0,1.0,x,i2+s1,j2); - RMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype==0) - { - //--- (A1 )-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- (A21 A2) ( X2 ) - RMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - RMatrixGemm(s2,n,s1,-1.0,a,i1+s1,j1,0,x,i2,j2,0,1.0,x,i2+s1,j2); - RMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - //--- exit the function - return; - } - //--- check - if(!isUpper && optype!=0) - { - //--- (A1' A21')-1 ( X1 ) - //--- A^-1*X = ( ) *( ) - //--- ( A2') ( X2 ) - RMatrixLeftTrsM(s2,n,a,i1+s1,j1+s1,isUpper,isUnit,optype,x,i2+s1,j2); - RMatrixGemm(s1,n,s2,-1.0,a,i1+s1,j1,optype,x,i2+s1,j2,0,1.0,x,i2,j2); - RMatrixLeftTrsM(s1,n,a,i1,j1,isUpper,isUnit,optype,x,i2,j2); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates C=alpha*A*A^H+beta*C or | -//| C=alpha*A^H*A+beta*C where: | -//| * C is NxN Hermitian matrix given by its upper/lower triangle | -//| * A is NxK matrix when A*A^H is calculated, KxN matrix otherwise | -//| Additional info: | -//| * cache-oblivious algorithm is used. | -//| * multiplication result replaces C. If Beta=0, C elements are not| -//| used in calculations (not multiplied by zero - just not | -//| referenced) | -//| * if Alpha=0, A is not used (not multiplied by zero - just not | -//| referenced) | -//| * if both Beta and Alpha are zero, C is filled by zeros. | -//| INPUT PARAMETERS | -//| N - matrix size, N>=0 | -//| K - matrix size, K>=0 | -//| Alpha - coefficient | -//| A - matrix | -//| IA - submatrix offset | -//| JA - submatrix offset | -//| OpTypeA - multiplication type: | -//| * 0 - A*A^H is calculated | -//| * 2 - A^H*A is calculated | -//| Beta - coefficient | -//| C - matrix | -//| IC - submatrix offset | -//| JC - submatrix offset | -//| IsUpper - whether C is upper triangular or lower triangular| -//+------------------------------------------------------------------+ -static void CAblas::CMatrixSyrk(const int n,const int k,const double alpha, - CMatrixComplex &a,const int ia,const int ja, - const int optypea,const double beta,CMatrixComplex &c, - const int ic,const int jc,const bool isUpper) - { -//--- create variables - al_complex Alpha(alpha,0); - al_complex Beta(beta,0); - int s1=0; - int s2=0; - int bs=AblasComplexBlockSize(); -//--- check - if(n<=bs && k<=bs) - { - //--- basic algorithm - CMatrixSyrk2(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - //--- exit the function - return; - } -//--- check - if(k>=n) - { - //--- Split K - AblasComplexSplitLength(a,k,s1,s2); - //--- check - if(optypea==0) - { - CMatrixSyrk(n,s1,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixSyrk(n,s2,alpha,a,ia,ja+s1,optypea,1.0,c,ic,jc,isUpper); - } - else - { - CMatrixSyrk(n,s1,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixSyrk(n,s2,alpha,a,ia+s1,ja,optypea,1.0,c,ic,jc,isUpper); - } - } - else - { - //--- Split N - AblasComplexSplitLength(a,n,s1,s2); - //--- check - if(optypea==0 && isUpper) - { - CMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixGemm(s1,s2,k,Alpha,a,ia,ja,0,a,ia+s1,ja,2,Beta,c,ic,jc+s1); - CMatrixSyrk(s2,k,alpha,a,ia+s1,ja,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea==0 && !isUpper) - { - CMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixGemm(s2,s1,k,Alpha,a,ia+s1,ja,0,a,ia,ja,2,Beta,c,ic+s1,jc); - CMatrixSyrk(s2,k,alpha,a,ia+s1,ja,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea!=0 && isUpper) - { - CMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixGemm(s1,s2,k,Alpha,a,ia,ja,2,a,ia,ja+s1,0,Beta,c,ic,jc+s1); - CMatrixSyrk(s2,k,alpha,a,ia,ja+s1,optypea,beta,c,ic+s1,jc+s1,isUpper); - //--- exit the function - return; - } - //--- check - if(optypea!=0 && !isUpper) - { - CMatrixSyrk(s1,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isUpper); - CMatrixGemm(s2,s1,k,Alpha,a,ia,ja+s1,2,a,ia,ja,0,Beta,c,ic+s1,jc); - CMatrixSyrk(s2,k,alpha,a,ia,ja+s1,optypea,beta,c,ic+s1,jc+s1,isUpper); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:| -//| * C is MxN general matrix | -//| * op1(A) is MxK matrix | -//| * op2(B) is KxN matrix | -//| * "op" may be identity transformation, transposition, conjugate | -//| transposition | -//| Additional info: | -//| * cache-oblivious algorithm is used. | -//| * multiplication result replaces C. If Beta=0, C elements are not| -//| used in calculations (not multiplied by zero - just not | -//| referenced) | -//| * if Alpha=0, A is not used (not multiplied by zero - just not | -//| referenced) | -//| * if both Beta and Alpha are zero, C is filled by zeros. | -//| INPUT PARAMETERS | -//| N - matrix size, N>0 | -//| M - matrix size, N>0 | -//| K - matrix size, K>0 | -//| Alpha - coefficient | -//| A - matrix | -//| IA - submatrix offset | -//| JA - submatrix offset | -//| OpTypeA - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| B - matrix | -//| IB - submatrix offset | -//| JB - submatrix offset | -//| OpTypeB - transformation type: | -//| * 0 - no transformation | -//| * 1 - transposition | -//| * 2 - conjugate transposition | -//| Beta - coefficient | -//| C - matrix | -//| IC - submatrix offset | -//| JC - submatrix offset | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixGemm(const int m,const int n,const int k,al_complex &alpha, - CMatrixComplex &a,const int ia,const int ja, - const int optypea,CMatrixComplex &b,const int ib, - const int jb,const int optypeb,al_complex &beta, - CMatrixComplex &c,const int ic,const int jc) - { -//--- create variables - al_complex Beta(1,0); - int s1=0; - int s2=0; - int bs=AblasComplexBlockSize(); -//--- check - if(m<=bs && n<=bs && k<=bs) - { - //--- basic algorithm - CMatrixGemmk(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - //--- exit the function - return; - } -//--- check - if(m>=n && m>=k) - { - //--- A*B = (A1 A2)^T*B - AblasComplexSplitLength(a,m,s1,s2); - CMatrixGemm(s1,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - //--- check - if(optypea==0) - CMatrixGemm(s2,n,k,alpha,a,ia+s1,ja,optypea,b,ib,jb,optypeb,beta,c,ic+s1,jc); - else - CMatrixGemm(s2,n,k,alpha,a,ia,ja+s1,optypea,b,ib,jb,optypeb,beta,c,ic+s1,jc); - //--- exit the function - return; - } -//--- check - if(n>=m && n>=k) - { - //---A*B = A*(B1 B2) - AblasComplexSplitLength(a,n,s1,s2); - //--- check - if(optypeb==0) - { - CMatrixGemm(m,s1,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,s2,k,alpha,a,ia,ja,optypea,b,ib,jb+s1,optypeb,beta,c,ic,jc+s1); - } - else - { - CMatrixGemm(m,s1,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,s2,k,alpha,a,ia,ja,optypea,b,ib+s1,jb,optypeb,beta,c,ic,jc+s1); - } - //--- exit the function - return; - } -//--- check - if(k>=m && k>=n) - { - //--- A*B = (A1 A2)*(B1 B2)^T - AblasComplexSplitLength(a,k,s1,s2); - //--- check - if(optypea==0 && optypeb==0) - { - CMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,n,s2,alpha,a,ia,ja+s1,optypea,b,ib+s1,jb,optypeb,Beta,c,ic,jc); - } - //--- check - if(optypea==0 && optypeb!=0) - { - CMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,n,s2,alpha,a,ia,ja+s1,optypea,b,ib,jb+s1,optypeb,Beta,c,ic,jc); - } - //--- check - if(optypea!=0 && optypeb==0) - { - CMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,n,s2,alpha,a,ia+s1,ja,optypea,b,ib+s1,jb,optypeb,Beta,c,ic,jc); - } - //--- check - if(optypea!=0 && optypeb!=0) - { - CMatrixGemm(m,n,s1,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc); - CMatrixGemm(m,n,s2,alpha,a,ia+s1,ja,optypea,b,ib,jb+s1,optypeb,Beta,c,ic,jc); - } - } -//--- exit the function - return; - } -//+------------------------------------------------------------------+ -//| Level 2 variant of CMatrixRightTRSM | -//+------------------------------------------------------------------+ -static void CAblas::CMatrixRightTrsM2(const int m,const int n,CMatrixComplex &a, - const int i1,const int j1,const bool isUpper, - const bool isUnit,const int optype, - CMatrixComplex &x,const int i2,const int j2) - { -//--- check - if(n*m==0) - return; -//--- create variables - int i=0; - int j=0; - al_complex vc=0; - al_complex vd=0; - int i_=0; - int i1_=0; -//--- General case - if(isUpper) - { - //--- Upper triangular matrix - if(optype==0) - { - //--- X*A^(-1) - for(i=0;i=0;j--) - { - vc=0; - vd=1; - //--- check - if(j=0;j--) - { - vc=0; - vd=1; - //--- check - if(j=0;j--) - { - //--- check - if(isUnit) - vd=1; - else - vd=a[i1+j][j1+j]; - //--- change x - x[i2+i].Set(j2+j,x[i2+i][j2+j]/vd); - //--- check - if(j>0) - { - vc=x[i2+i][j2+j]; - i1_=j1-j2; - for(i_=j2;i_0) - { - i1_=j1-j2; - vc=0.0; - for(i_=j2;i_0) - { - i1_=j1-j2; - vc=0.0; - for(i_=j2;i_=0;i--) - { - for(j=i+1;j<=m-1;j++) - { - vc=a[i1+i][j1+j]; - //--- change x - for(i_=j2;i_=0;i--) - { - //--- check - if(isUnit) - vd=1; - else - vd=Beta/a[i1+i][j1+i]; - //--- change x - for(i_=j2;i_=0;j--) - { - vc=a[i1+i][j1+j]; - for(i_=j2;i_=0;i--) - { - //--- check - if(isUnit) - vd=1; - else - vd=Beta/CMath::Conj(a[i1+i][j1+i]); - //--- change x - for(i_=j2;i_=0;j--) - { - vc=CMath::Conj(a[i1+i][j1+j]); - for(i_=j2;i_=0;j--) - { - vr=0; - vd=1; - //--- check - if(j=0;j--) - { - //--- check - if(isUnit) - vd=1; - else - vd=a[i1+j][j1+j]; - //--- change x - x[i2+i].Set(j2+j,x[i2+i][j2+j]/vd); - //--- check - if(j>0) - { - vr=x[i2+i][j2+j]; - i1_=j1-j2; - //--- change x - for(i_=j2;i_0) - { - i1_=j1-j2; - vr=0.0; - for(i_=j2;i_=0;i--) - { - for(j=i+1;j<=m-1;j++) - { - vr=a[i1+i][j1+j]; - for(i_=j2;i_=0;i--) - { - //--- check - if(isUnit) - vd=1; - else - vd=1/a[i1+i][j1+i]; - //--- change x - for(i_=j2;i_=0;j--) - { - vr=a[i1+i][j1+j]; - for(i_=j2;i_0) - { - v=0.0; - for(i_=ja;i_<=ja+k-1;i_++) - v+=a[ia+i][i_]*CMath::Conj(a[ia+j][i_]); - } - else - v=0; - //--- check - if(beta==0) - c[ic+i].Set(jc+j,Alpha*v); - else - c[ic+i].Set(jc+j,Beta*c[ic+i][jc+j]+Alpha*v); - } - } - //--- exit the function - return; - } - else - { - //--- C = alpha*A^H*A+beta*C - for(i=0;iCAblas::AblasBlockSize()) - blocksize=CAblas::AblasBlockSize(); - //--- change - rowscount=m-blockstart; - //--- QR decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::RMatrixCopy(rowscount,blocksize,a,blockstart,blockstart,tmpa,0,0); - RMatrixQRBaseCase(tmpa,rowscount,blocksize,work,t,taubuf); - CAblas::RMatrixCopy(rowscount,blocksize,tmpa,0,0,a,blockstart,blockstart); - i1_=-blockstart; - for(i_=blockstart;i_<=blockstart+blocksize-1;i_++) - tau[i_]=taubuf[i_+i1_]; - //--- check - if(blockstart+blocksize<=n-1) - { - //--- Update the rest, choose between: - //--- a) Level 2 algorithm (when the rest of the matrix is small enough) - //--- b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - //--- representation for products of Householder transformations', - //--- by R. Schreiber and C. Van Loan. - if(n-blockstart-blocksize>=2*CAblas::AblasBlockSize() || rowscount>=4*CAblas::AblasBlockSize()) - { - //--- Prepare block reflector - RMatrixBlockReflector(tmpa,taubuf,true,rowscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q'. - //--- Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - //--- Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA' - CAblas::RMatrixGemm(blocksize,n-blockstart-blocksize,rowscount,1.0,tmpa,0,0,1,a,blockstart,blockstart+blocksize,0,0.0,tmpr,0,0); - CAblas::RMatrixGemm(blocksize,n-blockstart-blocksize,blocksize,1.0,tmpt,0,0,1,tmpr,0,0,0,0.0,tmpr,blocksize,0); - CAblas::RMatrixGemm(rowscount,n-blockstart-blocksize,blocksize,1.0,tmpa,0,0,0,tmpr,blocksize,0,0,1.0,a,blockstart,blockstart+blocksize); - } - else - { - //--- Level 2 algorithm - for(i=0;iCAblas::AblasBlockSize()) - blocksize=CAblas::AblasBlockSize(); - //--- change - columnscount=n-blockstart; - //--- LQ decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::RMatrixCopy(blocksize,columnscount,a,blockstart,blockstart,tmpa,0,0); - RMatrixLQBaseCase(tmpa,blocksize,columnscount,work,t,taubuf); - CAblas::RMatrixCopy(blocksize,columnscount,tmpa,0,0,a,blockstart,blockstart); - i1_=-blockstart; - for(i_=blockstart;i_<=blockstart+blocksize-1;i_++) - { - tau[i_]=taubuf[i_+i1_]; - } - //--- Update the rest, choose between: - //--- a) Level 2 algorithm (when the rest of the matrix is small enough) - //--- b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - //--- representation for products of Householder transformations', - //--- by R. Schreiber and C. Van Loan. - if(blockstart+blocksize<=m-1) - { - //--- check - if(m-blockstart-blocksize>=2*CAblas::AblasBlockSize()) - { - //--- prepare - RMatrixBlockReflector(tmpa,taubuf,false,columnscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q. - //--- Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA - CAblas::RMatrixGemm(m-blockstart-blocksize,blocksize,columnscount,1.0,a,blockstart+blocksize,blockstart,0,tmpa,0,0,1,0.0,tmpr,0,0); - CAblas::RMatrixGemm(m-blockstart-blocksize,blocksize,blocksize,1.0,tmpr,0,0,0,tmpt,0,0,0,0.0,tmpr,0,blocksize); - CAblas::RMatrixGemm(m-blockstart-blocksize,columnscount,blocksize,1.0,tmpr,0,blocksize,0,tmpa,0,0,0,1.0,a,blockstart+blocksize,blockstart); - } - else - { - //--- Level 2 algorithm - for(i=0;iCAblas::AblasComplexBlockSize()) - blocksize=CAblas::AblasComplexBlockSize(); - rowscount=m-blockstart; - //--- QR decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::CMatrixCopy(rowscount,blocksize,a,blockstart,blockstart,tmpa,0,0); - CMatrixQRBaseCase(tmpa,rowscount,blocksize,work,t,taubuf); - CAblas::CMatrixCopy(rowscount,blocksize,tmpa,0,0,a,blockstart,blockstart); - i1_=-blockstart; - for(i_=blockstart;i_<=blockstart+blocksize-1;i_++) - tau[i_]=taubuf[i_+i1_]; - //--- Update the rest, choose between: - //--- a) Level 2 algorithm (when the rest of the matrix is small enough) - //--- b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - //--- representation for products of Householder transformations', - //--- by R. Schreiber and C. Van Loan. - if(blockstart+blocksize<=n-1) - { - //--- check - if(n-blockstart-blocksize>=2*CAblas::AblasComplexBlockSize()) - { - //--- Prepare block reflector - CMatrixBlockReflector(tmpa,taubuf,true,rowscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q'. - //--- Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - //--- Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA' - CAblas::CMatrixGemm(blocksize,n-blockstart-blocksize,rowscount,Alpha,tmpa,0,0,2,a,blockstart,blockstart+blocksize,0,Beta,tmpr,0,0); - CAblas::CMatrixGemm(blocksize,n-blockstart-blocksize,blocksize,Alpha,tmpt,0,0,2,tmpr,0,0,0,Beta,tmpr,blocksize,0); - CAblas::CMatrixGemm(rowscount,n-blockstart-blocksize,blocksize,Alpha,tmpa,0,0,0,tmpr,blocksize,0,0,Alpha,a,blockstart,blockstart+blocksize); - } - else - { - //--- Level 2 algorithm - for(i=0;iCAblas::AblasComplexBlockSize()) - blocksize=CAblas::AblasComplexBlockSize(); - columnscount=n-blockstart; - //--- LQ decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::CMatrixCopy(blocksize,columnscount,a,blockstart,blockstart,tmpa,0,0); - CMatrixLQBaseCase(tmpa,blocksize,columnscount,work,t,taubuf); - CAblas::CMatrixCopy(blocksize,columnscount,tmpa,0,0,a,blockstart,blockstart); - i1_=-blockstart; - for(i_=blockstart;i_<=blockstart+blocksize-1;i_++) - tau[i_]=taubuf[i_+i1_]; - //--- Update the rest, choose between: - //--- a) Level 2 algorithm (when the rest of the matrix is small enough) - //--- b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - //--- representation for products of Householder transformations', - //--- by R. Schreiber and C. Van Loan. - if(blockstart+blocksize<=m-1) - { - //--- check - if(m-blockstart-blocksize>=2*CAblas::AblasComplexBlockSize()) - { - //--- Prepare block reflector - CMatrixBlockReflector(tmpa,taubuf,false,columnscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q. - //--- Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA - CAblas::CMatrixGemm(m-blockstart-blocksize,blocksize,columnscount,Alpha,a,blockstart+blocksize,blockstart,0,tmpa,0,0,2,Beta,tmpr,0,0); - CAblas::CMatrixGemm(m-blockstart-blocksize,blocksize,blocksize,Alpha,tmpr,0,0,0,tmpt,0,0,0,Beta,tmpr,0,blocksize); - CAblas::CMatrixGemm(m-blockstart-blocksize,columnscount,blocksize,Alpha,tmpr,0,blocksize,0,tmpa,0,0,0,Alpha,a,blockstart+blocksize,blockstart); - } - else - { - //--- Level 2 algorithm - for(i=0;i=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of the RMatrixQR subroutine. | -//| QColumns - required number of columns of matrix Q. | -//| M>=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array whose indexes range within | -//| [0..M-1, 0..QColumns-1]. | -//| If QColumns=0, the array remains unchanged. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixQRUnpackQ(CMatrixDouble &a,const int m,const int n, - double &tau[],const int qcolumns,CMatrixDouble &q) - { -//--- check - if(!CAp::Assert(qcolumns<=m,__FUNCTION__+": QColumns>M!")) - return; -//--- check - if(m<=0 || n<=0 || qcolumns<=0) - return; -//--- create arrays - double work[]; - double t[]; - double taubuf[]; -//--- create matrix - CMatrixDouble tmpa; - CMatrixDouble tmpt; - CMatrixDouble tmpr; -//--- create variables - int minmn=MathMin(m,n); - int refcnt=MathMin(minmn,qcolumns); - int blockstart=CAblas::AblasBlockSize()*(refcnt/CAblas::AblasBlockSize()); - int blocksize=refcnt-blockstart; - int rowscount=0; - int i=0; - int j=0; - int i_=0; - int i1_=0; -//--- allocation - q.Resize(m,qcolumns); -//--- identity matrix - for(i=0;i=0) - { - rowscount=m-blockstart; - //--- Copy current block - CAblas::RMatrixCopy(rowscount,blocksize,a,blockstart,blockstart,tmpa,0,0); - i1_=blockstart; - for(i_=0;i_=2*CAblas::AblasBlockSize()) - { - //--- Prepare block reflector - RMatrixBlockReflector(tmpa,taubuf,true,rowscount,blocksize,tmpt,work); - //--- Multiply matrix by Q. - //--- Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - CAblas::RMatrixGemm(blocksize,qcolumns,rowscount,1.0,tmpa,0,0,1,q,blockstart,0,0,0.0,tmpr,0,0); - CAblas::RMatrixGemm(blocksize,qcolumns,blocksize,1.0,tmpt,0,0,0,tmpr,0,0,0,0.0,tmpr,blocksize,0); - CAblas::RMatrixGemm(rowscount,qcolumns,blocksize,1.0,tmpa,0,0,0,tmpr,blocksize,0,0,1.0,q,blockstart,0); - } - else - { - //--- Level 2 algorithm - for(i=blocksize-1;i>=0;i--) - { - i1_=i-1; - for(i_=1;i_<=rowscount-i;i_++) - { - t[i_]=tmpa[i_+i1_][i]; - } - t[1]=1; - //--- function call - CReflections::ApplyReflectionFromTheLeft(q,taubuf[i],t,blockstart+i,m-1,0,qcolumns-1,work); - } - } - //--- change value - blockstart=blockstart-CAblas::AblasBlockSize(); - blocksize=CAblas::AblasBlockSize(); - } - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix R from the QR decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of RMatrixQR subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| R - matrix R, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixQRUnpackR(CMatrixDouble &a,const int m,const int n,CMatrixDouble &r) - { -//--- check - if(m<=0 || n<=0) - return; -//--- create variables - int i=0; - int k=MathMin(m,n); - int i_=0; -//--- allocation - r.Resize(m,n); -//--- Prepare matrix - for(i=0;i=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of the RMatrixLQ subroutine. | -//| QRows - required number of rows in matrix Q. N>=QRows>=0.| -//| Output parameters: | -//| Q - first QRows rows of matrix Q. Array whose indexes| -//| range within [0..QRows-1, 0..N-1]. If QRows=0, | -//| the array remains unchanged. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixLQUnpackQ(CMatrixDouble &a,const int m,const int n, - double &tau[],const int qrows,CMatrixDouble &q) - { -//--- check - if(!CAp::Assert(qrows<=n,__FUNCTION__+": QRows>N!")) - return; -//--- check - if(m<=0 || n<=0 || qrows<=0) - return; -//--- create arrays - double work[]; - double t[]; - double taubuf[]; -//--- create matrix - CMatrixDouble tmpa; - CMatrixDouble tmpt; - CMatrixDouble tmpr; -//--- create variables - int minmn=MathMin(m,n); - int refcnt=MathMin(minmn,qrows); - int blockstart=CAblas::AblasBlockSize()*(refcnt/CAblas::AblasBlockSize()); - int blocksize=refcnt-blockstart; - int columnscount=0; - int i=0; - int j=0; - int i_=0; - int i1_=0; -//--- allocation - ArrayResizeAL(work,MathMax(m,n)+1); - ArrayResizeAL(t,MathMax(m,n)+1); - ArrayResizeAL(taubuf,minmn); -//--- allocation - tmpa.Resize(CAblas::AblasBlockSize(),n); - tmpt.Resize(CAblas::AblasBlockSize(),2*CAblas::AblasBlockSize()); - tmpr.Resize(qrows,2*CAblas::AblasBlockSize()); - q.Resize(qrows,n); -//--- identity matrix - for(i=0;i<=qrows-1;i++) - { - for(j=0;j=0) - { - columnscount=n-blockstart; - //--- Copy submatrix - CAblas::RMatrixCopy(blocksize,columnscount,a,blockstart,blockstart,tmpa,0,0); - i1_=blockstart; - for(i_=0;i_=2*CAblas::AblasBlockSize()) - { - //--- Prepare block reflector - RMatrixBlockReflector(tmpa,taubuf,false,columnscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q'. - //--- Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA - CAblas::RMatrixGemm(qrows,blocksize,columnscount,1.0,q,0,blockstart,0,tmpa,0,0,1,0.0,tmpr,0,0); - CAblas::RMatrixGemm(qrows,blocksize,blocksize,1.0,tmpr,0,0,0,tmpt,0,0,1,0.0,tmpr,0,blocksize); - CAblas::RMatrixGemm(qrows,columnscount,blocksize,1.0,tmpr,0,blocksize,0,tmpa,0,0,0,1.0,q,0,blockstart); - } - else - { - //--- Level 2 algorithm - for(i=blocksize-1;i>=0;i--) - { - i1_=i-1; - for(i_=1;i_<=columnscount-i;i_++) - t[i_]=tmpa[i][i_+i1_]; - t[1]=1; - //--- function call - CReflections::ApplyReflectionFromTheRight(q,taubuf[i],t,0,qrows-1,blockstart+i,n-1,work); - } - } - //--- change value - blockstart=blockstart-CAblas::AblasBlockSize(); - blocksize=CAblas::AblasBlockSize(); - } - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix L from the LQ decomposition of a matrix A | -//| Input parameters: | -//| A -matrices Q and L in compact form. | -//| Output of RMatrixLQ subroutine. | -//| M -number of rows in given matrix A. M>=0. | -//| N -number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| L -matrix L, array[0..M-1,0..N-1]. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixLQUnpackL(CMatrixDouble &a,const int m,const int n,CMatrixDouble &l) - { -//--- check - if(m<=0 || n<=0) - return; -//--- create variables - int i=0; - int k=0; - int i_=0; -//--- allocation - l.Resize(m,n); -//--- Prepare matrix - for(i=0;i=0. | -//| N - number of columns in matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of CMatrixQR subroutine . | -//| QColumns - required number of columns in matrix Q. | -//| M>=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array whose index ranges within [0..M-1, | -//| 0..QColumns-1]. | -//| If QColumns=0, array isn't changed. | -//+------------------------------------------------------------------+ -static void COrtFac::CMatrixQRUnpackQ(CMatrixComplex &a,const int m,const int n, - al_complex &tau[],const int qcolumns,CMatrixComplex &q) - { -//--- check - if(!CAp::Assert(qcolumns<=m,__FUNCTION__+": QColumns>M!")) - return; -//--- check - if(m<=0 || n<=0) - return; -//--- create arrays - al_complex work[]; - al_complex t[]; - al_complex taubuf[]; -//--- create matrix - CMatrixComplex tmpa; - CMatrixComplex tmpt; - CMatrixComplex tmpr; -//--- create variables - int minmn=MathMin(m,n); - int refcnt=MathMin(minmn,qcolumns); - int blockstart=CAblas::AblasComplexBlockSize()*(refcnt/CAblas::AblasComplexBlockSize()); - int blocksize=refcnt-blockstart; - int rowscount=0; - int i=0; - int j=0; - int i_=0; - int i1_=0; - al_complex One(1,0); - al_complex Zero(0,0); -//--- allocation - ArrayResizeAL(work,MathMax(m,n)+1); - ArrayResizeAL(t,MathMax(m,n)+1); - ArrayResizeAL(taubuf,minmn); -//--- allocation - tmpa.Resize(m,CAblas::AblasComplexBlockSize()); - tmpt.Resize(CAblas::AblasComplexBlockSize(),CAblas::AblasComplexBlockSize()); - tmpr.Resize(2*CAblas::AblasComplexBlockSize(),qcolumns); - q.Resize(m,qcolumns); - for(i=0;i=0) - { - rowscount=m-blockstart; - //--- QR decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::CMatrixCopy(rowscount,blocksize,a,blockstart,blockstart,tmpa,0,0); - i1_=blockstart; - for(i_=0;i_=2*CAblas::AblasComplexBlockSize()) - { - //--- Prepare block reflector - CMatrixBlockReflector(tmpa,taubuf,true,rowscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q. - //--- Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - CAblas::CMatrixGemm(blocksize,qcolumns,rowscount,One,tmpa,0,0,2,q,blockstart,0,0,Zero,tmpr,0,0); - CAblas::CMatrixGemm(blocksize,qcolumns,blocksize,One,tmpt,0,0,0,tmpr,0,0,0,Zero,tmpr,blocksize,0); - CAblas::CMatrixGemm(rowscount,qcolumns,blocksize,One,tmpa,0,0,0,tmpr,blocksize,0,0,One,q,blockstart,0); - } - else - { - //--- Level 2 algorithm - for(i=blocksize-1;i>=0;i--) - { - i1_=i-1; - for(i_=1;i_<=rowscount-i;i_++) - t[i_]=tmpa[i_+i1_][i]; - t[1]=1; - //--- function call - CComplexReflections::ComplexApplyReflectionFromTheLeft(q,taubuf[i],t,blockstart+i,m-1,0,qcolumns-1,work); - } - } - //--- change value - blockstart=blockstart-CAblas::AblasComplexBlockSize(); - blocksize=CAblas::AblasComplexBlockSize(); - } - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix R from the QR decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and R in compact form. | -//| Output of CMatrixQR subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| R - matrix R, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void COrtFac::CMatrixQRUnpackR(CMatrixComplex &a,const int m,const int n,CMatrixComplex &r) - { -//--- check - if(m<=0 || n<=0) - return; -//--- create variables - al_complex Zero(0,0); - int i=0; - int k=MathMin(m,n); - int i_=0; -//--- allocation - r.Resize(m,n); -//--- Prepare matrix - for(i=0;i=0. | -//| N - number of columns in matrix A. N>=0. | -//| Tau - scalar factors which are used to form Q. | -//| Output of CMatrixLQ subroutine . | -//| QRows - required number of rows in matrix Q. | -//| N>=QColumns>=0. | -//| Output parameters: | -//| Q - first QRows rows of matrix Q. | -//| Array whose index ranges within [0..QRows-1, | -//| 0..N-1]. | -//| If QRows=0, array isn't changed. | -//+------------------------------------------------------------------+ -static void COrtFac::CMatrixLQUnpackQ(CMatrixComplex &a,const int m,const int n, - al_complex &tau[],const int qrows,CMatrixComplex &q) - { -//--- check - if(m<=0 || n<=0) - return; -//--- create arrays - al_complex work[]; - al_complex t[]; - al_complex taubuf[]; -//--- create matrix - CMatrixComplex tmpa; - CMatrixComplex tmpt; - CMatrixComplex tmpr; -//--- create variables - int minmn=MathMin(m,n); - int refcnt=MathMin(minmn,qrows); - int blockstart=CAblas::AblasComplexBlockSize()*(refcnt/CAblas::AblasComplexBlockSize()); - int blocksize=refcnt-blockstart; - int columnscount=0; - int i=0; - int j=0; - int i_=0; - int i1_=0; - al_complex One(1,0); - al_complex Zero(0,0); -//--- allocation - ArrayResizeAL(work,MathMax(m,n)+1); - ArrayResizeAL(t,MathMax(m,n)+1); - ArrayResizeAL(taubuf,minmn); -//--- allocation - tmpa.Resize(CAblas::AblasComplexBlockSize(),n); - tmpt.Resize(CAblas::AblasComplexBlockSize(),CAblas::AblasComplexBlockSize()); - tmpr.Resize(qrows,2*CAblas::AblasComplexBlockSize()); - q.Resize(qrows,n); - for(i=0;i<=qrows-1;i++) - { - for(j=0;j=0) - { - columnscount=n-blockstart; - //--- LQ decomposition of submatrix. - //--- Matrix is copied to temporary storage to solve - //--- some TLB issues arising from non-contiguous memory - //--- access pattern. - CAblas::CMatrixCopy(blocksize,columnscount,a,blockstart,blockstart,tmpa,0,0); - i1_=blockstart; - for(i_=0;i_=2*CAblas::AblasComplexBlockSize()) - { - //--- Prepare block reflector - CMatrixBlockReflector(tmpa,taubuf,false,columnscount,blocksize,tmpt,work); - //--- Multiply the rest of A by Q'. - //--- Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA - CAblas::CMatrixGemm(qrows,blocksize,columnscount,One,q,0,blockstart,0,tmpa,0,0,2,Zero,tmpr,0,0); - CAblas::CMatrixGemm(qrows,blocksize,blocksize,One,tmpr,0,0,0,tmpt,0,0,2,Zero,tmpr,0,blocksize); - CAblas::CMatrixGemm(qrows,columnscount,blocksize,One,tmpr,0,blocksize,0,tmpa,0,0,0,One,q,0,blockstart); - } - else - { - //--- Level 2 algorithm - for(i=blocksize-1;i>=0;i--) - { - i1_=i-1; - for(i_=1;i_<=columnscount-i;i_++) - t[i_]=CMath::Conj(tmpa[i][i_+i1_]); - t[1]=1; - //--- function call - CComplexReflections::ComplexApplyReflectionFromTheRight(q,CMath::Conj(taubuf[i]),t,0,qrows-1,blockstart+i,n-1,work); - } - } - //--- change value - blockstart=blockstart-CAblas::AblasComplexBlockSize(); - blocksize=CAblas::AblasComplexBlockSize(); - } - } -//+------------------------------------------------------------------+ -//| Unpacking of matrix L from the LQ decomposition of a matrix A | -//| Input parameters: | -//| A - matrices Q and L in compact form. | -//| Output of CMatrixLQ subroutine. | -//| M - number of rows in given matrix A. M>=0. | -//| N - number of columns in given matrix A. N>=0. | -//| Output parameters: | -//| L - matrix L, array[0..M-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static void COrtFac::CMatrixLQUnpackL(CMatrixComplex &a,const int m,const int n,CMatrixComplex &l) - { -//--- check - if(m<=0 || n<=0) - return; -//--- create variables - al_complex Zero(0,0); - int i=0; - int k=0; - int i_=0; -//--- allocation - l.Resize(m,n); -//--- Prepare matrix - for(i=0;i=N, B is the upper bidiagonal MxN matrix and is stored in | -//| the corresponding elements of matrix A. Matrix Q is represented | -//| as a product of elementary reflections Q = H(0)*H(1)*...*H(n-1), | -//| where H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in | -//| TauQ[i], and vector v has the following structure: v(0:i-1)=0, | -//| v(i)=1, v(i+1:m-1) is stored in elements A(i+1:m-1,i).Matrix P is| -//| as follows: P = G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. | -//| Tau is stored in TauP[i], u(0:i)=0, u(i+1)=1, u(i+2:n-1) is | -//| stored in elements A(i,i+2:n-1). | -//| If M n): m=5, n=6 (m < n): | -//| ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) | -//| ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) | -//| ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) | -//| ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) | -//| ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) | -//| ( v1 v2 v3 v4 v5 ) | -//| Here vi and ui are vectors which form H(i) and G(i), and d and | -//| e - are the diagonal and off-diagonal elements of matrix B. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixBD(CMatrixDouble &a,const int m,const int n,double &tauq[],double &taup[]) - { -//--- check - if(n<=0 || m<=0) - return; -//--- create arrays - double work[]; - double t[]; -//--- create variables - int minmn=0; - int maxmn=MathMax(m,n); - int i=0; - double ltau=0; - int i_=0; - int i1_=0; -//--- allocation - ArrayResizeAL(work,maxmn+1); - ArrayResizeAL(t,maxmn+1); -//--- check - if(m>=n) - { - ArrayResizeAL(tauq,n); - ArrayResizeAL(taup,n); - } - else - { - ArrayResizeAL(tauq,m); - ArrayResizeAL(taup,m); - } -//--- check - if(m>=n) - { - //--- Reduce to upper bidiagonal form - for(i=0;i=QColumns>=0. | -//| Output parameters: | -//| Q - first QColumns columns of matrix Q. | -//| Array[0..M-1, 0..QColumns-1] | -//| If QColumns=0, the array is not modified. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixBDUnpackQ(CMatrixDouble &qp,const int m,const int n, - double &tauq[],const int qcolumns,CMatrixDouble &q) - { -//--- check - if(!CAp::Assert(qcolumns<=m,__FUNCTION__+": QColumns>M!")) - return; -//--- check - if(!CAp::Assert(qcolumns>=0,__FUNCTION__+": QColumns<0!")) - return; -//--- check - if(m==0 || n==0 || qcolumns==0) - return; -//--- create variables - int i=0; - int j=0; -//--- allocation - q.Resize(m,qcolumns); -//--- identity matrix - for(i=0;i=n) - { - //--- setup - if(fromtheright) - { - i1=0; - i2=n-1; - istep=1; - } - else - { - i1=n-1; - i2=0; - istep=-1; - } - //--- check - if(dotranspose) - { - i=i1; - i1=i2; - i2=i; - istep=-istep; - } - //--- Process - i=i1; - do - { - i1_=i-1; - for(i_=1;i_<=m-i;i_++) - v[i_]=qp[i_+i1_][i]; - v[1]=1; - //--- check - if(fromtheright) - CReflections::ApplyReflectionFromTheRight(z,tauq[i],v,0,zrows-1,i,m-1,work); - else - CReflections::ApplyReflectionFromTheLeft(z,tauq[i],v,i,m-1,0,zcolumns-1,work); - i=i+istep; - } - while(i!=i2+istep); - } - else - { - //--- setup - if(fromtheright) - { - i1=0; - i2=m-2; - istep=1; - } - else - { - i1=m-2; - i2=0; - istep=-1; - } - //--- check - if(dotranspose) - { - i=i1; - i1=i2; - i2=i; - istep=-istep; - } - //--- Process - if(m-1>0) - { - i=i1; - do - { - i1_=i; - for(i_=1;i_<=m-i-1;i_++) - v[i_]=qp[i_+i1_][i]; - v[1]=1; - //--- check - if(fromtheright) - CReflections::ApplyReflectionFromTheRight(z,tauq[i],v,0,zrows-1,i+1,m-1,work); - else - CReflections::ApplyReflectionFromTheLeft(z,tauq[i],v,i+1,m-1,0,zcolumns-1,work); - i=i+istep; - } - while(i!=i2+istep); - } - } - } -//+------------------------------------------------------------------+ -//| Unpacking matrix P which reduces matrix A to bidiagonal form. | -//| The subroutine returns transposed matrix P. | -//| Input parameters: | -//| QP - matrices Q and P in compact form. | -//| Output of ToBidiagonal subroutine. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| TAUP - scalar factors which are used to form P. | -//| Output of ToBidiagonal subroutine. | -//| PTRows - required number of rows of matrix P^T. | -//| N >= PTRows >= 0. | -//| Output parameters: | -//| PT - first PTRows columns of matrix P^T | -//| Array[0..PTRows-1, 0..N-1] | -//| If PTRows=0, the array is not modified. | -//+------------------------------------------------------------------+ -static void COrtFac::RMatrixBDUnpackPT(CMatrixDouble &qp,const int m,const int n, - double &taup[],const int ptrows,CMatrixDouble &pt) - { -//--- check - if(!CAp::Assert(ptrows<=n,__FUNCTION__+": PTRows>N!")) - return; -//--- check - if(!CAp::Assert(ptrows>=0,__FUNCTION__+": PTRows<0!")) - return; -//--- check - if(m==0 || n==0 || ptrows==0) - return; -//--- create variables - int i=0; - int j=0; -//--- allocation - pt.Resize(ptrows,n); -//--- prepare - for(i=0;i<=ptrows-1;i++) - { - for(j=0;j=n) - { - //--- setup - if(fromtheright) - { - i1=n-2; - i2=0; - istep=-1; - } - else - { - i1=0; - i2=n-2; - istep=1; - } - //--- check - if(!dotranspose) - { - i=i1; - i1=i2; - i2=i; - istep=-istep; - } - //--- Process - if(n-1>0) - { - i=i1; - do - { - i1_=i; - for(i_=1;i_=n) - isupper=true; - else - isupper=false; -//--- check - if(isupper) - { - //--- allocation - ArrayResizeAL(d,n); - ArrayResizeAL(e,n); - //--- get result - for(i=0;i=0,__FUNCTION__+": incorrect N!")) - return; -//--- create arrays - double t[]; - double work[]; -//--- create variables - int i=0; - double v=0; - int i_=0; - int i1_=0; -//--- allocation - ArrayResizeAL(tau,n-1); - ArrayResizeAL(t,n+1); - ArrayResizeAL(work,n); - for(i=0;i1) - ArrayResizeAL(tau,n-1); - ArrayResizeAL(d,n); -//--- check - if(n>1) - ArrayResizeAL(e,n-1); -//--- check - if(isupper) - { - //--- Reduce the upper triangle of A - for(i=n-2;i>=0;i--) - { - //--- Generate elementary reflector H() = E - tau * v * v' - if(i>=1) - { - i1_=-2; - for(i_=2;i_<=i+1;i_++) - t[i_]=a[i_+i1_][i+1]; - } - t[1]=a[i][i+1]; - CReflections::GenerateReflection(t,i+1,taui); - //--- check - if(i>=1) - { - i1_=2; - for(i_=0;i_=0;i--) - { - //--- Apply H(i) - i1_=i; - for(i_=1;i_1) - { - ArrayResizeAL(tau,n-1); - ArrayResizeAL(e,n-1); - } - ArrayResizeAL(d,n); - ArrayResizeAL(t,n); - ArrayResizeAL(t2,n); - ArrayResizeAL(t3,n); -//--- check - if(isupper) - { - //--- Reduce the upper triangle of A - a[n-1].Set(n-1,a[n-1][n-1].re); - for(i=n-2;i>=0;i--) - { - //--- Generate elementary reflector H = I+1 - tau * v * v' - alpha=a[i][i+1]; - t[1]=alpha; - //--- check - if(i>=1) - { - i1_=-2; - for(i_=2;i_<=i+1;i_++) - t[i_]=a[i_+i1_][i+1]; - } - //--- function call - CComplexReflections::ComplexGenerateReflection(t,i+1,taui); - //--- check - if(i>=1) - { - i1_=2; - for(i_=0;i_=0;i--) - { - //--- Apply H(i) - i1_=i; - for(i_=1;i_=0). | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if successful. M contains the number of eigenvalues in | -//| the given half-interval (could be equal to 0), W contains the| -//| eigenvalues, Z contains the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues | -//| and eigenvectors are not returned, M is equal to 0. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::SMatrixEVDR(CMatrixDouble &ca,const int n,const int zneeded, - const bool isupper,const double b1,const double b2, - int &m,double &w[],CMatrixDouble &z) - { -//--- create arrays - double tau[]; - double e[]; -//--- create copy - CMatrixDouble a; - a=ca; -//--- initialization - m=0; -//--- check - if(!CAp::Assert(zneeded==0 || zneeded==1,__FUNCTION__+": incorrect ZNeeded")) - return(false); -//--- function call - COrtFac::SMatrixTD(a,n,isupper,tau,w,e); -//--- check - if(zneeded==1) - { - //--- function call - COrtFac::SMatrixTDUnpackQ(a,n,isupper,tau,z); - } -//--- return result - return(SMatrixTdEVDR(w,e,n,zneeded,b1,b2,m,z)); - } -//+------------------------------------------------------------------+ -//| Subroutine for finding the eigenvalues and eigenvectors of a | -//| symmetric matrix with given indexes by using bisection and | -//| inverse iteration methods. | -//| Input parameters: | -//| A - symmetric matrix which is given by its upper or | -//| lower triangular part. Array whose indexes range | -//| within [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. | -//| If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| IsUpperA - storage format of matrix A. | -//| I1, I2 - index interval for searching (from I1 to I2). | -//| 0 <= I1 <= I2 <= N-1. | -//| Output parameters: | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..I2-I1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..I2-I1]. | -//| In that case, the eigenvectors are stored in the | -//| matrix columns. | -//| Result: | -//| True, if successful. W contains the eigenvalues, Z contains | -//| the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues | -//| and eigenvectors are not returned. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::SMatrixEVDI(CMatrixDouble &ca,const int n,const int zneeded, - const bool isupper,const int i1,const int i2, - double &w[],CMatrixDouble &z) - { -//--- create arrays - double tau[]; - double e[]; -//--- create copy - CMatrixDouble a; - a=ca; -//--- check - if(!CAp::Assert(zneeded==0 || zneeded==1,__FUNCTION__+": incorrect ZNeeded")) - return(false); -//--- function call - COrtFac::SMatrixTD(a,n,isupper,tau,w,e); -//--- check - if(zneeded==1) - { - //--- function call - COrtFac::SMatrixTDUnpackQ(a,n,isupper,tau,z); - } -//--- return result - return(SMatrixTdEVDI(w,e,n,zneeded,i1,i2,z)); - } -//+------------------------------------------------------------------+ -//| Finding the eigenvalues and eigenvectors of a Hermitian matrix | -//| The algorithm finds eigen pairs of a Hermitian matrix by reducing| -//| it to real tridiagonal form and using the QL/QR algorithm. | -//| Input parameters: | -//| A - Hermitian matrix which is given by its upper or | -//| lower triangular part. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - storage format. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not returned; | -//| * 1, the eigenvectors are returned. | -//| Output parameters: | -//| D - eigenvalues in ascending order. | -//| Array whose index ranges within [0..N-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains the eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged (rare case). | -//| Note: | -//| eigenvectors of Hermitian matrix are defined up to | -//| multiplication by a complex number L, such that |L|=1. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::HMatrixEVD(CMatrixComplex &ca,const int n,int zneeded, - const bool isupper,double &d[],CMatrixComplex &z) - { -//--- create variables - int i=0; - int k=0; - double v=0; - int i_=0; - bool result; -//--- create arrays - al_complex tau[]; - double e[]; - double work[]; -//--- create matrix - CMatrixDouble t; - CMatrixComplex q; -//--- create copy - CMatrixComplex a; - a=ca; -//--- check - if(!CAp::Assert(zneeded==0 || zneeded==1,__FUNCTION__+": incorrect ZNeeded")) - return(false); -//--- Reduce to tridiagonal form - COrtFac::HMatrixTD(a,n,isupper,tau,d,e); -//--- check - if(zneeded==1) - { - //--- function call - COrtFac::HMatrixTDUnpackQ(a,n,isupper,tau,q); - zneeded=2; - } -//--- get result - result=SMatrixTdEVD(d,e,n,zneeded,t); -//--- Eigenvectors are needed -//--- Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T - if(result && zneeded!=0) - { - ArrayResizeAL(work,n); - z.Resize(n,n); - for(i=0;i=0 | -//| W - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z hasn?t changed; | -//| * 1, Z contains eigenvectors. | -//| Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| The eigenvectors are stored in the matrix | -//| columns. | -//| Result: | -//| True, if successful. M contains the number of eigenvalues | -//| in the given half-interval (could be equal to 0), W contains | -//| the eigenvalues, Z contains the eigenvectors (if needed). | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned, M is equal to 0. | -//| Note: | -//| eigen vectors of Hermitian matrix are defined up to | -//| multiplication by a complex number L, such as |L|=1. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::HMatrixEVDR(CMatrixComplex &ca,const int n,int zneeded, - bool isupper,const double b1,const double b2, - int &m,double &w[],CMatrixComplex &z) - { -//--- create variables - int i=0; - int k=0; - double v=0; - int i_=0; - bool result; -//--- create arrays - al_complex tau[]; - double e[]; - double work[]; -//--- create matrix - CMatrixComplex q; - CMatrixDouble t; -//--- create copy - CMatrixComplex a; - a=ca; -//--- initialization - m=0; -//--- check - if(!CAp::Assert(zneeded==0 || zneeded==1,__FUNCTION__+": incorrect ZNeeded")) - return(false); -//--- Reduce to tridiagonal form - COrtFac::HMatrixTD(a,n,isupper,tau,w,e); -//--- check - if(zneeded==1) - { - //--- function call - COrtFac::HMatrixTDUnpackQ(a,n,isupper,tau,q); - zneeded=2; - } -//--- Bisection and inverse iteration - result=SMatrixTdEVDR(w,e,n,zneeded,b1,b2,m,t); -//--- Eigenvectors are needed -//--- Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T - if((result && zneeded!=0) && m!=0) - { - ArrayResizeAL(work,m); - z.Resize(n,m); - for(i=0;i1) - { - i1_=-1; - for(i_=1;i_=0. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not needed; | -//| * 1, the eigenvectors of a tridiagonal matrix | -//| are multiplied by the square matrix Z. It is | -//| used if the tridiagonal matrix is obtained by | -//| the similarity transformation of a symmetric | -//| matrix. | -//| * 2, the eigenvectors of a tridiagonal matrix | -//| replace matrix Z. | -//| A, B - half-interval (A, B] to search eigenvalues in. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z isn't used and remains unchanged; | -//| * 1, Z contains the square matrix (array whose | -//| indexes range within [0..N-1, 0..N-1]) which | -//| reduces the given symmetric matrix to | -//| tridiagonal form; | -//| * 2, Z isn't used (but changed on the exit). | -//| Output parameters: | -//| D - array of the eigenvalues found. | -//| Array whose index ranges within [0..M-1]. | -//| M - number of eigenvalues found in the given | -//| half-interval (M>=0). | -//| Z - if ZNeeded is equal to: | -//| * 0, doesn't contain any information; | -//| * 1, contains the product of a given NxN matrix | -//| Z (from the left) and NxM matrix of the | -//| eigenvectors found (from the right). Array | -//| whose indexes range within [0..N-1, 0..M-1]. | -//| * 2, contains the matrix of the eigenvectors | -//| found. Array whose indexes range within | -//| [0..N-1, 0..M-1]. | -//| Result: | -//| True, if successful. In that case, M contains the number of | -//| eigenvalues in the given half-interval (could be equal to 0),| -//| D contains the eigenvalues, Z contains the eigenvectors (if | -//| needed). It should be noted that the subroutine changes the | -//| size of arrays D and Z. | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned, M is equal to 0. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::SMatrixTdEVDR(double &d[],double &e[],const int n, - const int zneeded,const double a, - const double b,int &m,CMatrixDouble &z) - { -//--- create variables - bool result; - int errorcode=0; - int nsplit=0; - int i=0; - int j=0; - int k=0; - int cr=0; - double v=0; - int i_=0; - int i1_=0; -//--- create arrays - int iblock[]; - int isplit[]; - int ifail[]; - double d1[]; - double e1[]; - double w[]; -//--- create matrix - CMatrixDouble z2; - CMatrixDouble z3; -//--- initialization - m=0; -//--- check - if(!CAp::Assert(zneeded>=0 && zneeded<=2,__FUNCTION__+": incorrect ZNeeded!")) - return(false); -//--- check - if(b<=a) - { - m=0; - //--- return result - return(true); - } -//--- check - if(n<=0) - { - m=0; - //--- return result - return(true); - } -//--- Copy D,E to D1, E1 - ArrayResizeAL(d1,n+1); - i1_=-1; - for(i_=1;i_<=n;i_++) - d1[i_]=d[i_+i1_]; -//--- check - if(n>1) - { - ArrayResizeAL(e1,n); - i1_=-1; - for(i_=1;i_=0. | -//| ZNeeded - flag controlling whether the eigenvectors are | -//| needed or not. If ZNeeded is equal to: | -//| * 0, the eigenvectors are not needed; | -//| * 1, the eigenvectors of a tridiagonal matrix | -//| are multiplied by the square matrix Z. It is | -//| used if the tridiagonal matrix is obtained by | -//| the similarity transformation of a symmetric | -//| matrix. | -//| * 2, the eigenvectors of a tridiagonal matrix | -//| replace matrix Z. | -//| I1, I2 - index interval for searching (from I1 to I2). | -//| 0 <= I1 <= I2 <= N-1. | -//| Z - if ZNeeded is equal to: | -//| * 0, Z isn't used and remains unchanged; | -//| * 1, Z contains the square matrix (array whose | -//| indexes range within [0..N-1, 0..N-1]) which | -//| reduces the given symmetric matrix to | -//| tridiagonal form; | -//| * 2, Z isn't used (but changed on the exit). | -//| Output parameters: | -//| D - array of the eigenvalues found. | -//| Array whose index ranges within [0..I2-I1]. | -//| Z - if ZNeeded is equal to: | -//| * 0, doesn't contain any information; | -//| * 1, contains the product of a given NxN matrix | -//| Z (from the left) and Nx(I2-I1) matrix of the | -//| eigenvectors found (from the right). Array | -//| whose indexes range within [0..N-1, 0..I2-I1].| -//| * 2, contains the matrix of the eigenvalues | -//| found. Array whose indexes range within | -//| [0..N-1, 0..I2-I1]. | -//| Result: | -//| True, if successful. In that case, D contains the | -//| eigenvalues, Z contains the eigenvectors (if needed). | -//| It should be noted that the subroutine changes the size of | -//| arrays D and Z. | -//| False, if the bisection method subroutine wasn't able to find| -//| the eigenvalues in the given interval or if the inverse | -//| iteration subroutine wasn't able to find all the | -//| corresponding eigenvectors. In that case, the eigenvalues and| -//| eigenvectors are not returned. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::SMatrixTdEVDI(double &d[],double &e[],const int n, - const int zneeded,const int i1, - const int i2,CMatrixDouble &z) - { -//--- create variables - bool result; - int errorcode=0; - int nsplit=0; - int i=0; - int j=0; - int k=0; - int m=0; - int cr=0; - double v=0; - int i_=0; - int i1_=0; -//--- create arrays - int iblock[]; - int isplit[]; - int ifail[]; - double w[]; - double d1[]; - double e1[]; -//--- create matrix - CMatrixDouble z2; - CMatrixDouble z3; -//--- check - if(!CAp::Assert((0<=i1 && i1<=i2) && i21) - { - ArrayResizeAL(e1,n); - i1_=-1; - for(i_=1;i_0, we have a pair of complex conjugate | -//| numbers with positive and negative imaginary | -//| parts: the first eigenvalue WR[i] + | -//| + sqrt(-1)*WI[i]; the second eigenvalue | -//| WR[i+1] + sqrt(-1)*WI[i+1]; | -//| WI[i]>0 | -//| WI[i+1] = -WI[i] < 0 | -//| In that case, the eigenvector corresponding to | -//| the first eigenvalue is located in i and i+1 | -//| columns of matrices VL/VR (the column number i | -//| contains the real part, and the column number | -//| i+1 contains the imaginary part), and the vector | -//| corresponding to the second eigenvalue is a | -//| complex conjugate to the first vector. | -//| Arrays whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm has not converged. | -//| Note 1: | -//| Some users may ask the following question: what if WI[N-1]>0?| -//| WI[N] must contain an eigenvalue which is complex conjugate | -//| to the N-th eigenvalue, but the array has only size N? | -//| The answer is as follows: such a situation cannot occur | -//| because the algorithm finds a pairs of eigenvalues, | -//| therefore, if WI[i]>0, I is strictly less than N-1. | -//| Note 2: | -//| The algorithm performance depends on the value of the | -//| internal parameter NS of the InternalSchurDecomposition | -//| subroutine which defines the number of shifts in the QR | -//| algorithm (similarly to the block width in block-matrix | -//| algorithms of linear algebra). If you require maximum | -//| performance on your machine, it is recommended to adjust | -//| this parameter manually. | -//| See also the InternalTREVC subroutine. | -//| The algorithm is based on the LAPACK 3.0 library. | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::RMatrixEVD(CMatrixDouble &ca,const int n,const int vneeded, - double &wr[],double &wi[], - CMatrixDouble &vl,CMatrixDouble &vr) - { -//--- create variables - int i=0; - int i_=0; - int i1_=0; - bool result; -//--- create arrays - double wr1[]; - double wi1[]; -//--- create matrix - CMatrixDouble a1; - CMatrixDouble vl1; - CMatrixDouble vr1; -//--- create copy - CMatrixDouble a; - a=ca; -//--- check - if(!CAp::Assert(vneeded>=0 && vneeded<=3,__FUNCTION__+": incorrect VNeeded!")) - return(false); - a1.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - i1_=-1; - for(i_=1;i_<=n;i_++) - a1[i].Set(i_,a[i-1][i_+i1_]); - } -//--- get result - result=NonSymmetricEVD(a1,n,vneeded,wr1,wi1,vl1,vr1); -//--- check - if(result) - { - //--- allocation - ArrayResizeAL(wr,n); - ArrayResizeAL(wi,n); - i1_=1; - for(i_=0;i_=0 && zneeded<=3,__FUNCTION__+": Incorrent ZNeeded")) - return(false); -//--- check - if(zneeded<0 || zneeded>3) - return(false); -//--- initialization - result=true; -//--- check - if(n==0) - return(result); -//--- check - if(n==1) - { - //--- check - if(zneeded==2 || zneeded==3) - { - z.Resize(2,2); - z[1].Set(1,1); - } - //--- return result - return(result); - } -//--- initialization - maxit=30; -//--- allocation - ArrayResizeAL(wtemp,n+1); - ArrayResizeAL(work1,n); - ArrayResizeAL(work2,n); - ArrayResizeAL(workc,n+1); - ArrayResizeAL(works,n+1); -//--- Determine the unit roundoff and over/underflow thresholds. - eps=CMath::m_machineepsilon; - eps2=CMath::Sqr(eps); - safmin=CMath::m_minrealnumber; - safmax=CMath::m_maxrealnumber; - ssfmax=MathSqrt(safmax)/3; - ssfmin=MathSqrt(safmin)/eps2; -//--- Here we are using transposition to get rid of column operations - wastranspose=false; - zrows=0; -//--- check - if(zneeded==1) - zrows=n; -//--- check - if(zneeded==2) - zrows=n; -//--- check - if(zneeded==3) - zrows=1; -//--- check - if(zneeded==1) - { - wastranspose=true; - //--- function call - CBlas::InplaceTranspose(z,1,n,1,n,wtemp); - } -//--- check - if(zneeded==2) - { - wastranspose=true; - z.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - for(j=1;j<=n;j++) - { - //--- check - if(i==j) - z[i].Set(j,1); - else - z[i].Set(j,0); - } - } - } -//--- check - if(zneeded==3) - { - wastranspose=false; - z.Resize(2,n+1); - for(j=1;j<=n;j++) - { - //--- check - if(j==1) - z[1].Set(j,1); - else - z[1].Set(j,0); - } - } -//--- initialization - nmaxit=n*maxit; - jtot=0; -//--- Determine where the matrix splits and choose QL or QR iteration -//--- for each block, according to whether top or bottom diagonal -//--- element is smaller. - l1=1; - nm1=n-1; - while(true) - { - //--- check - if(l1>n) - break; - //--- check - if(l1>1) - e[l1-1]=0; - gotoflag=false; - m=l1; - //--- check - if(l1<=nm1) - { - for(m=l1;m<=nm1;m++) - { - tst=MathAbs(e[m]); - //--- check - if(tst==0.0) - { - gotoflag=true; - //--- break the cycle - break; - } - //--- check - if(tst<=MathSqrt(MathAbs(d[m]))*MathSqrt(MathAbs(d[m+1]))*eps) - { - e[m]=0; - gotoflag=true; - //--- break the cycle - break; - } - } - } - //--- check - if(!gotoflag) - m=n; - //--- change values - l=l1; - lsv=l; - lend=m; - lendsv=lend; - l1=m+1; - //--- check - if(lend==l) - continue; - //--- Scale submatrix in rows and columns L to LEND - if(l==lend) - anorm=MathAbs(d[l]); - else - { - anorm=MathMax(MathAbs(d[l])+MathAbs(e[l]),MathAbs(e[lend-1])+MathAbs(d[lend])); - for(i=l+1;i<=lend-1;i++) - anorm=MathMax(anorm,MathAbs(d[i])+MathAbs(e[i])+MathAbs(e[i-1])); - } - iscale=0; - //--- check - if(anorm==0.0) - continue; - //--- check - if(anorm>(double)(ssfmax)) - { - iscale=1; - tmp=ssfmax/anorm; - tmpint=lend-1; - for(i_=l;i_<=lend;i_++) - d[i_]=tmp*d[i_]; - for(i_=l;i_<=tmpint;i_++) - e[i_]=tmp*e[i_]; - } - //--- check - if(anorml) - { - //--- QL Iteration - //--- Look for small subdiagonal element. - while(true) - { - gotoflag=false; - //--- check - if(l!=lend) - { - lendm1=lend-1; - for(m=l;m<=lendm1;m++) - { - tst=CMath::Sqr(MathAbs(e[m])); - //--- check - if(tst<=eps2*MathAbs(d[m])*MathAbs(d[m+1])+safmin) - { - gotoflag=true; - //--- break the cycle - break; - } - } - } - //--- check - if(!gotoflag) - m=lend; - //--- check - if(m0) - { - //--- function call - TdEVDEv2(d[l],e[l],d[l+1],rt1,rt2,c,s); - //--- change values - work1[l]=c; - work2[l]=s; - workc[1]=work1[l]; - works[1]=work2[l]; - //--- check - if(!wastranspose) - CRotations::ApplyRotationsFromTheRight(false,1,zrows,l,l+1,workc,works,z,wtemp); - else - CRotations::ApplyRotationsFromTheLeft(false,l,l+1,1,zrows,workc,works,z,wtemp); - } - else - //--- function call - TdEVDE2(d[l],e[l],d[l+1],rt1,rt2); - //--- change values - d[l]=rt1; - d[l+1]=rt2; - e[l]=0; - l=l+2; - //--- check - if(l<=lend) - continue; - //--- break the cycle - break; - } - //--- check - if(jtot==nmaxit) - break; - jtot=jtot+1; - //--- Form shift. - g=(d[l+1]-p)/(2*e[l]); - //--- function call - r=TdEVDPythag(g,1); - g=d[m]-p+e[l]/(g+TdEVDExtSign(r,g)); - s=1; - c=1; - p=0; - //--- Inner loop - mm1=m-1; - for(i=mm1;i>=l;i--) - { - f=s*e[i]; - b=c*e[i]; - //--- function call - CRotations::GenerateRotation(g,f,c,s,r); - //--- check - if(i!=m-1) - e[i+1]=r; - g=d[i+1]-p; - r=(d[i]-g)*s+2*c*b; - p=s*r; - d[i+1]=g+p; - g=c*r-b; - //--- If eigenvectors are desired, then save rotations. - if(zneeded>0) - { - work1[i]=c; - work2[i]=-s; - } - } - //--- If eigenvectors are desired, then apply saved rotations. - if(zneeded>0) - { - for(i=l;i=lendp1;m--) - { - tst=CMath::Sqr(MathAbs(e[m-1])); - //--- check - if(tst<=(double)(eps2*MathAbs(d[m])*MathAbs(d[m-1])+safmin)) - { - gotoflag=true; - //--- break the cycle - break; - } - } - } - //--- check - if(!gotoflag) - m=lend; - //--- check - if(m>lend) - e[m-1]=0; - p=d[l]; - //--- check - if(m!=l) - { - //--- If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 - //--- to compute its eigensystem. - if(m==l-1) - { - //--- check - if(zneeded>0) - { - //--- function call - TdEVDEv2(d[l-1],e[l-1],d[l],rt1,rt2,c,s); - work1[m]=c; - work2[m]=s; - workc[1]=c; - works[1]=s; - //--- check - if(!wastranspose) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(true,1,zrows,l-1,l,workc,works,z,wtemp); - } - else - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(true,l-1,l,1,zrows,workc,works,z,wtemp); - } - } - else - { - //--- function call - TdEVDE2(d[l-1],e[l-1],d[l],rt1,rt2); - } - d[l-1]=rt1; - d[l]=rt2; - e[l-1]=0; - l=l-2; - //--- check - if(l>=lend) - continue; - //--- break the cycle - break; - } - //--- check - if(jtot==nmaxit) - break; - jtot=jtot+1; - //--- Form shift. - g=(d[l-1]-p)/(2*e[l-1]); - //--- function call - r=TdEVDPythag(g,1); - g=d[m]-p+e[l-1]/(g+TdEVDExtSign(r,g)); - s=1; - c=1; - p=0; - //--- Inner loop - lm1=l-1; - for(i=m;i<=lm1;i++) - { - f=s*e[i]; - b=c*e[i]; - //--- function call - CRotations::GenerateRotation(g,f,c,s,r); - //--- check - if(i!=m) - e[i-1]=r; - //--- change values - g=d[i]-p; - r=(d[i+1]-g)*s+2*c*b; - p=s*r; - d[i]=g+p; - g=c*r-b; - //--- If eigenvectors are desired, then save rotations. - if(zneeded>0) - { - work1[i]=c; - work2[i]=s; - } - } - //--- If eigenvectors are desired, then apply saved rotations. - if(zneeded>0) - { - mm=l-m+1; - for(i=m;i<=l-1;i++) - { - workc[i-m+1]=work1[i]; - works[i-m+1]=work2[i]; - } - //--- check - if(!wastranspose) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(true,1,zrows,m,l,workc,works,z,wtemp); - } - else - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(true,m,l,1,zrows,workc,works,z,wtemp); - } - } - d[l]=d[l]-p; - e[lm1]=g; - continue; - } - //--- Eigenvalue found. - d[l]=p; - l=l-1; - //--- check - if(l>=lend) - continue; - //--- break the cycle - break; - } - } - //--- Undo scaling if necessary - if(iscale==1) - { - tmp=anorm/ssfmax; - tmpint=lendsv-1; - for(i_=lsv;i_<=lendsv;i_++) - d[i_]=tmp*d[i_]; - for(i_=lsv;i_<=tmpint;i_++) - e[i_]=tmp*e[i_]; - } - //--- check - if(iscale==2) - { - tmp=anorm/ssfmin; - tmpint=lendsv-1; - for(i_=lsv;i_<=lendsv;i_++) - d[i_]=tmp*d[i_]; - for(i_=lsv;i_<=tmpint;i_++) - e[i_]=tmp*e[i_]; - } - //--- Check for no convergence to an eigenvalue after a total - //--- of N*MAXIT iterations. - if(jtot>=nmaxit) - { - result=false; - //--- check - if(wastranspose) - { - //--- function call - CBlas::InplaceTranspose(z,1,n,1,n,wtemp); - } - //--- return result - return(result); - } - } -//--- Order eigenvalues and eigenvectors. - if(zneeded==0) - { - //--- Sort - if(n==1) - return(result); - //--- check - if(n==2) - { - //--- check - if(d[1]>d[2]) - { - tmp=d[1]; - d[1]=d[2]; - d[2]=tmp; - } - //--- return result - return(result); - } - i=2; - do - { - t=i; - while(t!=1) - { - k=t/2; - //--- check - if(d[k]>=d[t]) - t=1; - else - { - //--- change values - tmp=d[k]; - d[k]=d[t]; - d[t]=tmp; - t=k; - } - } - i=i+1; - } - //--- cycle - while(i<=n); - i=n-1; - do - { - tmp=d[i+1]; - d[i+1]=d[1]; - d[1]=tmp; - t=1; - while(t!=0) - { - k=2*t; - //--- check - if(k>i) - t=0; - else - { - //--- check - if(kd[k]) - k=k+1; - } - //--- check - if(d[t]>=d[k]) - t=0; - else - { - //--- change values - tmp=d[k]; - d[k]=d[t]; - d[t]=tmp; - t=k; - } - } - } - i=i-1; - } - while(i>=1); - } - else - { - //--- Use Selection Sort to minimize swaps of eigenvectors - for(ii=2;ii<=n;ii++) - { - i=ii-1; - k=i; - p=d[i]; - for(j=ii;j<=n;j++) - { - //--- check - if(d[j]MathAbs(c)) - { - acmx=a; - acmn=c; - } - else - { - acmx=c; - acmn=a; - } -//--- check - if(adf>ab) - { - rt=adf*MathSqrt(1+CMath::Sqr(ab/adf)); - } - else - { - //--- check - if(adf0.0) - { - rt1=0.5*(sm+rt); - //--- Order of execution important. - //--- To get fully accurate smaller eigenvalue, - //--- next line needs to be executed in higher precision. - rt2=acmx/rt1*acmn-b/rt1*b; - } - else - { - //--- Includes case RT1 = RT2 = 0 - rt1=0.5*rt; - rt2=-(0.5*rt); - } - } - } -//+------------------------------------------------------------------+ -//| DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric | -//| matrix | -//| [ A B ] | -//| [ B C ]. | -//| On return, RT1 is the eigenvalue of larger absolute value, RT2 is| -//| the eigenvalue of smaller absolute value, and (CS1,SN1) is the | -//| unit right eigenvector for RT1, giving the decomposition | -//| [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] | -//| [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1992 | -//+------------------------------------------------------------------+ -static void CEigenVDetect::TdEVDEv2(const double a,const double b,const double c, - double &rt1,double &rt2,double &cs1,double &sn1) - { -//--- create variables - int sgn1=0; - int sgn2=0; - double ab=0; - double acmn=0; - double acmx=0; - double acs=0; - double adf=0; - double cs=0; - double ct=0; - double df=0; - double rt=0; - double sm=0; - double tb=0; - double tn=0; -//--- initialization - rt1=0; - rt2=0; - cs1=0; - sn1=0; -//--- Compute the eigenvalues - sm=a+c; - df=a-c; - adf=MathAbs(df); - tb=b+b; - ab=MathAbs(tb); -//--- check - if(MathAbs(a)>MathAbs(c)) - { - acmx=a; - acmn=c; - } - else - { - acmx=c; - acmn=a; - } -//--- check - if(adf>ab) - rt=adf*MathSqrt(1+CMath::Sqr(ab/adf)); - else - { - //--- check - if(adf0.0) - { - rt1=0.5*(sm+rt); - sgn1=1; - //--- Order of execution important. - //--- To get fully accurate smaller eigenvalue, - //--- next line needs to be executed in higher precision. - rt2=acmx/rt1*acmn-b/rt1*b; - } - else - { - //--- Includes case RT1 = RT2 = 0 - rt1=0.5*rt; - rt2=-(0.5*rt); - sgn1=1; - } - } -//--- Compute the eigenvector - if(df>=0.0) - { - cs=df+rt; - sgn2=1; - } - else - { - cs=df-rt; - sgn2=-1; - } - acs=MathAbs(cs); -//--- check - if(acs>ab) - { - ct=-(tb/cs); - sn1=1/MathSqrt(1+ct*ct); - cs1=ct*sn1; - } - else - { - //--- check - if(ab==0.0) - { - cs1=1; - sn1=0; - } - else - { - tn=-(cs/tb); - cs1=1/MathSqrt(1+tn*tn); - sn1=tn*cs1; - } - } -//--- check - if(sgn1==sgn2) - { - tn=cs1; - cs1=-sn1; - sn1=tn; - } - } -//+------------------------------------------------------------------+ -//| Internal routine | -//+------------------------------------------------------------------+ -static double CEigenVDetect::TdEVDPythag(const double a,const double b) - { -//--- create variables - double result=0; -//--- check - if(MathAbs(a)=0.0) - result=MathAbs(a); - else - result=-MathAbs(a); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static bool CEigenVDetect::InternalBisectionEigenValues(double &cd[],double &ce[], - const int n,int irange, - const int iorder,const double vl, - const double vu,const int il, - const int iu,const double abstol, - double &w[],int &m, - int &nsplit,int &iblock[], - int &isplit[],int &errorcode) - { -//--- create variables - bool result; - double fudge=0; - double relfac=0; - bool ncnvrg; - bool toofew; - int ib=0; - int ibegin=0; - int idiscl=0; - int idiscu=0; - int ie=0; - int iend=0; - int iinfo=0; - int im=0; - int iin=0; - int ioff=0; - int iout=0; - int itmax=0; - int iw=0; - int iwoff=0; - int j=0; - int itmp1=0; - int jb=0; - int jdisc=0; - int je=0; - int nwl=0; - int nwu=0; - int tmpi=0; - double atoli=0; - double bnorm=0; - double gl=0; - double gu=0; - double pivmin=0; - double rtoli=0; - double safemn=0; - double tmp1=0; - double tmp2=0; - double tnorm=0; - double ulp=0; - double wkill=0; - double wl=0; - double wlu=0; - double wu=0; - double wul=0; - double scalefactor=0; - double t=0; -//--- create arrays - int idumma[]; - double work[]; - int iwork[]; - int ia1s2[]; - double ra1s2[]; - double ra1siin[]; - double ra2siin[]; - double ra3siin[]; - double ra4siin[]; - int iworkspace[]; - double rworkspace[]; -//--- create matrix - CMatrixDouble ra1s2x2; - CMatrixInt ia1s2x2; - CMatrixDouble ra1siinx2; - CMatrixInt ia1siinx2; -//--- create copy - double d[]; - ArrayResizeAL(d,ArraySize(cd)); - ArrayCopy(d,cd); -//--- create copy - double e[]; - ArrayResizeAL(e,ArraySize(ce)); - ArrayCopy(e,ce); -//--- initialization - m=0; - nsplit=0; - errorcode=0; -//--- check - if(n==0) - return(true); -//--- Get machine constants -//--- NB is the minimum vector length for vector bisection, or 0 -//--- if only scalar is to be done. - fudge=2; - relfac=2; - safemn=CMath::m_minrealnumber; - ulp=2*CMath::m_machineepsilon; - rtoli=ulp*relfac; -//--- allocation - ArrayResizeAL(idumma,2); - ArrayResizeAL(work,4*n+1); - ArrayResizeAL(iwork,3*n+1); - ArrayResizeAL(w,n+1); - ArrayResizeAL(iblock,n+1); - ArrayResizeAL(isplit,n+1); - ArrayResizeAL(ia1s2,3); - ArrayResizeAL(ra1s2,3); - ArrayResizeAL(ra1siin,n+1); - ArrayResizeAL(ra2siin,n+1); - ArrayResizeAL(ra3siin,n+1); - ArrayResizeAL(ra4siin,n+1); - ArrayResizeAL(iworkspace,n+1); - ArrayResizeAL(rworkspace,n+1); - ra1siinx2.Resize(n+1,3); - ia1siinx2.Resize(n+1,3); - ra1s2x2.Resize(3,3); - ia1s2x2.Resize(3,3); -//--- initialization - wlu=0; - wul=0; -//--- Check for Errors - result=false; - errorcode=0; -//--- check - if(irange<=0 || irange>=4) - errorcode=-4; -//--- check - if(iorder<=0 || iorder>=3) - errorcode=-5; -//--- check - if(n<0) - errorcode=-3; -//--- check - if(irange==2 && vl>=vu) - errorcode=-6; -//--- check - if(irange==3 && (il<1 || il>MathMax(1,n))) - errorcode=-8; -//--- check - if(irange==3 && (iun)) - errorcode=-9; -//--- check - if(errorcode!=0) - return(result); -//--- Initialize error flags - ncnvrg=false; - toofew=false; -//--- Simplifications: - if(irange==3 && il==1 && iu==n) - irange=1; -//--- Special Case when N=1 - if(n==1) - { - nsplit=1; - isplit[1]=1; - //--- check - if((irange==2 && vl>=d[1]) || vuMathSqrt(MathSqrt(CMath::m_minrealnumber))*MathSqrt(CMath::m_maxrealnumber)) - scalefactor=t; - //--- check - if(ttmp1) - { - isplit[nsplit]=j-1; - nsplit=nsplit+1; - work[j-1]=0; - } - else - { - work[j-1]=tmp1; - pivmin=MathMax(pivmin,tmp1); - } - } - isplit[nsplit]=n; - pivmin=pivmin*safemn; -//--- Compute Interval and ATOLI - if(irange==3) - { - //--- RANGE='I': Compute the interval containing eigenvalues - //--- IL through IU. - //--- Compute Gershgorin interval for entire (split) matrix - //--- and use it as the initial interval - gu=d[1]; - gl=d[1]; - tmp1=0; - for(j=1;j=n || nwu<1 || nwu>n) - { - errorcode=4; - return(false); - } - } - else - { - //--- RANGE='A' or 'V' -- Set ATOLI - tnorm=MathMax(MathAbs(d[1])+MathAbs(e[1]),MathAbs(d[n])+MathAbs(e[n-1])); - for(j=2;j=d[ibegin]-pivmin) - nwl=nwl+1; - //--- check - if(irange==1 || wu>=d[ibegin]-pivmin) - nwu=nwu+1; - //--- check - if((irange==1 || wl=d[ibegin]-pivmin) - { - m=m+1; - w[m]=d[ibegin]; - iblock[m]=jb; - } - } - else - { - //--- General Case -- IIN > 1 - //--- Compute Gershgorin Interval - //--- and use it as the initial interval - gu=d[ibegin]; - gl=d[ibegin]; - tmp1=0; - for(j=ibegin;j<=iend-1;j++) - { - //--- change values - tmp2=MathAbs(e[j]); - gu=MathMax(gu,d[j]+tmp1+tmp2); - gl=MathMin(gl,d[j]-tmp1-tmp2); - tmp1=tmp2; - } - //--- change values - gu=MathMax(gu,d[iend]+tmp1); - gl=MathMin(gl,d[iend]-tmp1); - bnorm=MathMax(MathAbs(gl),MathAbs(gu)); - gl=gl-fudge*bnorm*ulp*iin-fudge*pivmin; - gu=gu+fudge*bnorm*ulp*iin+fudge*pivmin; - //--- Compute ATOLI for the current submatrix - if(abstol<=0.0) - atoli=ulp*MathMax(MathAbs(gl),MathAbs(gu)); - else - atoli=abstol; - //--- check - if(irange>1) - { - //--- check - if(gu=gu) - continue; - } - //--- Set Up Initial Interval - work[n+1]=gl; - work[n+iin+1]=gu; - //--- Calling DLAEBZ - //--- CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, - //--- D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), - //--- IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM, - //--- IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) - for(tmpi=1;tmpi<=iin;tmpi++) - { - ra1siin[tmpi]=d[ibegin-1+tmpi]; - //--- check - if(ibegin-1+tmpiiout-iinfo) - { - ncnvrg=true; - ib=-jb; - } - else - ib=jb; - for(je=iwork[j]+1+iwoff;je<=iwork[j+iin]+iwoff;je++) - { - w[je]=tmp1; - iblock[je]=ib; - } - } - m=m+im; - } - } -//--- If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU -//--- If NWL+1 < IL or NWU > IU, discard extra eigenvalues. - if(irange==3) - { - im=0; - idiscl=il-1-nwl; - idiscu=nwu-iu; - //--- check - if(idiscl>0 || idiscu>0) - { - for(je=1;je<=m;je++) - { - //--- check - if(w[je]<=wlu && idiscl>0) - { - idiscl=idiscl-1; - } - else - { - //--- check - if(w[je]>=wul && idiscu>0) - idiscu=idiscu-1; - else - { - im=im+1; - w[im]=w[je]; - iblock[im]=iblock[je]; - } - } - } - m=im; - } - //--- check - if(idiscl>0 || idiscu>0) - { - //--- Code to deal with effects of bad arithmetic: - //--- Some low eigenvalues to be discarded are not in (WL,WLU], - //--- or high eigenvalues to be discarded are not in (WUL,WU] - //--- so just kill off the smallest IDISCL/largest IDISCU - //--- eigenvalues, by simply finding the smallest/largest - //--- eigenvalue(s). - //--- (If N(w) is monotone non-decreasing, this should never - //--- happen.) - if(idiscl>0) - { - wkill=wu; - for(jdisc=1;jdisc<=idiscl;jdisc++) - { - iw=0; - for(je=1;je<=m;je++) - { - //--- check - if(iblock[je]!=0 && (w[je]<(double)(wkill) || iw==0)) - { - iw=je; - wkill=w[je]; - } - } - iblock[iw]=0; - } - } - //--- check - if(idiscu>0) - { - wkill=wl; - for(jdisc=1;jdisc<=idiscu;jdisc++) - { - iw=0; - for(je=1;je<=m;je++) - { - //--- check - if(iblock[je]!=0 && (w[je]>(double)(wkill) || iw==0)) - { - iw=je; - wkill=w[je]; - } - } - iblock[iw]=0; - } - } - im=0; - for(je=1;je<=m;je++) - { - //--- check - if(iblock[je]!=0) - { - im=im+1; - w[im]=w[je]; - iblock[im]=iblock[je]; - } - } - m=im; - } - //--- check - if(idiscl<0 || idiscu<0) - toofew=true; - } -//--- If ORDER='B', do nothing -- the eigenvalues are already sorted -//--- by block. -//--- If ORDER='E', sort the eigenvalues from smallest to largest - if(iorder==1 && nsplit>1) - { - for(je=1;je<=m-1;je++) - { - ie=0; - tmp1=w[je]; - for(j=je+1;j<=m;j++) - { - //--- check - if(w[j]n) - { - info=-4; - return; - } - for(j=2;j<=m;j++) - { - //--- check - if(iblock[j]1) - { - eps1=MathAbs(eps*xj); - pertol=10*eps1; - sep=xj-xjm; - //--- check - if(sepmaxits) - { - //--- If stopping criterion was not satisfied, update info and - //--- store eigenvector number in array ifail. - info=info+1; - ifail[info]=j; - break; - } - //--- Normalize and scale the righthand side vector Pb. - v=0; - for(ti=1;ti<=blksiz;ti++) - v=v+MathAbs(work1[ti]); - scl=blksiz*onenrm*MathMax(eps,MathAbs(work4[blksiz]))/v; - for(i_=1;i_<=blksiz;i_++) - work1[i_]=scl*work1[i_]; - //--- Solve the system LU = Pb. - TdIninternalDLAGTS(blksiz,work4,work2,work3,work5,iwork,work1,tol,iinfo); - //--- Reorthogonalize by modified Gram-Schmidt if eigenvalues are - //--- close enough. - if(jblk!=1) - { - //--- check - if(MathAbs(xj-xjm)>ortol) - gpind=j; - //--- check - if(gpind!=j) - { - for(i=gpind;i1) - tol=MathMax(tol,MathMax(MathAbs(a[2]),MathAbs(b[1]))); - for(k=3;k<=n;k++) - tol=MathMax(tol,MathMax(MathAbs(a[k]),MathMax(MathAbs(b[k-1]),MathAbs(d[k-2])))); - tol=tol*eps; - //--- check - if(tol==0.0) - tol=eps; - } - for(k=2;k<=n;k++) - { - //--- check - if(iin[k-1]==0) - y[k]=y[k]-c[k-1]*y[k-1]; - else - { - temp=y[k-1]; - y[k-1]=y[k]; - y[k]=temp-c[k-1]*y[k]; - } - } - for(k=n;k>=1;k--) - { - //--- check - if(k<=n-2) - temp=y[k]-b[k]*y[k+1]-d[k]*y[k+2]; - else - { - //--- check - if(k==n-1) - temp=y[k]-b[k]*y[k+1]; - else - temp=y[k]; - } - ak=a[k]; - pert=MathAbs(tol); - //--- check - if(ak<0.0) - pert=-pert; - while(true) - { - absak=MathAbs(ak); - //--- check - if(absak<1.0) - { - //--- check - if(absakabsak) - { - ak=ak+pert; - pert=2*pert; - continue; - } - else - { - temp=temp*bignum; - ak=ak*bignum; - } - } - else - { - //--- check - if(MathAbs(temp)>absak*bignum) - { - ak=ak+pert; - pert=2*pert; - continue; - } - } - } - //--- break the cycle - break; - } - y[k]=temp/ak; - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CEigenVDetect::InternalDLAEBZ(const int ijob,const int nitmax, - const int n,const int mmax,const int minp, - const double abstol,const double reltol, - const double pivmin,double &d[], - double &e[],double &e2[],int &nval[], - CMatrixDouble &ab,double &c[],int &mout, - CMatrixInt &nab,double &work[], - int &iwork[],int &info) - { -//--- create variables - int itmp1=0; - int itmp2=0; - int j=0; - int ji=0; - int jit=0; - int jp=0; - int kf=0; - int kfnew=0; - int kl=0; - int klnew=0; - double tmp1=0; - double tmp2=0; -//--- initialization - mout=0; - info=0; -//--- check - if(ijob<1 || ijob>3) - { - info=-1; - //--- exit the function - return; - } -//--- Initialize NAB - if(ijob==1) - { - //--- Compute the number of eigenvalues in the initial intervals. - mout=0; - //--- DIR$ NOVECTOR - for(ji=1;ji<=minp;ji++) - { - for(jp=1;jp<=2;jp++) - { - tmp1=d[1]-ab[ji][jp]; - //--- check - if(MathAbs(tmp1)=nval[ji]) - { - ab[ji].Set(2,tmp1); - nab[ji].Set(2,itmp1); - } - } - } - kl=klnew; - //--- Check for convergence - kfnew=kf; - for(ji=kf;ji<=kl;ji++) - { - tmp1=MathAbs(ab[ji][2]-ab[ji][1]); - tmp2=MathMax(MathAbs(ab[ji][2]),MathAbs(ab[ji][1])); - //--- check - if(tmp1<(double)(MathMax(abstol,MathMax(pivmin,reltol*tmp2))) || nab[ji][1]>=nab[ji][2]) - { - //--- Converged -- Swap with position KFNEW, - //--- then increment KFNEW - if(ji>kfnew) - { - tmp1=ab[ji][1]; - tmp2=ab[ji][2]; - itmp1=nab[ji][1]; - itmp2=nab[ji][2]; - //--- change values - ab[ji].Set(1,ab[kfnew][1]); - ab[ji].Set(2,ab[kfnew][2]); - nab[ji].Set(1,nab[kfnew][1]); - nab[ji].Set(2,nab[kfnew][2]); - ab[kfnew].Set(1,tmp1); - ab[kfnew].Set(2,tmp2); - nab[kfnew].Set(1,itmp1); - nab[kfnew].Set(2,itmp2); - //--- check - if(ijob==3) - { - itmp1=nval[ji]; - nval[ji]=nval[kfnew]; - nval[kfnew]=itmp1; - } - } - kfnew=kfnew+1; - } - } - kf=kfnew; - //--- Choose Midpoints - for(ji=kf;ji<=kl;ji++) - c[ji]=0.5*(ab[ji][1]+ab[ji][2]); - //--- If no more intervals to refine, quit. - if(kf>kl) - break; - } -//--- Converged - info=(int)MathMax(kl+1-kf,0); - mout=kl; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee,Univ. of California Berkeley,NAG Ltd., | -//| Courant Institute,Argonne National Lab, and Rice University | -//| June 30,1999 | -//+------------------------------------------------------------------+ -static void CEigenVDetect::InternalTREVC(CMatrixDouble &t,const int n,const int side, - const int howmny,bool &cvselect[],CMatrixDouble &vl, - CMatrixDouble &vr,int &m,int &info) - { -//--- create variables - bool allv; - bool bothv; - bool leftv; - bool over; - bool pair; - bool rightv; - bool somev; - int i=0; - int ierr=0; - int ii=0; - int ip=0; - int iis=0; - int j=0; - int j1=0; - int j2=0; - int jnxt=0; - int k=0; - int ki=0; - int n2=0; - double beta=0; - double bignum=0; - double emax=0; - double ovfl=0; - double rec=0; - double remax=0; - double scl=0; - double smin=0; - double smlnum=0; - double ulp=0; - double unfl=0; - double vcrit=0; - double vmax=0; - double wi=0; - double wr=0; - double xnorm=0; - bool skipflag; - int k1=0; - int k2=0; - int k3=0; - int k4=0; - double vt=0; - int i_=0; - int i1_=0; -//--- create arrays - double work[]; - double temp[]; - bool rswap4[]; - bool zswap4[]; - double civ4[]; - double crv4[]; -//--- create matrix - CMatrixDouble x; - CMatrixDouble temp11; - CMatrixDouble temp22; - CMatrixDouble temp11b; - CMatrixDouble temp21b; - CMatrixDouble temp12b; - CMatrixDouble temp22b; - CMatrixInt ipivot44; -//--- create copy - bool vselect[]; - ArrayResizeAL(vselect,ArraySize(cvselect)); - ArrayCopy(vselect,cvselect); -//--- initialization - m=0; - info=0; -//--- allocation - x.Resize(3,3); - temp11.Resize(2,2); - temp11b.Resize(2,2); - temp21b.Resize(3,2); - temp12b.Resize(2,3); - temp22b.Resize(3,3); - temp22.Resize(3,3); - ArrayResizeAL(work,3*n+1); - ArrayResizeAL(temp,n+1); - ArrayResizeAL(rswap4,5); - ArrayResizeAL(zswap4,5); - ArrayResizeAL(civ4,5); - ArrayResizeAL(crv4,5); - ipivot44.Resize(5,5); -//--- check - if(howmny!=1) - { - //--- check - if(side==1 || side==3) - vr.Resize(n+1,n+1); - //--- check - if(side==2 || side==3) - vl.Resize(n+1,n+1); - } -//--- Decode and test the input parameters - bothv=side==3; - rightv=side==1 || bothv; - leftv=side==2 || bothv; - allv=howmny==2; - over=howmny==1; - somev=howmny==3; - info=0; -//--- check - if(n<0) - { - info=-2; - return; - } -//--- check - if(!rightv && !leftv) - { - info=-3; - return; - } -//--- check - if((!allv && !over) && !somev) - { - info=-4; - return; - } -//--- Set M to the number of columns required to store the selected -//--- eigenvectors, standardize the array SELECT if necessary, and -//--- test MM. - if(somev) - { - m=0; - pair=false; - for(j=1;j<=n;j++) - { - //--- check - if(pair) - { - pair=false; - vselect[j]=false; - } - else - { - //--- check - if(j=1;ki--) - { - skipflag=false; - //--- check - if(ip==1) - skipflag=true; - else - { - //--- check - if(ki!=1) - { - //--- check - if(t[ki][ki-1]!=0.0) - ip=-1; - } - //--- check - if(somev) - { - //--- check - if(ip==0) - { - //--- check - if(!vselect[ki]) - skipflag=true; - } - else - { - //--- check - if(!vselect[ki-1]) - skipflag=true; - } - } - } - //--- check - if(!skipflag) - { - //--- Compute the KI-th eigenvalue (WR,WI). - wr=t[ki][ki]; - wi=0; - //--- check - if(ip!=0) - wi=MathSqrt(MathAbs(t[ki][ki-1]))*MathSqrt(MathAbs(t[ki-1][ki])); - smin=MathMax(ulp*(MathAbs(wr)+MathAbs(wi)),smlnum); - //--- check - if(ip==0) - { - //--- Real right eigenvector - work[ki+n]=1; - //--- Form right-hand side - for(k=1;k<=ki-1;k++) - work[k+n]=-t[k][ki]; - //--- Solve the upper quasi-triangular system: - //--- (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK. - jnxt=ki-1; - for(j=ki-1;j>=1;j--) - { - //--- check - if(j>jnxt) - continue; - j1=j; - j2=j; - jnxt=j-1; - //--- check - if(j>1) - { - //--- check - if(t[j][j-1]!=0.0) - { - j1=j-1; - jnxt=j-2; - } - } - //--- check - if(j1==j2) - { - //--- 1-by-1 diagonal block - temp11[1].Set(1,t[j][j]); - temp11b[1].Set(1,work[j+n]); - //--- function call - InternalHsEVDLALN2(false,1,1,smin,1,temp11,1.0,1.0,temp11b,wr,0.0,rswap4,zswap4,ipivot44,civ4,crv4,x,scl,xnorm,ierr); - //--- Scale X(1,1) to avoid overflow when updating - //--- the right-hand side. - if(xnorm>1.0) - { - //--- check - if(work[j]>bignum/xnorm) - { - x[1].Set(1,x[1][1]/xnorm); - scl=scl/xnorm; - } - } - //--- Scale if necessary - if(scl!=1.0) - { - k1=n+1; - k2=n+ki; - for(i_=k1;i_<=k2;i_++) - work[i_]=scl*work[i_]; - } - work[j+n]=x[1][1]; - //--- Update right-hand side - k1=1+n; - k2=j-1+n; - k3=j-1; - vt=-x[1][1]; - i1_=1-k1; - for(i_=k1;i_<=k2;i_++) - { - work[i_]=work[i_]+vt*t[i_+i1_][j]; - } - } - else - { - //--- 2-by-2 diagonal block - temp22[1].Set(1,t[j-1][j-1]); - temp22[1].Set(2,t[j-1][j]); - temp22[2].Set(1,t[j][j-1]); - temp22[2].Set(2,t[j][j]); - temp21b[1].Set(1,work[j-1+n]); - temp21b[2].Set(1,work[j+n]); - //--- function call - InternalHsEVDLALN2(false,2,1,smin,1.0,temp22,1.0,1.0,temp21b,wr,0,rswap4,zswap4,ipivot44,civ4,crv4,x,scl,xnorm,ierr); - //--- Scale X(1,1) and X(2,1) to avoid overflow when - //--- updating the right-hand side. - if(xnorm>1.0) - { - beta=MathMax(work[j-1],work[j]); - //--- check - if(beta>bignum/xnorm) - { - x[1].Set(1,x[1][1]/xnorm); - x[2].Set(1,x[2][1]/xnorm); - scl=scl/xnorm; - } - } - //--- Scale if necessary - if(scl!=1.0) - { - k1=1+n; - k2=ki+n; - for(i_=k1;i_<=k2;i_++) - work[i_]=scl*work[i_]; - } - work[j-1+n]=x[1][1]; - work[j+n]=x[2][1]; - //--- Update right-hand side - k1=1+n; - k2=j-2+n; - k3=j-2; - k4=j-1; - vt=-x[1][1]; - i1_=1-k1; - for(i_=k1;i_<=k2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][k4]; - vt=-x[2][1]; - i1_=1-k1; - for(i_=k1;i_<=k2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j]; - } - } - //--- Copy the vector x or Q*x to VR and normalize. - if(!over) - { - k1=1+n; - k2=ki+n; - i1_=k1-1; - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis,work[i_+i1_]); - //--- function call - ii=CBlas::ColumnIdxAbsMax(vr,1,ki,iis); - remax=1/MathAbs(vr[ii][iis]); - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis,remax*vr[i_][iis]); - for(k=ki+1;k<=n;k++) - vr[k].Set(iis,0); - } - else - { - //--- check - if(ki>1) - { - for(i_=1;i_<=n;i_++) - temp[i_]=vr[i_][ki]; - //--- function call - CBlas::MatrixVectorMultiply(vr,1,n,1,ki-1,false,work,1+n,ki-1+n,1.0,temp,1,n,work[ki+n]); - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki,temp[i_]); - } - //--- function call - ii=CBlas::ColumnIdxAbsMax(vr,1,n,ki); - remax=1/MathAbs(vr[ii][ki]); - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki,remax*vr[i_][ki]); - } - } - else - { - //--- Complex right eigenvector. - //--- Initial solve - //--- [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0. - //--- [ (T(KI,KI-1) T(KI,KI) ) ] - if(MathAbs(t[ki-1][ki])>=MathAbs(t[ki][ki-1])) - { - work[ki-1+n]=1; - work[ki+n2]=wi/t[ki-1][ki]; - } - else - { - work[ki-1+n]=-(wi/t[ki][ki-1]); - work[ki+n2]=1; - } - work[ki+n]=0; - work[ki-1+n2]=0; - //--- Form right-hand side - for(k=1;k<=ki-2;k++) - { - work[k+n]=-(work[ki-1+n]*t[k][ki-1]); - work[k+n2]=-(work[ki+n2]*t[k][ki]); - } - //--- Solve upper quasi-triangular system: - //--- (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2) - jnxt=ki-2; - for(j=ki-2;j>=1;j--) - { - //--- check - if(j>jnxt) - continue; - j1=j; - j2=j; - jnxt=j-1; - //--- check - if(j>1) - { - //--- check - if(t[j][j-1]!=0.0) - { - j1=j-1; - jnxt=j-2; - } - } - //--- check - if(j1==j2) - { - //--- 1-by-1 diagonal block - temp11[1].Set(1,t[j][j]); - temp12b[1].Set(1,work[j+n]); - temp12b[1].Set(2,work[j+n+n]); - //--- function call - InternalHsEVDLALN2(false,1,2,smin,1.0,temp11,1.0,1.0,temp12b,wr,wi,rswap4,zswap4,ipivot44,civ4,crv4,x,scl,xnorm,ierr); - //--- Scale X(1,1) and X(1,2) to avoid overflow when - //--- updating the right-hand side. - if(xnorm>1.0) - { - //--- check - if(work[j]>bignum/xnorm) - { - x[1].Set(1,x[1][1]/xnorm); - x[1].Set(2,x[1][2]/xnorm); - scl=scl/xnorm; - } - } - //--- Scale if necessary - if(scl!=1.0) - { - k1=1+n; - k2=ki+n; - for(i_=k1;i_<=k2;i_++) - work[i_]=scl*work[i_]; - k1=1+n2; - k2=ki+n2; - for(i_=k1;i_<=k2;i_++) - work[i_]=scl*work[i_]; - } - work[j+n]=x[1][1]; - work[j+n2]=x[1][2]; - //--- Update the right-hand side - k1=1+n; - k2=j-1+n; - k3=1; - k4=j-1; - vt=-x[1][1]; - i1_=k3-k1; - for(i_=k1;i_<=k2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j]; - //--- change values - k1=1+n2; - k2=j-1+n2; - k3=1; - k4=j-1; - vt=-x[1][2]; - i1_=k3-k1; - for(i_=k1;i_<=k2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j]; - } - else - { - //--- 2-by-2 diagonal block - temp22[1].Set(1,t[j-1][j-1]); - temp22[1].Set(2,t[j-1][j]); - temp22[2].Set(1,t[j][j-1]); - temp22[2].Set(2,t[j][j]); - temp22b[1].Set(1,work[j-1+n]); - temp22b[1].Set(2,work[j-1+n+n]); - temp22b[2].Set(1,work[j+n]); - temp22b[2].Set(2,work[j+n+n]); - //--- function call - InternalHsEVDLALN2(false,2,2,smin,1.0,temp22,1.0,1.0,temp22b,wr,wi,rswap4,zswap4,ipivot44,civ4,crv4,x,scl,xnorm,ierr); - //--- Scale X to avoid overflow when updating - //--- the right-hand side. - if(xnorm>1.0) - { - beta=MathMax(work[j-1],work[j]); - //--- check - if(beta>bignum/xnorm) - { - rec=1/xnorm; - x[1].Set(1,x[1][1]*rec); - x[1].Set(2,x[1][2]*rec); - x[2].Set(1,x[2][1]*rec); - x[2].Set(2,x[2][2]*rec); - scl=scl*rec; - } - } - //--- Scale if necessary - if(scl!=1.0) - { - for(i_=1+n;i_<=ki+n;i_++) - work[i_]=scl*work[i_]; - for(i_=1+n2;i_<=ki+n2;i_++) - work[i_]=scl*work[i_]; - } - //--- change values - work[j-1+n]=x[1][1]; - work[j+n]=x[2][1]; - work[j-1+n2]=x[1][2]; - work[j+n2]=x[2][2]; - //--- Update the right-hand side - vt=-x[1][1]; - i1_=-n; - for(i_=n+1;i_<=n+j-2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j-1]; - vt=-x[2][1]; - i1_=-n; - for(i_=n+1;i_<=n+j-2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j]; - vt=-x[1][2]; - i1_=-n2; - for(i_=n2+1;i_<=n2+j-2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j-1]; - vt=-x[2][2]; - i1_=-n2; - for(i_=n2+1;i_<=n2+j-2;i_++) - work[i_]=work[i_]+vt*t[i_+i1_][j]; - } - } - //--- Copy the vector x or Q*x to VR and normalize. - if(!over) - { - i1_=n; - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis-1,work[i_+i1_]); - i1_=n2; - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis,work[i_+i1_]); - emax=0; - for(k=1;k<=ki;k++) - emax=MathMax(emax,MathAbs(vr[k][iis-1])+MathAbs(vr[k][iis])); - remax=1/emax; - //--- copy - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis-1,remax*vr[i_][iis-1]); - for(i_=1;i_<=ki;i_++) - vr[i_].Set(iis,remax*vr[i_][iis]); - for(k=ki+1;k<=n;k++) - vr[k].Set(iis-1,0); - vr[k].Set(iis,0); - } - else - { - //--- check - if(ki>2) - { - for(i_=1;i_<=n;i_++) - temp[i_]=vr[i_][ki-1]; - //--- function call - CBlas::MatrixVectorMultiply(vr,1,n,1,ki-2,false,work,1+n,ki-2+n,1.0,temp,1,n,work[ki-1+n]); - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki-1,temp[i_]); - for(i_=1;i_<=n;i_++) - temp[i_]=vr[i_][ki]; - //--- function call - CBlas::MatrixVectorMultiply(vr,1,n,1,ki-2,false,work,1+n2,ki-2+n2,1.0,temp,1,n,work[ki+n2]); - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki,temp[i_]); - } - else - { - vt=work[ki-1+n]; - //--- copy - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki-1,vt*vr[i_][ki-1]); - vt=work[ki+n2]; - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki,vt*vr[i_][ki]); - } - emax=0; - for(k=1;k<=n;k++) - emax=MathMax(emax,MathAbs(vr[k][ki-1])+MathAbs(vr[k][ki])); - remax=1/emax; - //--- copy - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki-1,remax*vr[i_][ki-1]); - for(i_=1;i_<=n;i_++) - vr[i_].Set(ki,remax*vr[i_][ki]); - } - } - iis=iis-1; - //--- check - if(ip!=0) - iis=iis-1; - } - //--- check - if(ip==1) - ip=0; - //--- check - if(ip==-1) - ip=1; - } - } -//--- check - if(leftv) - { - //--- Compute left eigenvectors. - ip=0; - iis=1; - for(ki=1;ki<=n;ki++) - { - skipflag=false; - //--- check - if(ip==-1) - skipflag=true; - else - { - //--- check - if(ki!=n) - { - //--- check - if(t[ki+1][ki]!=0.0) - ip=1; - } - //--- check - if(somev) - { - //--- check - if(!vselect[ki]) - skipflag=true; - } - } - //--- check - if(!skipflag) - { - //--- Compute the KI-th eigenvalue (WR,WI). - wr=t[ki][ki]; - wi=0; - //--- check - if(ip!=0) - wi=MathSqrt(MathAbs(t[ki][ki+1]))*MathSqrt(MathAbs(t[ki+1][ki])); - smin=MathMax(ulp*(MathAbs(wr)+MathAbs(wi)),smlnum); - //--- check - if(ip==0) - { - //--- Real left eigenvector. - work[ki+n]=1; - //--- Form right-hand side - for(k=ki+1;k<=n;k++) - work[k+n]=-t[ki][k]; - //--- Solve the quasi-triangular system: - //--- (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK - vmax=1; - vcrit=bignum; - jnxt=ki+1; - for(j=ki+1;j<=n;j++) - { - //--- check - if(jvcrit) - { - rec=1/vmax; - for(i_=ki+n;i_<=n+n;i_++) - { - work[i_]=rec*work[i_]; - } - vmax=1; - vcrit=bignum; - } - i1_=n; - vt=0.0; - for(i_=ki+1;i_vcrit) - { - rec=1/vmax; - for(i_=ki+n;i_<=n+n;i_++) - work[i_]=rec*work[i_]; - vmax=1; - vcrit=bignum; - } - i1_=n; - vt=0.0; - for(i_=ki+1;i_=MathAbs(t[ki+1][ki])) - { - work[ki+n]=wi/t[ki][ki+1]; - work[ki+1+n2]=1; - } - else - { - work[ki+n]=1; - work[ki+1+n2]=-(wi/t[ki+1][ki]); - } - work[ki+1+n]=0; - work[ki+n2]=0; - //--- Form right-hand side - for(k=ki+2;k<=n;k++) - { - work[k+n]=-(work[ki+n]*t[ki][k]); - work[k+n2]=-(work[ki+1+n2]*t[ki+1][k]); - } - //--- Solve complex quasi-triangular system: - //--- ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2 - vmax=1; - vcrit=bignum; - jnxt=ki+2; - for(j=ki+2;j<=n;j++) - { - //--- check - if(jvcrit) - { - rec=1/vmax; - for(i_=ki+n;i_<=n+n;i_++) - work[i_]=rec*work[i_]; - for(i_=ki+n2;i_<=n+n2;i_++) - work[i_]=rec*work[i_]; - vmax=1; - vcrit=bignum; - } - i1_=n; - vt=0.0; - for(i_=ki+2;i_vcrit) - { - rec=1/vmax; - for(i_=ki+n;i_<=n+n;i_++) - work[i_]=rec*work[i_]; - for(i_=ki+n2;i_<=n+n2;i_++) - work[i_]=rec*work[i_]; - vmax=1; - vcrit=bignum; - } - i1_=n; - vt=0.0; - for(i_=ki+2;i_1.0) - { - //--- check - if(bnorm>bignum*cnorm) - scl=1/bnorm; - } - //--- Compute X - x[1].Set(1,b[1][1]*scl/csr); - xnorm=MathAbs(x[1][1]); - } - else - { - //--- Complex 1x1 system (w is complex) - //--- C = ca A - w D - csr=ca*a[1][1]-wr*d1; - csi=-(wi*d1); - cnorm=MathAbs(csr)+MathAbs(csi); - //--- If | C | < SMINI, use C = SMINI - if(cnorm1.0) - { - //--- check - if(bnorm>bignum*cnorm) - scl=1/bnorm; - } - //--- Compute X - InternalHsEVDLADIV(scl*b[1][1],scl*b[1][2],csr,csi,tmp1,tmp2); - x[1].Set(1,tmp1); - x[1].Set(2,tmp2); - xnorm=MathAbs(x[1][1])+MathAbs(x[1][2]); - } - } - else - { - //--- 2x2 System - //--- Compute the real part of C = ca A - w D (or ca A' - w D ) - crv4[1+0]=ca*a[1][1]-wr*d1; - crv4[2+2]=ca*a[2][2]-wr*d2; - //--- check - if(ltrans) - { - crv4[1+2]=ca*a[2][1]; - crv4[2+0]=ca*a[1][2]; - } - else - { - crv4[2+0]=ca*a[2][1]; - crv4[1+2]=ca*a[1][2]; - } - //--- check - if(nw==1) - { - //--- Real 2x2 system (w is real) - //--- Find the largest element in C - cmax=0; - icmax=0; - for(j=1;j<=4;j++) - { - //--- check - if(MathAbs(crv4[j])>cmax) - { - cmax=MathAbs(crv4[j]); - icmax=j; - } - } - //--- If norm(C) < SMINI, use SMINI*identity. - if(cmax1.0) - { - //--- check - if(bnorm>bignum*smini) - scl=1/bnorm; - } - //--- change values - temp=scl/smini; - x[1].Set(1,temp*b[1][1]); - x[2].Set(1,temp*b[2][1]); - xnorm=temp*bnorm; - info=1; - //--- exit the function - return; - } - //--- Gaussian elimination with complete pivoting. - ur11=crv4[icmax]; - cr21=crv4[ipivot44[2][icmax]]; - ur12=crv4[ipivot44[3][icmax]]; - cr22=crv4[ipivot44[4][icmax]]; - ur11r=1/ur11; - lr21=ur11r*cr21; - ur22=cr22-ur12*lr21; - //--- If smaller pivot < SMINI, use SMINI - if(MathAbs(ur22)1.0 && MathAbs(ur22)<1.0) - { - //--- check - if(bbnd>=bignum*MathAbs(ur22)) - scl=1/bbnd; - } - xr2=br2*scl/ur22; - xr1=scl*br1*ur11r-xr2*(ur11r*ur12); - //--- check - if(zswap4[icmax]) - { - x[1].Set(1,xr2); - x[2].Set(1,xr1); - } - else - { - x[1].Set(1,xr1); - x[2].Set(1,xr2); - } - xnorm=MathMax(MathAbs(xr1),MathAbs(xr2)); - //--- Further scaling if norm(A) norm(X) > overflow - if(xnorm>1.0 && cmax>1.0) - { - //--- check - if(xnorm>bignum/cmax) - { - temp=cmax/bignum; - x[1].Set(1,temp*x[1][1]); - x[2].Set(1,temp*x[2][1]); - xnorm=temp*xnorm; - scl=temp*scl; - } - } - } - else - { - //--- Complex 2x2 system (w is complex) - //--- Find the largest element in C - civ4[1+0]=-(wi*d1); - civ4[2+0]=0; - civ4[1+2]=0; - civ4[2+2]=-(wi*d2); - cmax=0; - icmax=0; - for(j=1;j<=4;j++) - { - //--- check - if(MathAbs(crv4[j])+MathAbs(civ4[j])>cmax) - { - cmax=MathAbs(crv4[j])+MathAbs(civ4[j]); - icmax=j; - } - } - //--- If norm(C) < SMINI, use SMINI*identity. - if(cmax1.0) - { - //--- check - if(bnorm>bignum*smini) - scl=1/bnorm; - } - //--- change values - temp=scl/smini; - x[1].Set(1,temp*b[1][1]); - x[2].Set(1,temp*b[2][1]); - x[1].Set(2,temp*b[1][2]); - x[2].Set(2,temp*b[2][2]); - xnorm=temp*bnorm; - info=1; - //--- exit the function - return; - } - //--- Gaussian elimination with complete pivoting. - ur11=crv4[icmax]; - ui11=civ4[icmax]; - cr21=crv4[ipivot44[2][icmax]]; - ci21=civ4[ipivot44[2][icmax]]; - ur12=crv4[ipivot44[3][icmax]]; - ui12=civ4[ipivot44[3][icmax]]; - cr22=crv4[ipivot44[4][icmax]]; - ci22=civ4[ipivot44[4][icmax]]; - //--- check - if(icmax==1 || icmax==4) - { - //--- Code when off-diagonals of pivoted C are real - if(MathAbs(ur11)>MathAbs(ui11)) - { - temp=ui11/ur11; - ur11r=1/(ur11*(1+CMath::Sqr(temp))); - ui11r=-(temp*ur11r); - } - else - { - temp=ur11/ui11; - ui11r=-(1/(ui11*(1+CMath::Sqr(temp)))); - ur11r=-(temp*ui11r); - } - //--- change values - lr21=cr21*ur11r; - li21=cr21*ui11r; - ur12s=ur12*ur11r; - ui12s=ur12*ui11r; - ur22=cr22-ur12*lr21; - ui22=ci22-ur12*li21; - } - else - { - //--- Code when diagonals of pivoted C are real - ur11r=1/ur11; - ui11r=0; - lr21=cr21*ur11r; - li21=ci21*ur11r; - ur12s=ur12*ur11r; - ui12s=ui12*ur11r; - ur22=cr22-ur12*lr21+ui12*li21; - ui22=-(ur12*li21)-ui12*lr21; - } - u22abs=MathAbs(ur22)+MathAbs(ui22); - //--- If smaller pivot < SMINI, use SMINI - if(u22abs1.0 && u22abs<1.0) - { - //--- check - if(bbnd>=bignum*u22abs) - { - //--- change values - scl=1/bbnd; - br1=scl*br1; - bi1=scl*bi1; - br2=scl*br2; - bi2=scl*bi2; - } - } - //--- function call - InternalHsEVDLADIV(br2,bi2,ur22,ui22,xr2,xi2); - xr1=ur11r*br1-ui11r*bi1-ur12s*xr2+ui12s*xi2; - xi1=ui11r*br1+ur11r*bi1-ui12s*xr2-ur12s*xi2; - //--- check - if(zswap4[icmax]) - { - x[1].Set(1,xr2); - x[2].Set(1,xr1); - x[1].Set(2,xi2); - x[2].Set(2,xi1); - } - else - { - x[1].Set(1,xr1); - x[2].Set(1,xr2); - x[1].Set(2,xi1); - x[2].Set(2,xi2); - } - xnorm=MathMax(MathAbs(xr1)+MathAbs(xi1),MathAbs(xr2)+MathAbs(xi2)); - //--- Further scaling if norm(A) norm(X) > overflow - if(xnorm>1.0 && cmax>1.0) - { - //--- check - if(xnorm>bignum/cmax) - { - //--- change values - temp=cmax/bignum; - x[1].Set(1,temp*x[1][1]); - x[2].Set(1,temp*x[2][1]); - x[1].Set(2,temp*x[1][2]); - x[2].Set(2,temp*x[2][2]); - xnorm=temp*xnorm; - scl=temp*scl; - } - } - } - } - } -//+------------------------------------------------------------------+ -//| performs complex division in real arithmetic | -//| a + i*b | -//| p + i*q = --------- | -//| c + i*d | -//| The algorithm is due to Robert L. Smith and can be found | -//| in D. Knuth, The art of Computer Programming, Vol.2, p.195 | -//| -- LAPACK auxiliary routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1992 | -//+------------------------------------------------------------------+ -static void CEigenVDetect::InternalHsEVDLADIV(const double a,const double b, - const double c,const double d, - double &p,double &q) - { -//--- create variables - double e=0; - double f=0; -//--- initialization - p=0; - q=0; -//--- check - if(MathAbs(d)=0 && vneeded<=3,__FUNCTION__+": incorrect VNeeded!")) - return(false); -//--- check - if(vneeded==0) - { - //--- Eigen values only - ToUpperHessenberg(a,n,tau); - //--- function call - CHsSchur::InternalSchurDecomposition(a,n,0,0,wr,wi,s,info); - //--- get result - result=info==0; - //--- return result - return(result); - } -//--- Eigen values and vectors - ToUpperHessenberg(a,n,tau); -//--- function call - UnpackQFromUpperHessenberg(a,n,tau,s); -//--- function call - CHsSchur::InternalSchurDecomposition(a,n,1,1,wr,wi,s,info); -//--- get result - result=info==0; -//--- check - if(!result) - return(result); -//--- check - if(vneeded==1 || vneeded==3) - { - vr.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - for(i_=1;i_<=n;i_++) - vr[i].Set(i_,s[i][i_]); - } - } -//--- check - if(vneeded==2 || vneeded==3) - { - vl.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - for(i_=1;i_<=n;i_++) - vl[i].Set(i_,s[i][i_]); - } - } -//--- function call - InternalTREVC(a,n,vneeded,1,sel,vl,vr,m,info); -//--- get result - result=info==0; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Upper Hessenberg form | -//+------------------------------------------------------------------+ -static void CEigenVDetect::ToUpperHessenberg(CMatrixDouble &a,const int n,double &tau[]) - { -//--- create variables - int i=0; - int ip1=0; - int nmi=0; - double v=0; - int i_=0; - int i1_=0; -//--- create arrays - double t[]; - double work[]; -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": incorrect N!")) - return; -//--- check - if(n<=1) - return; -//--- allocation - ArrayResizeAL(tau,n); - ArrayResizeAL(t,n+1); - ArrayResizeAL(work,n+1); -//--- calculations - for(i=1;i=1 | -//| OUTPUT PARAMETERS: | -//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] | -//+------------------------------------------------------------------+ -static void CMatGen::RMatrixRndOrthogonal(const int n,CMatrixDouble &a) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - a.Resize(n,n); - for(i=0;i=1&&c>=1.0,__FUNCTION__+": N<1 or C<1!")) - return; -//--- allocation - a.Resize(n,n); -//--- check - if(n==1) - { - a[0].Set(0,2*CMath::RandomInteger(2)-1); - //--- exit the function - return; - } -//--- initialization - l1=0; - l2=MathLog(1/c); - for(i=0;i=1 | -//| OUTPUT PARAMETERS: | -//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] | -//+------------------------------------------------------------------+ -static void CMatGen::CMatrixRndOrthogonal(const int n,CMatrixComplex &a) - { -//--- create variables - int i=0; - int j=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- allocation - a.Resize(n,n); - for(i=0;i=1&&c>=1.0,__FUNCTION__+": N<1 or C<1!")) - return; -//--- allocation - a.Resize(n,n); -//--- check - if(n==1) - { - //--- function call - CHighQualityRand::HQRndRandomize(state); - //--- function call - CHighQualityRand::HQRndUnit2(state,v.re,v.im); - a[0].Set(0,v); - return; - } -//--- initialization - l1=0; - l2=MathLog(1/c); - for(i=0;i=1&&c>=1.0,__FUNCTION__+": N<1 or C<1!")) - return; -//--- allocation - a.Resize(n,n); -//--- check - if(n==1) - { - a[0].Set(0,2*CMath::RandomInteger(2)-1); - return; - } -//--- Prepare matrix - l1=0; - l2=MathLog(1/c); - for(i=0;i=1&&c>=1.0,__FUNCTION__+": N<1 or C<1!")) - return; -//--- allocation - a.Resize(n,n); -//--- check - if(n==1) - { - a[0].Set(0,2*CMath::RandomInteger(2)-1); - return; - } -//--- Prepare matrix - l1=0; - l2=MathLog(1/c); - for(i=0;i=1 && m>=1,__FUNCTION__+": N<1 or M<1!")) - return; -//--- check - if(n==1) - { - tau=2*CMath::RandomInteger(2)-1; - for(i=0;i=1 && m>=1,__FUNCTION__+": N<1 or M<1!")) - return; -//--- check - if(m==1) - { - tau=2*CMath::RandomInteger(2)-1; - for(j=0;j=1 && m>=1,__FUNCTION__+": N<1 or M<1!")) - return; -//--- check - if(n==1) - { - //--- function call - CHighQualityRand::HQRndRandomize(state); - //--- function call - CHighQualityRand::HQRndUnit2(state,tau.re,tau.im); - for(i=0;i=1 && m>=1,__FUNCTION__+": N<1 or M<1!")) - return; -//--- check - if(m==1) - { - //--- function call - CHighQualityRand::HQRndRandomize(state); - //--- function call - CHighQualityRand::HQRndUnit2(state,tau.re,tau.im); - for(j=0;j>N | -//| * worst case - N>>M, small M, large N, matrix does not fit in CPU| -//| cache | -//| INPUT PARAMETERS: | -//| A - array[0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| OUTPUT PARAMETERS: | -//| A - matrices L and U in compact form: | -//| * L is stored under main diagonal | -//| * U is stored on and above main diagonal | -//| Pivots - permutation matrix in compact form. | -//| array[0..Min(M-1,N-1)]. | -//+------------------------------------------------------------------+ -static void CTrFac::RMatrixLU(CMatrixDouble &a,const int m,const int n,int &pivots[]) - { -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- function call - RMatrixPLU(a,m,n,pivots); - } -//+------------------------------------------------------------------+ -//| LU decomposition of a general complex matrix with row pivoting | -//| A is represented as A = P*L*U, where: | -//| * L is lower unitriangular matrix | -//| * U is upper triangular matrix | -//| * P = P0*P1*...*PK, K=min(M,N)-1, | -//| Pi - permutation matrix for I and Pivots[I] | -//| This is cache-oblivous implementation of LU decomposition. It is | -//| optimized for square matrices. As for rectangular matrices: | -//| * best case - M>>N | -//| * worst case - N>>M, small M, large N, matrix does not fit in CPU| -//| cache | -//| INPUT PARAMETERS: | -//| A - array[0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| OUTPUT PARAMETERS: | -//| A - matrices L and U in compact form: | -//| * L is stored under main diagonal | -//| * U is stored on and above main diagonal | -//| Pivots - permutation matrix in compact form. | -//| array[0..Min(M-1,N-1)]. | -//+------------------------------------------------------------------+ -static void CTrFac::CMatrixLU(CMatrixComplex &a,const int m,const int n,int &pivots[]) - { -//--- check - if(!CAp::Assert(m>0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- function call - CMatrixPLU(a,m,n,pivots); - } -//+------------------------------------------------------------------+ -//| Cache-oblivious Cholesky decomposition | -//| The algorithm computes Cholesky decomposition of a Hermitian | -//| positive - definite matrix. The result of an algorithm is a | -//| representation of A as A=U'*U or A=L*L' (here X' detones | -//| conj(X^T)). | -//| INPUT PARAMETERS: | -//| A - upper or lower triangle of a factorized matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - if IsUpper=True, then A contains an upper | -//| triangle of a symmetric matrix, otherwise A | -//| contains a lower one. | -//| OUTPUT PARAMETERS: | -//| A - the result of factorization. If IsUpper=True, | -//| then the upper triangle contains matrix U, so | -//| that A = U'*U, and the elements below the main | -//| diagonal are not modified. Similarly, if | -//| IsUpper = False. | -//| RESULT: | -//| If the matrix is positive-definite, the function returns | -//| True. Otherwise, the function returns False. Contents of A is| -//| not determined in such case. | -//+------------------------------------------------------------------+ -static bool CTrFac::HPDMatrixCholesky(CMatrixComplex &a,const int n,const bool isupper) - { -//--- create array - al_complex tmp[]; -//--- check - if(n<1) - return(false); -//--- return result - return(HPDMatrixCholeskyRec(a,0,n,isupper,tmp)); - } -//+------------------------------------------------------------------+ -//| Cache-oblivious Cholesky decomposition | -//| The algorithm computes Cholesky decomposition of a symmetric | -//| positive - definite matrix. The result of an algorithm is a | -//| representation of A as A=U^T*U or A=L*L^T | -//| INPUT PARAMETERS: | -//| A - upper or lower triangle of a factorized matrix. | -//| array with elements [0..N-1, 0..N-1]. | -//| N - size of matrix A. | -//| IsUpper - if IsUpper=True, then A contains an upper | -//| triangle of a symmetric matrix, otherwise A | -//| contains a lower one. | -//| OUTPUT PARAMETERS: | -//| A - the result of factorization. If IsUpper=True, | -//| then the upper triangle contains matrix U, so | -//| that A = U^T*U, and the elements below the main | -//| diagonal are not modified. Similarly, if | -//| IsUpper = False. | -//| RESULT: | -//| If the matrix is positive-definite, the function returns | -//| True. Otherwise, the function returns False. Contents of A is| -//| not determined in such case. | -//+------------------------------------------------------------------+ -static bool CTrFac::SPDMatrixCholesky(CMatrixDouble &a,const int n,const bool isupper) - { -//--- create array - double tmp[]; -//--- check - if(n<1) - return(false); -//--- return result - return(SPDMatrixCholeskyRec(a,0,n,isupper,tmp)); - } -//+------------------------------------------------------------------+ -//| LUP decomposition of general real matrix | -//+------------------------------------------------------------------+ -static void CTrFac::RMatrixLUP(CMatrixDouble &a,const int m,const int n,int &pivots[]) - { -//--- create variables - int i=0; - int j=0; - double mx=0; - double v=0; - int i_=0; -//--- create array - double tmp[]; -//--- Internal LU decomposition subroutine. -//--- Never call it directly. - if(!CAp::Assert(m>0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- Scale matrix to avoid overflows, -//--- decompose it, then scale back. - mx=0; - for(i=0;i0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- Scale matrix to avoid overflows, -//--- decompose it, then scale back. - mx=0; - for(i=0;i0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- allocation - ArrayResizeAL(tmp,2*MathMax(m,n)); - ArrayResizeAL(pivots,MathMin(m,n)); -//--- Scale matrix to avoid overflows, -//--- decompose it, then scale back. - mx=0; - for(i=0;i0,__FUNCTION__+": incorrect M!")) - return; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": incorrect N!")) - return; -//--- allocation - ArrayResizeAL(tmp,2*MathMax(m,n)); - ArrayResizeAL(pivots,MathMin(m,n)); -//--- Scale matrix to avoid overflows, -//--- decompose it, then scale back. - mx=0; - for(i=0;i0.0) - { - a[offs].Set(offs,MathSqrt(a[offs][offs])); - //--- return result - return(true); - } - else - { - //--- return result - return(false); - } - } -//--- check - if(n<=CAblas::AblasBlockSize()) - { - //--- return result - return(SPDMatrixCholesky2(a,offs,n,isupper,tmp)); - } -//--- general case: split task in cache-oblivious manner - result=true; - CAblas::AblasSplitLength(a,n,n1,n2); - result=SPDMatrixCholeskyRec(a,offs,n1,isupper,tmp); -//--- check - if(!result) - { - //--- return result - return(result); - } -//--- check - if(n2>0) - { - if(isupper) - { - //--- function call - CAblas::RMatrixLeftTrsM(n1,n2,a,offs,offs,isupper,false,1,a,offs,offs+n1); - //--- function call - CAblas::RMatrixSyrk(n2,n1,-1.0,a,offs,offs+n1,1,1.0,a,offs+n1,offs+n1,isupper); - } - else - { - //--- function call - CAblas::RMatrixRightTrsM(n2,n1,a,offs,offs,isupper,false,1,a,offs+n1,offs); - //--- function call - CAblas::RMatrixSyrk(n2,n1,-1.0,a,offs+n1,offs,0,1.0,a,offs+n1,offs+n1,isupper); - } - result=SPDMatrixCholeskyRec(a,offs+n1,n2,isupper,tmp); - //--- check - if(!result) - { - //--- return result - return(result); - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Recurrent complex LU subroutine. | -//| Never call it directly. | -//+------------------------------------------------------------------+ -static void CTrFac::CMatrixLUPRec(CMatrixComplex &a,const int offs,const int m, - const int n,int &pivots[],al_complex &tmp[]) - { -//--- create variables - int i=0; - int m1=0; - int m2=0; - int i_=0; - int i1_=0; - al_complex One(1.0,0.0); - al_complex _One(-1.0,0.0); -//--- Kernel case - if(MathMin(m,n)<=CAblas::AblasComplexBlockSize()) - { - CMatrixLUP2(a,offs,m,n,pivots,tmp); - //--- exit the function - return; - } -//--- Preliminary step, make N>=M -//--- ( A1 ) -//--- A = ( ), where A1 is square -//--- ( A2 ) -//--- Factorize A1, update A2 - if(m>n) - { - //--- function call - CMatrixLUPRec(a,offs,n,n,pivots,tmp); - for(i=0;i0) - { - for(i=0;i=M -//--- ( A1 ) -//--- A = ( ), where A1 is square -//--- ( A2 ) -//--- Factorize A1, update A2 - if(m>n) - { - //--- function call - RMatrixLUPRec(a,offs,n,n,pivots,tmp); - for(i=0;i0) - { - for(i=0;i=N. -//--- A = (A1 A2), where A1 is square -//--- Factorize A1, update A2 - if(n>m) - { - //--- function call - CMatrixPLURec(a,offs,m,m,pivots,tmp); - for(i=0;i0) - { - for(i=0;i=N. -//--- A = (A1 A2), where A1 is square -//--- Factorize A1, update A2 - if(n>m) - { - //--- function call - RMatrixPLURec(a,offs,m,m,pivots,tmp); - for(i=0;i0) - { - for(i=0;iCMath::AbsComplex(a[offs+j][offs+jp])) - jp=i; - } - pivots[offs+j]=offs+jp; - //--- check - if(jp!=j) - { - i1_=offs; - for(i_=0;i_MathAbs(a[offs+j][offs+jp])) - jp=i; - } - pivots[offs+j]=offs+jp; - //--- check - if(jp!=j) - { - i1_=offs; - for(i_=0;i_CMath::AbsComplex(a[offs+jp][offs+j])) - jp=i; - } - pivots[offs+j]=offs+jp; - if(a[offs+jp][offs+j]!=zero) - { - //--- Apply the interchange to rows - if(jp!=j) - { - for(i=0;iMathAbs(a[offs+jp][offs+j])) - jp=i; - } - pivots[offs+j]=offs+jp; - //--- check - if(a[offs+jp][offs+j]!=0.0) - { - //--- Apply the interchange to rows - if(jp!=j) - { - for(i=0;i0.0) - { - a[offs].Set(offs,MathSqrt(a[offs][offs].re)); - result=true; - } - else - { - result=false; - } - //--- return result - return(result); - } -//--- check - if(n<=CAblas::AblasComplexBlockSize()) - { - result=HPDMatrixCholesky2(a,offs,n,isupper,tmp); - //--- return result - return(result); - } -//--- general case: split task in cache-oblivious manner - result=true; -//--- function call - CAblas::AblasComplexSplitLength(a,n,n1,n2); - result=HPDMatrixCholeskyRec(a,offs,n1,isupper,tmp); -//--- check - if(!result) - return(result); -//--- check - if(n2>0) - { - //--- check - if(isupper) - { - //--- function call - CAblas::CMatrixLeftTrsM(n1,n2,a,offs,offs,isupper,false,2,a,offs,offs+n1); - //--- function call - CAblas::CMatrixSyrk(n2,n1,-1.0,a,offs,offs+n1,2,1.0,a,offs+n1,offs+n1,isupper); - } - else - { - //--- function call - CAblas::CMatrixRightTrsM(n2,n1,a,offs,offs,isupper,false,2,a,offs+n1,offs); - //--- function call - CAblas::CMatrixSyrk(n2,n1,-1.0,a,offs+n1,offs,0,1.0,a,offs+n1,offs+n1,isupper); - } - result=HPDMatrixCholeskyRec(a,offs+n1,n2,isupper,tmp); - //--- check - if(!result) - return(result); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Level-2 Hermitian Cholesky subroutine. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee,Univ. of California Berkeley,NAG Ltd., | -//| Courant Institute,Argonne National Lab,and Rice University | -//| February 29,1992 | -//+------------------------------------------------------------------+ -static bool CTrFac::HPDMatrixCholesky2(CMatrixComplex &aaa,const int offs, - const int n,const bool isupper,al_complex &tmp[]) - { -//--- create variables - bool result; - int i=0; - int j=0; - double ajj=0; - al_complex v=0; - al_complex cR; - double r=0; - int i_=0; - int i1_=0; -//--- initialization - result=true; -//--- check - if(n<0) - return(false); -//--- check - if(n==0) - return(result); -//--- check - if(isupper) - { - //--- Compute the Cholesky factorization A = U'*U. - for(j=0;j0) - { - i1_=offs; - for(i_=0;i_0) - { - i1_=offs; - for(i_=0;i_0) - { - i1_=offs; - for(i_=0;i_0) - { - i1_=offs; - for(i_=0;i_=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- allocation - ArrayResizeAL(t,n); -//--- fiiling array - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- change values - nrm=0; - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- allocation - ArrayResizeAL(t,n); -//--- fiiling array - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- change values - nrm=0; - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- allocation - ArrayResizeAL(t,n); -//--- fiiling array - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- change values - nrm=0; - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- function call - CMatrixRCondLUInternal(lua,n,true,false,0.0,v); -//--- return result - return(v); - } -//+------------------------------------------------------------------+ -//| Estimate of the condition number of a matrix given by its LU | -//| decomposition (infinity norm). | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| LUA - LU decomposition of a matrix in compact form. | -//| Output of the CMatrixLU subroutine. | -//| N - size of matrix A. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CRCond::CMatrixLURCondInf(CMatrixComplex &lua,const int n) - { -//--- create a variable - double v=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- function call - CMatrixRCondLUInternal(lua,n,false,false,0.0,v); -//--- return result - return(v); - } -//+------------------------------------------------------------------+ -//| Triangular matrix: estimate of a condition number (1-norm) | -//| The algorithm calculates a lower bound of the condition number. | -//| In this case, the algorithm does not return a lower bound of the | -//| condition number, but an inverse number (to avoid an overflow in | -//| case of a singular matrix). | -//| Input parameters: | -//| A - matrix. Array[0..N-1, 0..N-1]. | -//| N - size of A. | -//| IsUpper - True, if the matrix is upper triangular. | -//| IsUnit - True, if the matrix has a unit diagonal. | -//| Result: 1/LowerBound(cond(A)) | -//| NOTE: | -//| if k(A) is very large, then matrix is assumed degenerate, | -//| k(A)=INF, 0.0 is returned in such cases. | -//+------------------------------------------------------------------+ -static double CRCond::CMatrixTrRCond1(CMatrixComplex &a,const int n, - const bool isupper,const bool isunit) - { -//--- create variables - int i=0; - int j=0; - double v=0; - double nrm=0; - int j1=0; - int j2=0; -//--- create arrays - int pivots[]; - double t[]; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- allocation - ArrayResizeAL(t,n); -//--- fiiling array - for(i=0;i=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- change values - nrm=0; - for(i=0;i0 after this block - if(anorm==0.0) - return; -//--- check - if(n==1) - { - rc=1; - return; - } -//--- Estimate the norm of inv(A). - ainvnm=0; - kase=0; - while(true) - { - //--- function call - RMatrixEstimateNorm(n,ev,ex,iwork,ainvnm,kase); - //--- check - if(kase==0) - break; - //--- from 1-based array to 0-based - for(i=0;i=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - rc=1/ainvnm; - rc=rc/anorm; - //--- check - if(rc=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - rc=1/ainvnm; - rc=rc/anorm; - //--- check - if(rc=1)) - return; -//--- allocation - ArrayResizeAL(tmp,n); -//--- initialization - rc=0; -//--- prepare parameters for triangular solver - maxgrowth=1/RCondThreshold(); - sa=0; -//--- check - if(isupper) - { - for(i=0;i=1;i--) - { - i1_=1; - v=0.0; - for(i_=0;i_=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - v=1/ainvnm; - rc=v/anorm; - //--- check - if(rc=1)) - return; -//--- allocation - ArrayResizeAL(tmp,n); -//--- initialization - rc=0; -//--- prepare parameters for triangular solver - maxgrowth=1/RCondThreshold(); - sa=0; -//--- check - if(isupper) - { - for(i=0;i=1;i--) - { - i1_=1; - v=0.0; - for(i_=0;i_0 - if(anorm==0.0) - return; -//--- check - if(n==1) - { - rc=1; - return; - } -//--- Estimate the norm of inv(A). - ainvnm=0; - kase=0; - while(true) - { - //--- function call - CMatrixEstimateNorm(n,ev,ex,ainvnm,kase,isave,rsave); - //--- check - if(kase==0) - break; - for(i=0;i=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - rc=1/ainvnm; - rc=rc/anorm; - //--- check - if(rc=1;i--) - { - //--- check - if(i>1) - { - i1_=1; - v=0.0; - for(i_=0;i_<=i-2;i_++) - v+=lua[i-1][i_]*ex[i_+i1_]; - } - else - v=0; - ex[i]=ex[i]+v; - } - } - else - { - //--- Multiply by L' - for(i=0;i=1) - { - for(i_=0;i_0 after this block - if(anorm==0.0) - return; -//--- check - if(n==1) - { - rc=1; - return; - } -//--- Estimate the norm of inv(A). - ainvnm=0; - kase=0; - while(true) - { - //--- function call - RMatrixEstimateNorm(n,ev,ex,iwork,ainvnm,kase); - //--- check - if(kase==0) - break; - //--- from 1-based array to 0-based - for(i=0;i=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - rc=1/ainvnm; - rc=rc/anorm; - //--- check - if(rc=1;i--) - { - v=0; - //--- check - if(i>1) - { - i1_=1; - v=0.0; - for(i_=0;i_<=i-2;i_++) - v+=lua[i-1][i_]*ex[i_+i1_]; - } - ex[i]=v+ex[i]; - } - } - else - { - //--- Multiply by L' - for(i=1;i<=n;i++) - cwork2[i]=0; - for(i=1;i<=n;i++) - { - v=ex[i]; - //--- check - if(i>1) - { - i1_=-1; - for(i_=1;i_=0;i--) - ex[i+1]=ex[i]; - } -//--- Compute the estimate of the reciprocal condition number. - if(ainvnm!=0.0) - { - rc=1/ainvnm; - rc=rc/anorm; - //--- check - if(rc=0.0) - x[i]=1; - else - x[i]=-1; - //--- check - if(x[i]>0) - isgn[i]=1; - //--- check - if(x[i]<0) - isgn[i]=-1; - //--- check - if(x[i]==0) - isgn[i]=0; - } - kase=2; - isgn[posjump]=2; - //--- exit the function - return; - } -//--- ................ entry (jump = 2) -//--- first iteration. x has been overwritten by trandpose(a)*x. - if(isgn[posjump]==2) - { - isgn[posj]=1; - for(i=2;i<=n;i++) - { - //--- check - if(MathAbs(x[i])>MathAbs(x[isgn[posj]])) - isgn[posj]=i; - } - isgn[positer]=2; - //--- main loop - iterations 2,3,...,itmax. - for(i=1;i<=n;i++) - x[i]=0; - x[isgn[posj]]=1; - kase=1; - isgn[posjump]=3; - //--- exit the function - return; - } -//--- ................ entry (jump = 3) -//--- x has been overwritten by a*x. - if(isgn[posjump]==3) - { - for(i_=1;i_<=n;i_++) - v[i_]=x[i_]; - v[posestold]=est; - //--- change value - est=0; - for(i=1;i<=n;i++) - est=est+MathAbs(v[i]); - flg=false; - for(i=1;i<=n;i++) - { - if(((x[i]>=0.0)&&(isgn[i]<0))||((x[i]<0.0)&&(isgn[i]>=0))) - flg=true; - } - //--- repeated sign vector detected, hence algorithm has converged. - //--- or may be cycling. - if(!flg || est<=v[posestold]) - { - v[posaltsgn]=1; - for(i=1;i<=n;i++) - { - x[i]=v[posaltsgn]*(1+(double)(i-1)/(double)(n-1)); - v[posaltsgn]=-v[posaltsgn]; - } - kase=1; - isgn[posjump]=5; - //--- exit the function - return; - } - for(i=1;i<=n;i++) - { - //--- check - if(x[i]>=0.0) - { - x[i]=1; - isgn[i]=1; - } - else - { - x[i]=-1; - isgn[i]=-1; - } - } - kase=2; - isgn[posjump]=4; - //--- exit the function - return; - } -//--- ................ entry (jump = 4) -//--- x has been overwritten by trandpose(a)*x. - if(isgn[posjump]==4) - { - isgn[posjlast]=isgn[posj]; - isgn[posj]=1; - for(i=2;i<=n;i++) - { - //--- check - if(MathAbs(x[i])>MathAbs(x[isgn[posj]])) - isgn[posj]=i; - } - //--- check - if(x[isgn[posjlast]]!=MathAbs(x[isgn[posj]]) && isgn[positer]est) - { - for(i_=1;i_<=n;i_++) - v[i_]=x[i_]; - est=v[postemp]; - } - kase=0; - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CRCond::CMatrixEstimateNorm(const int n,al_complex &v[],al_complex &x[], - double &est,int &kase,int &isave[], - double &rsave[]) - { -//--- create variables - int itmax=0; - int i=0; - int iter=0; - int j=0; - int jlast=0; - int jump=0; - double absxi=0; - double altsgn=0; - double estold=0; - double safmin=0; - double temp=0; - int i_=0; -//--- Executable Statements - itmax=5; - safmin=CMath::m_minrealnumber; -//--- check - if(kase==0) - { - //--- allocation - ArrayResizeAL(v,n+1); - ArrayResizeAL(x,n+1); - ArrayResizeAL(isave,5); - ArrayResizeAL(rsave,4); - for(i=1;i<=n;i++) - x[i]=1.0/(double)n; - kase=1; - jump=1; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } -//--- function call - InternalComplexRCondLoadAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); -//--- entry (jump = 1) -//--- first iteration. x has been overwritten by a*x. - if(jump==1) - { - //--- check - if(n==1) - { - v[1]=x[1]; - //--- function call - est=CMath::AbsComplex(v[1]); - kase=0; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } - //--- function call - est=InternalComplexRCondScSum1(x,n); - for(i=1;i<=n;i++) - { - //--- function call - absxi=CMath::AbsComplex(x[i]); - //--- check - if(absxi>safmin) - x[i]=x[i]/absxi; - else - x[i]=1; - } - kase=2; - jump=2; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } -//--- entry (jump = 2) -//--- first iteration. x has been overwritten by ctrans(a)*x. - if(jump==2) - { - j=InternalComplexRCondIcMax1(x,n); - iter=2; - //--- main loop - iterations 2,3,...,itmax. - for(i=1;i<=n;i++) - x[i]=0; - x[j]=1; - kase=1; - jump=3; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } -//--- entry (jump = 3) -//--- x has been overwritten by a*x. - if(jump==3) - { - for(i_=1;i_<=n;i_++) - v[i_]=x[i_]; - estold=est; - //--- function call - est=InternalComplexRCondScSum1(v,n); - //--- test for cycling. - if(est<=estold) - { - //--- iteration complete. final stage. - altsgn=1; - for(i=1;i<=n;i++) - { - x[i]=altsgn*(1+(double)(i-1)/(double)(n-1)); - altsgn=-altsgn; - } - kase=1; - jump=5; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } - for(i=1;i<=n;i++) - { - absxi=CMath::AbsComplex(x[i]); - //--- check - if(absxi>safmin) - x[i]=x[i]/absxi; - else - x[i]=1; - } - kase=2; - jump=4; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } -//--- entry (jump = 4) -//--- x has been overwritten by ctrans(a)*x. - if(jump==4) - { - jlast=j; - j=InternalComplexRCondIcMax1(x,n); - //--- check - if(CMath::AbsComplex(x[jlast])!=CMath::AbsComplex(x[j]) && iterest) - { - for(i_=1;i_<=n;i_++) - v[i_]=x[i_]; - est=temp; - } - kase=0; - //--- function call - InternalComplexRCondSaveAll(isave,rsave,i,iter,j,jlast,jump,absxi,altsgn,estold,temp); - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static double CRCond::InternalComplexRCondScSum1(al_complex &x[],const int n) - { -//--- create variables - double result=0; - int i=0; -//--- get result - for(i=1;i<=n;i++) - result=result+CMath::AbsComplex(x[i]); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static int CRCond::InternalComplexRCondIcMax1(al_complex &x[],const int n) - { -//--- create variables - int result=0; - int i=0; - double m=0; -//--- get result - result=1; - m=CMath::AbsComplex(x[1]); - for(i=2;i<=n;i++) - { - //--- check - if(CMath::AbsComplex(x[i])>m) - { - result=i; - m=CMath::AbsComplex(x[i]); - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CRCond::InternalComplexRCondSaveAll(int &isave[],double &rsave[], - int &i,int &iter,int &j, - int &jlast,int &jump, - double &absxi,double &altsgn, - double &estold,double &temp) - { -//--- copy - isave[0]=i; - isave[1]=iter; - isave[2]=j; - isave[3]=jlast; - isave[4]=jump; -//--- copy - rsave[0]=absxi; - rsave[1]=altsgn; - rsave[2]=estold; - rsave[3]=temp; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CRCond::InternalComplexRCondLoadAll(int &isave[],double &rsave[], - int &i,int &iter,int &j, - int &jlast,int &jump, - double &absxi,double &altsgn, - double &estold,double &temp) - { -//--- get - i=isave[0]; - iter=isave[1]; - j=isave[2]; - jlast=isave[3]; - jump=isave[4]; -//--- get - absxi=rsave[0]; - altsgn=rsave[1]; - estold=rsave[2]; - temp=rsave[3]; - } -//+------------------------------------------------------------------+ -//| Matrix inverse report: | -//| * R1 reciprocal of condition number in 1-norm | -//| * RInf reciprocal of condition number in inf-norm | -//+------------------------------------------------------------------+ -class CMatInvReport - { -public: - double m_r1; - double m_rinf; - //--- constructor, destructor - CMatInvReport(void); - ~CMatInvReport(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMatInvReport::CMatInvReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMatInvReport::~CMatInvReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Matrix inverse report: | -//| * R1 reciprocal of condition number in 1-norm | -//| * RInf reciprocal of condition number in inf-norm | -//+------------------------------------------------------------------+ -class CMatInvReportShell - { -private: - CMatInvReport m_innerobj; -public: - //--- constructors, destructor - CMatInvReportShell(void); - CMatInvReportShell(CMatInvReport &obj); - ~CMatInvReportShell(void); - //--- methods - double GetR1(void); - void SetR1(double r); - double GetRInf(void); - void SetRInf(double r); - CMatInvReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMatInvReportShell::CMatInvReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -CMatInvReportShell::CMatInvReportShell(CMatInvReport &obj) - { - m_innerobj.m_r1=obj.m_r1; - m_innerobj.m_rinf=obj.m_rinf; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMatInvReportShell::~CMatInvReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable r1 | -//+------------------------------------------------------------------+ -double CMatInvReportShell::GetR1(void) - { - return(m_innerobj.m_r1); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable r1 | -//+------------------------------------------------------------------+ -void CMatInvReportShell::SetR1(double r) - { - m_innerobj.m_r1=r; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable rinf | -//+------------------------------------------------------------------+ -double CMatInvReportShell::GetRInf(void) - { - return(m_innerobj.m_rinf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable rint | -//+------------------------------------------------------------------+ -void CMatInvReportShell::SetRInf(double r) - { - m_innerobj.m_rinf=r; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMatInvReport *CMatInvReportShell::GetInnerObj(void) - { - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Inverse matrix | -//+------------------------------------------------------------------+ -class CMatInv - { -private: - //--- private methods - static void RMatrixTrInverseRec(CMatrixDouble &a,const int offs,const int n,const bool isupper,const bool isunit,double &tmp[],int &info,CMatInvReport &rep); - static void CMatrixTrInverseRec(CMatrixComplex &a,const int offs,const int n,const bool isupper,const bool isunit,al_complex &tmp[],int &info,CMatInvReport &rep); - static void RMatrixLUInverseRec(CMatrixDouble &a,const int offs,const int n,double &work[],int &info,CMatInvReport &rep); - static void CMatrixLUInverseRec(CMatrixComplex &a,const int offs,const int n,al_complex &work[],int &info,CMatInvReport &rep); - static void SPDMatrixCholeskyInverseRec(CMatrixDouble &a,const int offs,const int n,const bool isupper,double &tmp[]); - static void HPDMatrixCholeskyInverseRec(CMatrixComplex &a,const int offs,const int n,const bool isupper,al_complex &tmp[]); -public: - CMatInv(void); - ~CMatInv(void); - //--- public methods - static void RMatrixLUInverse(CMatrixDouble &a,int &pivots[],const int n,int &info,CMatInvReport &rep); - static void RMatrixInverse(CMatrixDouble &a,const int n,int &info,CMatInvReport &rep); - static void SPDMatrixCholeskyInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReport &rep); - static void SPDMatrixInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReport &rep); - static void RMatrixTrInverse(CMatrixDouble &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReport &rep); - static void CMatrixLUInverse(CMatrixComplex &a,int &pivots[],const int n,int &info,CMatInvReport &rep); - static void CMatrixInverse(CMatrixComplex &a,const int n,int &info,CMatInvReport &rep); - static void HPDMatrixCholeskyInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReport &rep); - static void HPDMatrixInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReport &rep); - static void CMatrixTrInverse(CMatrixComplex &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReport &rep); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMatInv::CMatInv(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMatInv::~CMatInv(void) - { - - } -//+------------------------------------------------------------------+ -//| Inversion of a matrix given by its LU decomposition. | -//| INPUT PARAMETERS: | -//| A - LU decomposition of the matrix | -//| (output of RMatrixLU subroutine). | -//| Pivots - table of permutations | -//| (the output of RMatrixLU subroutine). | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| OUTPUT PARAMETERS: | -//| Info - return code: | -//| * -3 A is singular, or VERY close to singular.| -//| it is filled by zeros in such cases. | -//| * 1 task is solved (but matrix A may be | -//| ill-conditioned, check R1/RInf parameters| -//| for condition numbers). | -//| Rep - solver report, see below for more info | -//| A - inverse of matrix A. | -//| Array whose indexes range within | -//| [0..N-1, 0..N-1]. | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. | -//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. | -//+------------------------------------------------------------------+ -static void CMatInv::RMatrixLUInverse(CMatrixDouble &a,int &pivots[], - const int n,int &info,CMatInvReport &rep) - { -//--- create variables - int i=0; - int j=0; - int k=0; - double v=0; -//--- create array - double work[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": len(Pivots)n-1 || pivots[i]0,__FUNCTION__+": incorrect Pivots array!")) - return; -//--- calculate condition numbers - rep.m_r1=CRCond::RMatrixLURCond1(a,n); - rep.m_rinf=CRCond::RMatrixLURCondInf(a,n); -//--- check - if(rep.m_r1=0;j--) - { - k=pivots[j]; - v=a[i][j]; - a[i].Set(j,a[i][k]); - a[i].Set(k,v); - } - } - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix. | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//| Result: | -//| True, if the matrix is not singular. | -//| False, if the matrix is singular. | -//+------------------------------------------------------------------+ -static void CMatInv::RMatrixInverse(CMatrixDouble &a,const int n,int &info, - CMatInvReport &rep) - { -//--- create array - int pivots[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": len(Pivots)n-1 || pivots[i]0,__FUNCTION__+": incorrect Pivots array!")) - return; -//--- calculate condition numbers - rep.m_r1=CRCond::CMatrixLURCond1(a,n); - rep.m_rinf=CRCond::CMatrixLURCondInf(a,n); -//--- check - if(rep.m_r1=0;j--) - { - k=pivots[j]; - v=a[i][j]; - a[i].Set(j,a[i][k]); - a[i].Set(k,v); - } - } - } -//+------------------------------------------------------------------+ -//| Inversion of a general matrix. | -//| Input parameters: | -//| A - matrix | -//| N - size of matrix A (optional) : | -//| * if given, only principal NxN submatrix is | -//| processed and overwritten. other elements are | -//| unchanged. | -//| * if not given, size is automatically determined | -//| from matrix size (A must be square matrix) | -//| Output parameters: | -//| Info - return code, same as in RMatrixLUInverse | -//| Rep - solver report, same as in RMatrixLUInverse | -//| A - inverse of matrix A, same as in RMatrixLUInverse | -//+------------------------------------------------------------------+ -static void CMatInv::CMatrixInverse(CMatrixComplex &a,const int n,int &info, - CMatInvReport &rep) - { -//--- create array - int pivots[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(n>0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0,__FUNCTION__+": N<=0!")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(a)>=n,__FUNCTION__+": cols(A)=n,__FUNCTION__+": rows(A)0) - { - i1_=offs; - for(i_=0;i_=0;j--) - { - //--- check - if(!isunit) - { - //--- check - if(a[offs+j][offs+j]==0.0) - { - info=-3; - //--- exit the function - return; - } - a[offs+j].Set(offs+j,1/a[offs+j][offs+j]); - ajj=-a[offs+j][offs+j]; - } - else - ajj=-1; - //--- check - if(jj+1) - { - i1_=-offs; - v=0.0; - for(i_=offs+j+1;i_0) - { - //--- check - if(isupper) - { - for(i=0;i0) - { - i1_=offs; - for(i_=0;i_=0;j--) - { - //--- check - if(!isunit) - { - //--- check - if(a[offs+j][offs+j]==0) - { - info=-3; - //--- exit the function - return; - } - a[offs+j].Set(offs+j,One/a[offs+j][offs+j]); - ajj=-a[offs+j][offs+j]; - } - else - ajj=-1; - //--- check - if(jj+1) - { - i1_=-offs; - v=0.0; - for(i_=offs+j+1;i_0) - { - //--- check - if(isupper) - { - for(i=0;i=0;j--) - { - //--- Copy current column of L to WORK and replace with zeros. - for(i=j+1;i0,__FUNCTION__+": internal error!")) - return; -//--- X :=inv(U1)*U12*inv(U2) - CAblas::RMatrixLeftTrsM(n1,n2,a,offs,offs,true,false,0,a,offs,offs+n1); - CAblas::RMatrixRightTrsM(n1,n2,a,offs+n1,offs+n1,true,false,0,a,offs,offs+n1); -//--- Y :=inv(L2)*L12*inv(L1) - CAblas::RMatrixLeftTrsM(n2,n1,a,offs+n1,offs+n1,false,true,0,a,offs+n1,offs); - CAblas::RMatrixRightTrsM(n2,n1,a,offs,offs,false,true,0,a,offs+n1,offs); -//--- W :=inv(L1*U1)+X*Y - RMatrixLUInverseRec(a,offs,n1,work,info,rep); -//--- check - if(info<=0) - return; -//--- function call - CAblas::RMatrixGemm(n1,n1,n2,1.0,a,offs,offs+n1,0,a,offs+n1,offs,0,1.0,a,offs,offs); -//--- X :=-X*inv(L2) -//--- Y :=-inv(U2)*Y - CAblas::RMatrixRightTrsM(n1,n2,a,offs+n1,offs+n1,false,true,0,a,offs,offs+n1); - for(i=0;i=0;j--) - { - //--- Copy current column of L to WORK and replace with zeros. - for(i=j+1;i0,__FUNCTION__+": internal error!")) - return; -//--- X :=inv(U1)*U12*inv(U2) - CAblas::CMatrixLeftTrsM(n1,n2,a,offs,offs,true,false,0,a,offs,offs+n1); - CAblas::CMatrixRightTrsM(n1,n2,a,offs+n1,offs+n1,true,false,0,a,offs,offs+n1); -//--- Y :=inv(L2)*L12*inv(L1) - CAblas::CMatrixLeftTrsM(n2,n1,a,offs+n1,offs+n1,false,true,0,a,offs+n1,offs); - CAblas::CMatrixRightTrsM(n2,n1,a,offs,offs,false,true,0,a,offs+n1,offs); -//--- W :=inv(L1*U1)+X*Y - CMatrixLUInverseRec(a,offs,n1,work,info,rep); -//--- check - if(info<=0) - return; - CAblas::CMatrixGemm(n1,n1,n2,One,a,offs,offs+n1,0,a,offs+n1,offs,0,One,a,offs,offs); -//--- X :=-X*inv(L2) -//--- Y :=-inv(U2)*Y - CAblas::CMatrixRightTrsM(n1,n2,a,offs+n1,offs+n1,false,true,0,a,offs,offs+n1); - for(i=0;i0, contains matrix U*Q. | -//| VT - if NCVT>0, contains matrix (P^T)*VT. | -//| C - if NCC>0, contains matrix Q'*C. | -//| Result: | -//| True, if the algorithm has converged. | -//| False, if the algorithm hasn't converged (rare case). | -//| Additional information: | -//| The type of convergence is controlled by the internal | -//| parameter TOL. If the parameter is greater than 0, the | -//| singular values will have relative accuracy TOL. If TOL<0, | -//| the singular values will have absolute accuracy | -//| ABS(TOL)*norm(B). By default, |TOL| falls within the range of| -//| 10*Epsilon and 100*Epsilon, where Epsilon is the machine | -//| precision. It is not recommended to use TOL less than | -//| 10*Epsilon since this will considerably slow down the | -//| algorithm and may not lead to error decreasing. | -//| History: | -//| * 31 March, 2007. | -//| changed MAXITR from 6 to 12. | -//| -- LAPACK routine (version 3.0) -- | -//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., | -//| Courant Institute, Argonne National Lab, and Rice University| -//| October 31, 1999. | -//+------------------------------------------------------------------+ -static bool CBdSingValueDecompose::RMatrixBdSVD(double &d[],double &ce[], - const int n,const bool isupper, - const bool isfractionalaccuracyrequired, - CMatrixDouble &u,const int nru, - CMatrixDouble &c,const int ncc, - CMatrixDouble &vt,const int ncvt) - { -//--- create variables - bool result; -//--- create arrays - double d1[]; - double e1[]; - int i_=0; - int i1_=0; -//--- create copy - double e[]; - ArrayCopy(e,ce); -//--- allocation - ArrayResizeAL(d1,n+1); -//--- change values - i1_=-1; - for(i_=1;i_<=n;i_++) - d1[i_]=d[i_+i1_]; -//--- check - if(n>1) - { - //--- allocation - ArrayResizeAL(e1,n); - //--- change values - i1_=-1; - for(i_=1;i_0) - for(i_=vstart;i_<=vstart+ncvt-1;i_++) - vt[vstart].Set(i_,-1*vt[vstart][i_]); - } - //--- return result - return(result); - } -//--- initialization - ll=0; - oldsn=0; -//--- allocation - ArrayResizeAL(work0,n); - ArrayResizeAL(work1,n); - ArrayResizeAL(work2,n); - ArrayResizeAL(work3,n); - uend=ustart+(int)MathMax(nru-1,0); - vend=vstart+(int)MathMax(ncvt-1,0); - cend=cstart+(int)MathMax(ncc-1,0); - ArrayResizeAL(utemp,uend+1); - ArrayResizeAL(vttemp,vend+1); - ArrayResizeAL(ctemp,cend+1); -//--- initialization - maxitr=12; - rightside=true; - fwddir=true; -//--- resize E from N-1 to N - ArrayResizeAL(etemp,n+1); - for(i=1;i0) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(fwddir,ustart,uend,1+ustart-1,n+ustart-1,work0,work1,u,utemp); - } - //--- check - if(ncc>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(fwddir,1+cstart-1,n+cstart-1,cstart,cend,work0,work1,c,ctemp); - } - } -//--- Compute singular values to relative accuracy TOL -//--- (By setting TOL to be negative, algorithm will compute -//--- singular values to absolute accuracy ABS(TOL)*norm(input matrix)) - tolmul=MathMax(10,MathMin(100,MathPow(eps,-0.125))); - tol=tolmul*eps; -//--- check - if(!isfractionalaccuracyrequired) - tol=-tol; -//--- Compute approximate maximum, minimum singular values - smax=0; - for(i=1;i<=n;i++) - smax=MathMax(smax,MathAbs(d[i])); - for(i=1;i=0.0) - { - //--- Relative accuracy desired - sminoa=MathAbs(d[1]); - //--- check - if(sminoa!=0.0) - { - mu=sminoa; - for(i=2;i<=n;i++) - { - mu=MathAbs(d[i])*(mu/(mu+MathAbs(e[i-1]))); - sminoa=MathMin(sminoa,mu); - //--- check - if(sminoa==0.0) - break; - } - } - //--- change values - sminoa=sminoa/MathSqrt(n); - thresh=MathMax(tol*sminoa,maxitr*n*n*unfl); - } - else - { - //--- Absolute accuracy desired - thresh=MathMax(MathAbs(tol)*smax,maxitr*n*n*unfl); - } -//--- Prepare for main iteration loop for the singular values -//--- (MAXIT is the maximum number of passes through the inner -//--- loop permitted before nonconvergence signalled.) - maxit=maxitr*n*n; - iter=0; - oldll=-1; - oldm=-1; -//--- M points to last element of unconverged part of matrix - m=n; -//--- Begin main iteration loop - while(true) - { - //--- Check for convergence or exceeding iteration count - if(m<=1) - break; - //--- check - if(iter>maxit) - return(false); - //--- Find diagonal block of matrix to work on - if(tol<0.0 && MathAbs(d[m])<=thresh) - d[m]=0; - //--- change values - smax=MathAbs(d[m]); - smin=smax; - matrixsplitflag=false; - for(lll=1;lll<=m-1;lll++) - { - ll=m-lll; - abss=MathAbs(d[ll]); - abse=MathAbs(e[ll]); - //--- check - if(tol<0.0 && abss<=thresh) - d[ll]=0; - //--- check - if(abse<=thresh) - { - matrixsplitflag=true; - break; - } - //--- change values - smin=MathMin(smin,abss); - smax=MathMax(smax,MathMax(abss,abse)); - } - //--- check - if(!matrixsplitflag) - ll=0; - else - { - //--- Matrix splits since E(LL) = 0 - e[ll]=0; - //--- check - if(ll==m-1) - { - //--- Convergence of bottom singular value, return to top of loop - m=m-1; - continue; - } - } - ll=ll+1; - //--- E(LL) through E(M-1) are nonzero, E(LL-1) is zero - if(ll==m-1) - { - //--- 2 by 2 block, handle separately - SVDV2x2(d[m-1],e[m-1],d[m],sigmn,sigmx,sinr,cosr,sinl,cosl); - d[m-1]=sigmx; - e[m-1]=0; - d[m]=sigmn; - //--- Compute singular vectors, if desired - if(ncvt>0) - { - mm0=m+(vstart-1); - mm1=m-1+(vstart-1); - //--- swap - for(i_=vstart;i_<=vend;i_++) - vttemp[i_]=cosr*vt[mm1][i_]; - for(i_=vstart;i_<=vend;i_++) - vttemp[i_]=vttemp[i_]+sinr*vt[mm0][i_]; - for(i_=vstart;i_<=vend;i_++) - vt[mm0].Set(i_,cosr*vt[mm0][i_]); - for(i_=vstart;i_<=vend;i_++) - vt[mm0].Set(i_,vt[mm0][i_]-sinr*vt[mm1][i_]); - for(i_=vstart;i_<=vend;i_++) - vt[mm1].Set(i_,vttemp[i_]); - } - //--- check - if(nru>0) - { - mm0=m+ustart-1; - mm1=m-1+ustart-1; - //--- swap - for(i_=ustart;i_<=uend;i_++) - utemp[i_]=cosl*u[i_][mm1]; - for(i_=ustart;i_<=uend;i_++) - utemp[i_]=utemp[i_]+sinl*u[i_][mm0]; - for(i_=ustart;i_<=uend;i_++) - u[i_].Set(mm0,cosl*u[i_][mm0]); - for(i_=ustart;i_<=uend;i_++) - u[i_].Set(mm0,u[i_][mm0]-sinl*u[i_][mm1]); - for(i_=ustart;i_<=uend;i_++) - u[i_].Set(mm1,utemp[i_]); - } - //--- check - if(ncc>0) - { - mm0=m+cstart-1; - mm1=m-1+cstart-1; - //--- swap - for(i_=cstart;i_<=cend;i_++) - ctemp[i_]=cosl*c[mm1][i_]; - for(i_=cstart;i_<=cend;i_++) - ctemp[i_]=ctemp[i_]+sinl*c[mm0][i_]; - for(i_=cstart;i_<=cend;i_++) - c[mm0].Set(i_,cosl*c[mm0][i_]); - for(i_=cstart;i_<=cend;i_++) - c[mm0].Set(i_,c[mm0][i_]-sinl*c[mm1][i_]); - for(i_=cstart;i_<=cend;i_++) - c[mm1].Set(i_,ctemp[i_]); - } - m=m-2; - continue; - } - //--- If working on new submatrix, choose shift direction - //--- (from larger end diagonal element towards smaller) - //--- Previously was - //--- "if (LL>OLDM) or (M - //--- Very strange that LAPACK still contains it. - bchangedir=false; - //--- check - if(idir==1 && MathAbs(d[ll])<1.0E-3*MathAbs(d[m])) - bchangedir=true; - //--- check - if(idir==2 && MathAbs(d[m])<1.0E-3*MathAbs(d[ll])) - bchangedir=true; - //--- check - if(ll!=oldll || m!=oldm || bchangedir) - { - //--- check - if(MathAbs(d[ll])>=MathAbs(d[m])) - { - //--- Chase bulge from top(big end) to bottom(small end) - idir=1; - } - else - { - //--- Chase bulge from bottom (big end) to top (small end) - idir=2; - } - } - //--- Apply convergence tests - if(idir==1) - { - //--- Run convergence test in forward direction - //--- First apply standard test to bottom of matrix - if(MathAbs(e[m-1])<=MathAbs(tol)*MathAbs(d[m]) || (tol<0.0 && MathAbs(e[m-1])<=thresh)) - { - e[m-1]=0; - continue; - } - //--- check - if(tol>=0.0) - { - //--- If relative accuracy desired, - //--- apply convergence criterion forward - mu=MathAbs(d[ll]); - sminl=mu; - iterflag=false; - for(lll=ll;lll<=m-1;lll++) - { - //--- check - if(MathAbs(e[lll])<=tol*mu) - { - e[lll]=0; - iterflag=true; - //--- break the cycle - break; - } - //--- change values - sminlo=sminl; - mu=MathAbs(d[lll+1])*(mu/(mu+MathAbs(e[lll]))); - sminl=MathMin(sminl,mu); - } - //--- check - if(iterflag) - continue; - } - } - else - { - //--- Run convergence test in backward direction - //--- First apply standard test to top of matrix - if(MathAbs(e[ll])<=MathAbs(tol)*MathAbs(d[ll]) || (tol<0.0 && MathAbs(e[ll])<=thresh)) - { - e[ll]=0; - continue; - } - //--- check - if(tol>=0.0) - { - //--- If relative accuracy desired, - //--- apply convergence criterion backward - mu=MathAbs(d[m]); - sminl=mu; - iterflag=false; - for(lll=m-1;lll>=ll;lll--) - { - //--- check - if(MathAbs(e[lll])<=(double)(tol*mu)) - { - e[lll]=0; - iterflag=true; - //--- break the cycle - break; - } - sminlo=sminl; - mu=MathAbs(d[lll])*(mu/(mu+MathAbs(e[lll]))); - sminl=MathMin(sminl,mu); - } - //--- check - if(iterflag) - continue; - } - } - //--- change values - oldll=ll; - oldm=m; - //--- Compute shift. First, test if shifting would ruin relative - //--- accuracy, and if so set the shift to zero. - if(tol>=0.0 && n*tol*(sminl/smax)<=MathMax(eps,0.01*tol)) - { - //--- Use a zero shift to avoid loss of relative accuracy - shift=0; - } - else - { - //--- Compute the shift from 2-by-2 block at end of matrix - if(idir==1) - { - sll=MathAbs(d[ll]); - SVD2x2(d[m-1],e[m-1],d[m],shift,r); - } - else - { - sll=MathAbs(d[m]); - SVD2x2(d[ll],e[ll],d[ll+1],shift,r); - } - //--- Test if shift negligible, and if so set to zero - if(sll>0.0) - { - //--- check - if(CMath::Sqr(shift/sll)ll) - e[i-1]=oldsn*r; - //--- function call - CRotations::GenerateRotation(oldcs*r,d[i+1]*sn,oldcs,oldsn,tmp); - //--- change values - d[i]=tmp; - work0[i-ll+1]=cs; - work1[i-ll+1]=sn; - work2[i-ll+1]=oldcs; - work3[i-ll+1]=oldsn; - } - //--- change values - h=d[m]*cs; - d[m]=h*oldcs; - e[m-1]=h*oldsn; - //--- Update singular vectors - if(ncvt>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(fwddir,ll+vstart-1,m+vstart-1,vstart,vend,work0,work1,vt,vttemp); - } - //--- check - if(nru>0) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(fwddir,ustart,uend,ll+ustart-1,m+ustart-1,work2,work3,u,utemp); - } - //--- check - if(ncc>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(fwddir,ll+cstart-1,m+cstart-1,cstart,cend,work2,work3,c,ctemp); - } - //--- Check for convergence - if(MathAbs(e[m-1])<=thresh) - e[m-1]=0; - } - else - { - //--- Chase bulge from bottom to top - //--- Save cosines and sines for later singular vector updates - cs=1; - oldcs=1; - for(i=m;i>=ll+1;i--) - { - //--- function call - CRotations::GenerateRotation(d[i]*cs,e[i-1],cs,sn,r); - //--- check - if(i0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(!fwddir,ll+vstart-1,m+vstart-1,vstart,vend,work2,work3,vt,vttemp); - } - //--- check - if(nru>0) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(!fwddir,ustart,uend,ll+ustart-1,m+ustart-1,work0,work1,u,utemp); - } - //--- check - if(ncc>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(!fwddir,ll+cstart-1,m+cstart-1,cstart,cend,work0,work1,c,ctemp); - } - //--- Check for convergence - if(MathAbs(e[ll])<=thresh) - e[ll]=0; - } - } - else - { - //--- Use nonzero shift - if(idir==1) - { - //--- Chase bulge from top to bottom - //--- Save cosines and sines for later singular vector updates - f=(MathAbs(d[ll])-shift)*(ExtSignBdSQR(1,d[ll])+shift/d[ll]); - g=e[ll]; - for(i=ll;ill) - e[i-1]=r; - //--- change values - f=cosr*d[i]+sinr*e[i]; - e[i]=cosr*e[i]-sinr*d[i]; - g=sinr*d[i+1]; - d[i+1]=cosr*d[i+1]; - //--- function call - CRotations::GenerateRotation(f,g,cosl,sinl,r); - //--- change values - d[i]=r; - f=cosl*e[i]+sinl*d[i+1]; - d[i+1]=cosl*d[i+1]-sinl*e[i]; - //--- check - if(i0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(fwddir,ll+vstart-1,m+vstart-1,vstart,vend,work0,work1,vt,vttemp); - } - //--- check - if(nru>0) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(fwddir,ustart,uend,ll+ustart-1,m+ustart-1,work2,work3,u,utemp); - } - //--- check - if(ncc>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(fwddir,ll+cstart-1,m+cstart-1,cstart,cend,work2,work3,c,ctemp); - } - //--- Check for convergence - if(MathAbs(e[m-1])<=thresh) - e[m-1]=0; - } - else - { - //--- Chase bulge from bottom to top - //--- Save cosines and sines for later singular vector updates - f=(MathAbs(d[m])-shift)*(ExtSignBdSQR(1,d[m])+shift/d[m]); - g=e[m-1]; - for(i=m;i>=ll+1;i--) - { - //--- function call - CRotations::GenerateRotation(f,g,cosr,sinr,r); - //--- check - if(ill+1) - { - g=sinl*e[i-2]; - e[i-2]=cosl*e[i-2]; - } - //--- change values - work0[i-ll]=cosr; - work1[i-ll]=-sinr; - work2[i-ll]=cosl; - work3[i-ll]=-sinl; - } - e[ll]=f; - //--- Check for convergence - if(MathAbs(e[ll])<=thresh) - e[ll]=0; - //--- Update singular vectors if desired - if(ncvt>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(!fwddir,ll+vstart-1,m+vstart-1,vstart,vend,work2,work3,vt,vttemp); - } - //--- check - if(nru>0) - { - //--- function call - CRotations::ApplyRotationsFromTheRight(!fwddir,ustart,uend,ll+ustart-1,m+ustart-1,work0,work1,u,utemp); - } - //--- check - if(ncc>0) - { - //--- function call - CRotations::ApplyRotationsFromTheLeft(!fwddir,ll+cstart-1,m+cstart-1,cstart,cend,work0,work1,c,ctemp); - } - } - } - //--- QR iteration finished, go back and check convergence - continue; - } -//--- All singular values converged, so make them positive - for(i=1;i<=n;i++) - { - //--- check - if(d[i]<0.0) - { - d[i]=-d[i]; - //--- Change sign of singular vectors, if desired - if(ncvt>0) - { - for(i_=vstart;i_<=vend;i_++) - vt[i+vstart-1].Set(i_,-1*vt[i+vstart-1][i_]); - } - } - } -//--- Sort the singular values into decreasing order (insertion sort on -//--- singular values, but only one transposition per singular vector) - for(i=1;i0) - { - j=n+1-i; - //--- swap - for(i_=vstart;i_<=vend;i_++) - vttemp[i_]=vt[isub+vstart-1][i_]; - for(i_=vstart;i_<=vend;i_++) - vt[isub+vstart-1].Set(i_,vt[j+vstart-1][i_]); - for(i_=vstart;i_<=vend;i_++) - vt[j+vstart-1].Set(i_,vttemp[i_]); - } - if(nru>0) - { - j=n+1-i; - //--- swap - for(i_=ustart;i_<=uend;i_++) - utemp[i_]=u[i_][isub+ustart-1]; - for(i_=ustart;i_<=uend;i_++) - u[i_].Set(isub+ustart-1,u[i_][j+ustart-1]); - for(i_=ustart;i_<=uend;i_++) - u[i_].Set(j+ustart-1,utemp[i_]); - } - //--- check - if(ncc>0) - { - j=n+1-i; - //--- swap - for(i_=cstart;i_<=cend;i_++) - ctemp[i_]=c[isub+cstart-1][i_]; - for(i_=cstart;i_<=cend;i_++) - c[isub+cstart-1].Set(i_,c[j+cstart-1][i_]); - for(i_=cstart;i_<=cend;i_++) - c[j+cstart-1].Set(i_,ctemp[i_]); - } - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static double CBdSingValueDecompose::ExtSignBdSQR(const double a, - const double b) - { -//--- create a variable - double result=0; -//--- check - if(b>=0.0) - result=MathAbs(a); - else - result=-MathAbs(a); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBdSingValueDecompose::SVD2x2(const double f,const double g, - const double h,double &ssmin, - double &ssmax) - { -//--- create variables - double aas=0; - double at=0; - double au=0; - double c=0; - double fa=0; - double fhmn=0; - double fhmx=0; - double ga=0; - double ha=0; -//--- initialization - ssmin=0; - ssmax=0; - fa=MathAbs(f); - ga=MathAbs(g); - ha=MathAbs(h); - fhmn=MathMin(fa,ha); - fhmx=MathMax(fa,ha); -//--- check - if(fhmn==0.0) - { - ssmin=0; - //--- check - if(fhmx==0.0) - ssmax=ga; - else - ssmax=MathMax(fhmx,ga)*MathSqrt(1+CMath::Sqr(MathMin(fhmx,ga)/MathMax(fhmx,ga))); - } - else - { - //--- check - if(gafa; -//--- check - if(swp) - { - //--- Now FA .ge. HA - pmax=3; - temp=ft; - ft=ht; - ht=temp; - temp=fa; - fa=ha; - ha=temp; - } - gt=g; - ga=MathAbs(gt); -//--- check - if(ga==0.0) - { - //--- Diagonal matrix - ssmin=ha; - ssmax=fa; - clt=1; - crt=1; - slt=0; - srt=0; - } - else - { - gasmal=true; - //--- check - if(ga>fa) - { - pmax=2; - //--- check - if(fa/ga1.0) - { - v=ga/ha; - ssmin=fa/v; - } - else - { - v=fa/ga; - ssmin=v*ha; - } - //--- change values - clt=1; - slt=ht/gt; - srt=1; - crt=ft/gt; - } - } - //--- check - if(gasmal) - { - //--- Normal case - d=fa-ha; - //--- check - if(d==fa) - l=1; - else - l=d/fa; - //--- change values - m=gt/ft; - t=2-l; - mm=m*m; - tt=t*t; - s=MathSqrt(tt+mm); - //--- check - if(l==0.0) - r=MathAbs(m); - else - r=MathSqrt(l*l+mm); - //--- change values - a=0.5*(s+r); - ssmin=ha/a; - ssmax=fa*a; - //--- check - if(mm==0.0) - { - //--- Note that M is very tiny - if(l==0.0) - t=ExtSignBdSQR(2,ft)*ExtSignBdSQR(1,gt); - else - t=gt/ExtSignBdSQR(d,ft)+m/t; - } - else - t=(m/(s+t)+m/(r+l))*(1+a); - //--- change values - l=MathSqrt(t*t+4); - crt=2/l; - srt=t/l; - clt=(crt+srt*m)/a; - v=ht/ft; - slt=v*srt/a; - } - } -//--- check - if(swp) - { - csl=srt; - snl=crt; - csr=slt; - snr=clt; - } - else - { - csl=clt; - snl=slt; - csr=crt; - snr=srt; - } -//--- Correct signs of SSMAX and SSMIN - if(pmax==1) - tsign=ExtSignBdSQR(1,csr)*ExtSignBdSQR(1,csl)*ExtSignBdSQR(1,f); -//--- check - if(pmax==2) - tsign=ExtSignBdSQR(1,snr)*ExtSignBdSQR(1,csl)*ExtSignBdSQR(1,g); -//--- check - if(pmax==3) - tsign=ExtSignBdSQR(1,snr)*ExtSignBdSQR(1,snl)*ExtSignBdSQR(1,h); -//--- get result - ssmax=ExtSignBdSQR(ssmax,tsign); - ssmin=ExtSignBdSQR(ssmin,tsign*ExtSignBdSQR(1,f)*ExtSignBdSQR(1,h)); - } -//+------------------------------------------------------------------+ -//| Singular value decomposition | -//+------------------------------------------------------------------+ -class CSingValueDecompose - { -public: - //--- constructor, destructor - CSingValueDecompose(void); - ~CSingValueDecompose(void); - //--- method - static bool RMatrixSVD(CMatrixDouble &ca,const int m,const int n,const int uneeded,const int vtneeded,const int additionalmemory,double &w[],CMatrixDouble &u,CMatrixDouble &vt); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSingValueDecompose::CSingValueDecompose(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSingValueDecompose::~CSingValueDecompose(void) - { - - } -//+------------------------------------------------------------------+ -//| Singular value decomposition of a rectangular matrix. | -//| The algorithm calculates the singular value decomposition of a | -//| matrix of size MxN: A = U * S * V^T | -//| The algorithm finds the singular values and, optionally, matrices| -//| U and V^T. The algorithm can find both first min(M,N) columns of | -//| matrix U and rows of matrix V^T (singular vectors), and matrices | -//| U and V^T wholly (of sizes MxM and NxN respectively). | -//| Take into account that the subroutine does not return matrix V | -//| but V^T. | -//| Input parameters: | -//| A - matrix to be decomposed. | -//| Array whose indexes range within | -//| [0..M-1, 0..N-1]. | -//| M - number of rows in matrix A. | -//| N - number of columns in matrix A. | -//| UNeeded - 0, 1 or 2. See the description of the | -//| parameter U. | -//| VTNeeded - 0, 1 or 2. See the description of the | -//| parameter VT. | -//| AdditionalMemory - | -//| If the parameter: | -//| * equals 0, the algorithm doesn?t use | -//| additional memory (lower requirements, | -//| lower performance). | -//| * equals 1, the algorithm uses additional | -//| memory of size min(M,N)*min(M,N) of real | -//| numbers. It often speeds up the algorithm.| -//| * equals 2, the algorithm uses additional | -//| memory of size M*min(M,N) of real numbers.| -//| It allows to get a maximum performance. | -//| The recommended value of the parameter is 2. | -//| Output parameters: | -//| W - contains singular values in descending order.| -//| U - if UNeeded=0, U isn't changed, the left | -//| singular vectors are not calculated. | -//| if Uneeded=1, U contains left singular | -//| vectors (first min(M,N) columns of matrix U).| -//| Array whose indexes range within | -//| [0..M-1, 0..Min(M,N)-1]. if UNeeded=2, U | -//| contains matrix U wholly. Array whose indexes| -//| range within [0..M-1, 0..M-1]. | -//| VT - if VTNeeded=0, VT isn?t changed, the right | -//| singular vectors are not calculated. | -//| if VTNeeded=1, VT contains right singular | -//| vectors (first min(M,N) rows of matrix V^T). | -//| Array whose indexes range within | -//| [0..min(M,N)-1, 0..N-1]. if VTNeeded=2, VT | -//| contains matrix V^T wholly. Array whose | -//| indexes range within [0..N-1, 0..N-1]. | -//+------------------------------------------------------------------+ -static bool CSingValueDecompose::RMatrixSVD(CMatrixDouble &ca,const int m, - const int n,const int uneeded, - const int vtneeded, - const int additionalmemory, - double &w[],CMatrixDouble &u, - CMatrixDouble &vt) - { -//--- create variables - bool result; - bool isupper; - int minmn=0; - int ncu=0; - int nrvt=0; - int nru=0; - int ncvt=0; - int i=0; - int j=0; -//--- create arrays - double tauq[]; - double taup[]; - double tau[]; - double e[]; - double work[]; -//--- create matrix - CMatrixDouble t2; -//--- create copy - CMatrixDouble a; - a=ca; -//--- initialization - result=true; -//--- check - if(m==0 || n==0) - return(true); -//--- check - if(!CAp::Assert(uneeded>=0 && uneeded<=2,__FUNCTION__+": wrong parameters!")) - return(false); -//--- check - if(!CAp::Assert(vtneeded>=0 && vtneeded<=2,__FUNCTION__+": wrong parameters!")) - return(false); -//--- check - if(!CAp::Assert(additionalmemory>=0 && additionalmemory<=2,__FUNCTION__+": wrong parameters!")) - return(false); -//--- initialization - minmn=MathMin(m,n); - ArrayResizeAL(w,minmn+1); - ncu=0; - nru=0; -//--- check - if(uneeded==1) - { - nru=m; - ncu=minmn; - u.Resize(nru,ncu); - } -//--- check - if(uneeded==2) - { - nru=m; - ncu=m; - u.Resize(nru,ncu); - } - nrvt=0; - ncvt=0; -//--- check - if(vtneeded==1) - { - nrvt=minmn; - ncvt=n; - vt.Resize(nrvt,ncvt); - } -//--- check - if(vtneeded==2) - { - nrvt=n; - ncvt=n; - vt.Resize(nrvt,ncvt); - } -//--- M much larger than N -//--- Use bidiagonal reduction with QR-decomposition - if((double)(m)>(double)(1.6*n)) - { - //--- check - if(uneeded==0) - { - //-- No left singular vectors to be computed - COrtFac::RMatrixQR(a,m,n,tau); - for(i=0;i(double)(1.6*m)) - { - //--- check - if(vtneeded==0) - { - //--- No right singular vectors to be computed - COrtFac::RMatrixLQ(a,m,n,tau); - for(i=0;i<=m-1;i++) - { - for(j=i+1;j<=m-1;j++) - a[i].Set(j,0); - } - //--- function call - COrtFac::RMatrixBD(a,m,m,tauq,taup); - //--- function call - COrtFac::RMatrixBDUnpackQ(a,m,m,tauq,ncu,u); - //--- function call - COrtFac::RMatrixBDUnpackDiagonals(a,m,m,isupper,w,e); - ArrayResizeAL(work,m+1); - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- get result - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,m,isupper,false,a,0,u,nru,vt,0); - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- return result - return(result); - } - else - { - //--- Right singular vectors (may be full matrix VT) to be computed - COrtFac::RMatrixLQ(a,m,n,tau); - //--- function call - COrtFac::RMatrixLQUnpackQ(a,m,n,tau,nrvt,vt); - for(i=0;i<=m-1;i++) - { - for(j=i+1;j<=m-1;j++) - a[i].Set(j,0); - } - //--- function call - COrtFac::RMatrixBD(a,m,m,tauq,taup); - //--- function call - COrtFac::RMatrixBDUnpackQ(a,m,m,tauq,ncu,u); - //--- function call - COrtFac::RMatrixBDUnpackDiagonals(a,m,m,isupper,w,e); - ArrayResizeAL(work,MathMax(m,n)+1); - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- check - if(additionalmemory<1) - { - //--- No additional memory available - COrtFac::RMatrixBDMultiplyByP(a,m,m,taup,vt,m,n,false,true); - //--- get result - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,m,isupper,false,a,0,u,nru,vt,n); - } - else - { - //--- Large VT. Transforming intermediate matrix T2 - COrtFac::RMatrixBDUnpackPT(a,m,m,taup,m,t2); - //--- get result - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,m,isupper,false,a,0,u,nru,t2,m); - //--- function call - CBlas::CopyMatrix(vt,0,m-1,0,n-1,a,0,m-1,0,n-1); - //--- function call - CBlas::MatrixMatrixMultiply(t2,0,m-1,0,m-1,false,a,0,m-1,0,n-1,false,1.0,vt,0,m-1,0,n-1,0.0,work); - } - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- return result - return(result); - } - } -//--- M<=N -//--- We can use inplace transposition of U to get rid of columnwise operations - if(m<=n) - { - //--- function call - COrtFac::RMatrixBD(a,m,n,tauq,taup); - //--- function call - COrtFac::RMatrixBDUnpackQ(a,m,n,tauq,ncu,u); - //--- function call - COrtFac::RMatrixBDUnpackPT(a,m,n,taup,nrvt,vt); - //--- function call - COrtFac::RMatrixBDUnpackDiagonals(a,m,n,isupper,w,e); - ArrayResizeAL(work,m+1); - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- get result - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,minmn,isupper,false,a,0,u,nru,vt,ncvt); - //--- function call - CBlas::InplaceTranspose(u,0,nru-1,0,ncu-1,work); - //--- return result - return(result); - } -//--- Simple bidiagonal reduction - COrtFac::RMatrixBD(a,m,n,tauq,taup); -//--- function call - COrtFac::RMatrixBDUnpackQ(a,m,n,tauq,ncu,u); -//--- function call - COrtFac::RMatrixBDUnpackPT(a,m,n,taup,nrvt,vt); -//--- function call - COrtFac::RMatrixBDUnpackDiagonals(a,m,n,isupper,w,e); -//--- check - if(additionalmemory<2 || uneeded==0) - { - //--- We cant use additional memory or there is no need in such operations - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,minmn,isupper,false,u,nru,a,0,vt,ncvt); - } - else - { - //--- We can use additional memory - t2.Resize(minmn,m); - //--- function call - CBlas::CopyAndTranspose(u,0,m-1,0,minmn-1,t2,0,minmn-1,0,m-1); - //--- get result - result=CBdSingValueDecompose::RMatrixBdSVD(w,e,minmn,isupper,false,u,0,t2,m,vt,ncvt); - //--- function call - CBlas::CopyAndTranspose(t2,0,minmn-1,0,m-1,u,0,m-1,0,minmn-1); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Structure which stores state of linear CG solver between | -//| subsequent calls of FBLSCgIteration(). Initialized with | -//| FBLSCGCreate(). | -//| USAGE: | -//| 1. call to FBLSCGCreate() | -//| 2. F:=FBLSCgIteration(State) | -//| 3. if F is False, iterations are over | -//| 4. otherwise, fill State.AX with A*x, State.XAX with x'*A*x | -//| 5. goto 2 | -//| If you want to rerminate iterations, pass zero or negative value | -//| to XAX. | -//| FIELDS: | -//| E1 - 2-norm of residual at the start | -//| E2 - 2-norm of residual at the end | -//| X - on return from FBLSCgIteration() it contains | -//| vector for matrix-vector product | -//| AX - must be filled with A*x if FBLSCgIteration() | -//| returned True | -//| XAX - must be filled with x'*A*x | -//| XK - contains result (if FBLSCgIteration() returned | -//| False) | -//| Other fields are private and should not be used by outsiders. | -//+------------------------------------------------------------------+ -class CFblsLinCgState - { -public: - //--- variables - double m_e1; - double m_e2; - double m_x[]; - double m_ax[]; - double m_xax; - double m_xk[]; - int m_n; - double m_rk[]; - double m_rk1[]; - double m_xk1[]; - double m_pk[]; - double m_pk1[]; - double m_b[]; - RCommState m_rstate; - double m_tmp2[]; - //--- constructor, destructor - CFblsLinCgState(void); - ~CFblsLinCgState(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFblsLinCgState::CFblsLinCgState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFblsLinCgState::~CFblsLinCgState(void) - { - - } -//+------------------------------------------------------------------+ -//| Fast basic linear solutions | -//+------------------------------------------------------------------+ -class CFbls - { -private: - //--- auxiliary functions for FblsCGiteration - static void Func_lbl_rcomm(CFblsLinCgState &state,int n,int k,double rk2,double rk12,double pap,double s,double betak,double v1,double v2); - static bool Func_lbl_3(CFblsLinCgState &state,int &n,int &k,double &rk2,double &rk12,double &pap,double &s,double &betak,double &v1,double &v2); - static bool Func_lbl_5(CFblsLinCgState &state,int &n,int &k,double &rk2,double &rk12,double &pap,double &s,double &betak,double &v1,double &v2); -public: - //--- constructor, destructor - CFbls(void); - ~CFbls(void); - //--- methods - static void FblsCholeskySolve(CMatrixDouble &cha,const double sqrtscalea,const int n,const bool isupper,double &xb[],double &tmp[]); - static void FblsSolveCGx(CMatrixDouble &a,const int m,const int n,const double alpha,const double &b[],double &x[],double &buf[]); - static void FblsCGCreate(double &x[],double &b[],const int n,CFblsLinCgState &state); - static bool FblsCGIteration(CFblsLinCgState &state); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFbls::CFbls(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFbls::~CFbls(void) - { - - } -//+------------------------------------------------------------------+ -//| Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. | -//| This subroutine assumes that: | -//| * A*ScaleA is well scaled | -//| * A is well-conditioned, so no zero divisions or overflow may | -//| occur | -//| INPUT PARAMETERS: | -//| CHA - Cholesky decomposition of A | -//| SqrtScaleA- square root of scale factor ScaleA | -//| N - matrix size | -//| IsUpper - storage type | -//| XB - right part | -//| Tmp - buffer; function automatically allocates it, if | -//| it is too small. It can be reused if function is | -//| called several times. | -//| OUTPUT PARAMETERS: | -//| XB - solution | -//| NOTES: no assertion or tests are done during algorithm operation | -//+------------------------------------------------------------------+ -static void CFbls::FblsCholeskySolve(CMatrixDouble &cha,const double sqrtscalea, - const int n,const bool isupper,double &xb[], - double &tmp[]) - { -//--- create variables - int i=0; - double v=0; - int i_=0; -//--- check - if(CAp::Len(tmp)=0;i--) - { - //--- check - if(i0) - { - for(i_=0;i_=0;i--) - { - xb[i]=xb[i]/(sqrtscalea*cha[i][i]); - //--- check - if(i>0) - { - v=xb[i]; - for(i_=0;i_0 is a scalar | -//| * I is NxN identity matrix | -//| * b is Nx1 vector | -//| * X is Nx1 unknown vector. | -//| N iterations of linear conjugate gradient are used to solve | -//| problem. | -//| INPUT PARAMETERS: | -//| A - array[M,N], matrix | -//| M - number of rows | -//| N - number of unknowns | -//| B - array[N], right part | -//| X - initial approxumation, array[N] | -//| Buf - buffer; function automatically allocates it, if it | -//| is too small. It can be reused if function is called | -//| several times with same M and N. | -//| OUTPUT PARAMETERS: | -//| X - improved solution | -//| NOTES: | -//| * solver checks quality of improved solution. If (because of | -//| problem condition number, numerical noise, etc.) new solution| -//| is WORSE than original approximation, then original | -//| approximation is returned. | -//| * solver assumes that both A, B, Alpha are well scaled (i.e. | -//| they are less than sqrt(overflow) and greater than | -//| sqrt(underflow)). | -//+------------------------------------------------------------------+ -static void CFbls::FblsSolveCGx(CMatrixDouble &a,const int m,const int n, - const double alpha,const double &b[], - double &x[],double &buf[]) - { -//--- create variables - int k=0; - int offsrk=0; - int offsrk1=0; - int offsxk=0; - int offsxk1=0; - int offspk=0; - int offspk1=0; - int offstmp1=0; - int offstmp2=0; - int bs=0; - double e1=0; - double e2=0; - double rk2=0; - double rk12=0; - double pap=0; - double s=0; - double betak=0; - double v1=0; - double v2=0; - int i_=0; - int i1_=0; -//--- Test for special case: B=0 - v1=0.0; - for(i_=0;i_=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - k=state.m_rstate.ia[1]; - rk2=state.m_rstate.ra[0]; - rk12=state.m_rstate.ra[1]; - pap=state.m_rstate.ra[2]; - s=state.m_rstate.ra[3]; - betak=state.m_rstate.ra[4]; - v1=state.m_rstate.ra[5]; - v2=state.m_rstate.ra[6]; - } - else - { - //--- initialization - n=-983; - k=-989; - rk2=-834; - rk12=900; - pap=-287; - s=364; - betak=214; - v1=-338; - v2=-686; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- copy - for(i_=0;i_n-1) - return(Func_lbl_5(state,n,k,rk2,rk12,pap,s,betak,v1,v2)); -//--- Calculate A*p(k) - store in State.Tmp2 -//--- and p(k)'*A*p(k) - store in PAP -//--- If PAP=0,break (iteration is over) - for(int i_=0;i_=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(pivots)>=n,__FUNCTION__+": Pivots array is too short!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(pivots)>=n,__FUNCTION__+": Pivots array is too short!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)=1,__FUNCTION__+": N<1!")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Rows(a)>=n,__FUNCTION__+": rows(A)=n,__FUNCTION__+": cols(A)0,__FUNCTION__+": N<=0!")) - return(false); -//--- check - if(!CAp::Assert(problemtype==1 || problemtype==2 || problemtype==3,__FUNCTION__+": incorrect ProblemType!")) - return(false); -//--- initialization - result=true; -//--- Problem 1: A*x = lambda*B*x -//--- Reducing to: -//--- C*y = lambda*y -//--- C = L^(-1) * A * L^(-T) -//--- x = L^(-T) * y - if(problemtype==1) - { - //--- Factorize B in T: B = LL' - t.Resize(n,n); - //--- check - if(isupperb) - { - for(i=0;i=0 && updrow=0 && updcolumn=0. | -//| Output parameters: | -//| A - contains matrix T. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//| S - contains Schur vectors. | -//| Array whose indexes range within [0..N-1, 0..N-1]. | -//| Note 1: | -//| The block structure of matrix T can be easily recognized: | -//| since all the elements below the blocks are zeros, the | -//| elements a[i+1,i] which are equal to 0 show the block border.| -//| Note 2: | -//| The algorithm performance depends on the value of the | -//| internal parameter NS of the InternalSchurDecomposition | -//| subroutine which defines the number of shifts in the QR | -//| algorithm (similarly to the block width in block-matrix | -//| algorithms in linear algebra). If you require maximum | -//| performance on your machine, it is recommended to adjust | -//| this parameter manually. | -//| Result: | -//| True, | -//| if the algorithm has converged and parameters A and S | -//| contain the result. | -//| False, | -//| if the algorithm has not converged. | -//| Algorithm implemented on the basis of the DHSEQR subroutine | -//| (LAPACK 3.0 library). | -//+------------------------------------------------------------------+ -static bool CSchur::RMatrixSchur(CMatrixDouble &a,const int n,CMatrixDouble &s) - { -//--- create variables - bool result; - int info=0; - int i=0; - int j=0; -//--- create arrays - double tau[]; - double wi[]; - double wr[]; -//--- create matrix - CMatrixDouble a1; - CMatrixDouble s1; -//--- Upper Hessenberg form of the 0-based matrix - COrtFac::RMatrixHessenberg(a,n,tau); - COrtFac::RMatrixHessenbergUnpackQ(a,n,tau,s); -//--- Convert from 0-based arrays to 1-based, -//--- then call InternalSchurDecomposition -//--- Awkward, of course, but Schur decompisiton subroutine -//--- is too complex to fix it. - a1.Resize(n+1,n+1); - s1.Resize(n+1,n+1); - for(i=1;i<=n;i++) - { - for(j=1;j<=n;j++) - { - a1[i].Set(j,a[i-1][j-1]); - s1[i].Set(j,s[i-1][j-1]); - } - } -//--- function call - CHsSchur::InternalSchurDecomposition(a1,n,1,1,wr,wi,s1,info); - result=info==0; -//--- convert from 1-based arrays to -based - for(i=1;i<=n;i++) - { - for(j=1;j<=n;j++) - { - a[i-1].Set(j-1,a1[i][j]); - s[i-1].Set(j-1,s1[i][j]); - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/matrix.mqh b/Include/Math/Alglib/matrix.mqh deleted file mode 100644 index 02bf07f..0000000 --- a/Include/Math/Alglib/matrix.mqh +++ /dev/null @@ -1,629 +0,0 @@ -//+------------------------------------------------------------------+ -//| matrix.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "complex.mqh" -#include "arrayresize.mqh" -//+------------------------------------------------------------------+ -//| Rows (double) | -//+------------------------------------------------------------------+ -class CRowDouble - { -private: - double m_array[]; - -public: - CRowDouble(void); - ~CRowDouble(void); - //--- methods - int Size(void) const; - void Resize(const int n); - void Set(const int i,const double d); - //--- overloading - double operator[](const int i) const; - void operator=(const double &array[]); - void operator=(const CRowDouble &r); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CRowDouble::CRowDouble(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CRowDouble::~CRowDouble(void) - { - - } -//+------------------------------------------------------------------+ -//| Row size | -//+------------------------------------------------------------------+ -int CRowDouble::Size(void) const - { - return(ArraySize(m_array)); - } -//+------------------------------------------------------------------+ -//| Resize | -//+------------------------------------------------------------------+ -void CRowDouble::Resize(const int n) - { - ArrayResizeAL(m_array,n); - } -//+------------------------------------------------------------------+ -//| Set value | -//+------------------------------------------------------------------+ -void CRowDouble::Set(const int i,const double d) - { - m_array[i]=d; - } -//+------------------------------------------------------------------+ -//| Indexing operator | -//+------------------------------------------------------------------+ -double CRowDouble::operator[](const int i) const - { - return(m_array[i]); - } -//+------------------------------------------------------------------+ -//| Overloading (=) | -//+------------------------------------------------------------------+ -void CRowDouble::operator=(const double &array[]) - { - int size=ArraySize(array); -//--- check - if(size==0) - return; -//--- filling array - ArrayResizeAL(m_array,size); - for(int i=0;i0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGCreate(const int n,double &x[],CMinCGState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N too small!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to | -//| DiffStep*S[I] where S[] is scaling vector which can be set by | -//| MinCGSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. L-BFGS needs | -//| exact gradient values. Imprecise gradient may slow down | -//| convergence, especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping | -//| on small- dimensional problems only, and to implement | -//| analytical gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGCreateF(const int n,double &x[],const double diffstep, - CMinCGState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N too small!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0.0,__FUNCTION__+": DiffStep is non-positive!")) - return; -//--- function call - MinCGInitInternal(n,diffstep,state); -//--- function call - MinCGRestartFrom(state,x); - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for CG optimization | -//| algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by MinCGSetScale()| -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetCond(CMinCGState &state,const double epsg, - const double epsf,double epsx,const int maxits) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsg),__FUNCTION__+": EpsG is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsg>=0.0,__FUNCTION__+": negative EpsG!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsx>=0.0,__FUNCTION__+": negative EpsX!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- check - if(epsg==0.0 && epsf==0.0 && epsx==0.0 && maxits==0) - epsx=1.0E-6; -//--- change values - state.m_epsg=epsg; - state.m_epsf=epsf; - state.m_epsx=epsx; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for CG optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of CG | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the CG too) scaling is NOT a form of | -//| preconditioning. It just affects stopping conditions. You should | -//| set preconditioner by separate call to one of the | -//| MinCGSetPrec...() functions. | -//| There is special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should understand| -//| that scaling is not the same thing as preconditioning - these are| -//| two different, although related forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetScale(CMinCGState &state,double &s[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(s)>=state.m_n,__FUNCTION__+": Length(S)=-1 && cgtype<=1,__FUNCTION__+": incorrect CGType!")) - return; -//--- check - if(cgtype==-1) - cgtype=1; -//--- change value - state.m_cgtype=cgtype; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetStpMax(CMinCGState &state,const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| This function allows to suggest initial step length to the CG | -//| algorithm. | -//| Suggested step length is used as starting point for the line | -//| search. It can be useful when you have badly scaled problem, i.e.| -//| when ||grad|| (which is used as initial estimate for the first | -//| step) is many orders of magnitude different from the desired | -//| step. | -//| Line search may fail on such problems without good estimate of | -//| initial step length. Imagine, for example, problem with | -//| ||grad||=10^50 and desired step equal to 0.1 Line search | -//| function will use 10^50 as initial step, then it will decrease | -//| step length by 2 (up to 20 attempts) and will get 10^44, which is| -//| still too large. | -//| This function allows us to tell than line search should be | -//| started from some moderate step length, like 1.0, so algorithm | -//| will be able to detect desired step length in a several searches.| -//| Default behavior (when no step is suggested) is to use | -//| preconditioner, if it is available, to generate initial estimate | -//| of step length. | -//| This function influences only first iteration of algorithm. It | -//| should be called between MinCGCreate/MinCGRestartFrom() call and | -//| MinCGOptimize call. Suggested step is ignored if you have | -//| preconditioner. | -//| INPUT PARAMETERS: | -//| State - structure used to store algorithm state. | -//| Stp - initial estimate of the step length. | -//| Can be zero (no estimate). | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSuggestStep(CMinCGState &state,const double stp) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stp),__FUNCTION__+": Stp is infinite or NAN")) - return; -//--- check - if(!CAp::Assert(stp>=0.0,__FUNCTION__+": Stp<0")) - return; -//--- change value - state.m_suggestedstep=stp; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: preconditioning is turned | -//| off. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetPrecDefault(CMinCGState &state) - { -//--- change values - state.m_prectype=0; - state.m_innerresetneeded=true; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: diagonal of approximate | -//| Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| D - diagonal of the approximate Hessian, | -//| array[0..N-1], (if larger, only leading N | -//| elements are used). | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//| NOTE 2: D[i] should be positive. Exception will be thrown | -//| otherwise. | -//| NOTE 3: you should pass diagonal of approximate Hessian - NOT | -//| ITS INVERSE. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetPrecDiag(CMinCGState &state,double &d[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(d)>=state.m_n,__FUNCTION__+": D is too short")) - return; - for(i=0;i<=state.m_n-1;i++) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(d[i]),__FUNCTION__+": D contains infinite or NAN elements")) - return; - //--- check - if(!CAp::Assert((double)(d[i])>0.0,__FUNCTION__+": D contains non-positive elements")) - return; - } -//--- function call - MinCGSetPrecDiagFast(state,d); - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, | -//| with H[i] = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinCGSetScale() call (before or after MinCGSetPrecScale() call). | -//| Without knowledge of the scale of your variables scale-based | -//| preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGSetPrecScale(CMinCGState &state) - { -//--- change values - state.m_prectype=3; - state.m_innerresetneeded=true; - } -//+------------------------------------------------------------------+ -//| Conjugate gradient results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * 1 relative function improvement is no | -//| more than EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient norm is no more than EpsG | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible, we return best X found | -//| so far | -//| * 8 terminated by user | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGResults(CMinCGState &state,double &x[],CMinCGReport &rep) - { -//--- reset memory - ArrayResizeAL(x,0); -//--- function call - MinCGResultsBuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| Conjugate gradient results | -//| Buffered implementation of MinCGResults(), which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer.It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGResultsBuf(CMinCGState &state,double &x[],CMinCGReport &rep) - { -//--- create a variable - int i_=0; -//--- check - if(CAp::Len(x)=state.m_n,__FUNCTION__+": Length(X)0 - for(i=0;i<=n-1;i++) - x[i]=x[i]/(state.m_diagh[i]+state.m_diaghl2[i]); -//--- if VCnt>0 - if(vcnt>0) - { - //--- calculation work0 - for(i=0;i<=vcnt-1;i++) - { - v=0.0; - for(i_=0;i_<=n-1;i_++) - v+=state.m_vcorr[i][i_]*x[i_]; - work0[i]=v; - } - //--- calculation work1 - for(i=0;i<=n-1;i++) - work1[i]=0; - for(i=0;i<=vcnt-1;i++) - { - v=work0[i]; - for(i_=0;i_<=n-1;i_++) - state.m_work1[i_]=state.m_work1[i_]+v*state.m_vcorr[i][i_]; - } - //--- change x - for(i=0;i<=n-1;i++) - x[i]=x[i]-state.m_work1[i]/(state.m_diagh[i]+state.m_diaghl2[i]); - } - } -//+------------------------------------------------------------------+ -//| This function calculates preconditioned product x'*H^(-1)*y. | -//| Work0[] and Work1[] are used as temporaries (size must be at | -//| least N; this function doesn't allocate arrays). | -//+------------------------------------------------------------------+ -static double CMinCG::PreconditionedMultiply2(CMinCGState &state,double &x[], - double &y[],double &work0[], - double &work1[]) - { -//--- create variables - double result=0; - int i=0; - int n=0; - int vcnt=0; - double v0=0; - double v1=0; - int i_=0; -//--- initialization - n=state.m_n; - vcnt=state.m_vcnt; -//--- no preconditioning - if(state.m_prectype==0) - { - v0=0.0; - for(i_=0;i_<=n-1;i_++) - v0+=x[i_]*y[i_]; - //--- return result - return(v0); - } -//--- check - if(state.m_prectype==3) - { - result=0; - for(i=0;i<=n-1;i++) - result=result+x[i]*state.m_s[i]*state.m_s[i]*y[i]; - //--- return result - return(result); - } -//--- check - if(!CAp::Assert(state.m_prectype==2,__FUNCTION__+": internal error (unexpected PrecType)")) - return(EMPTY_VALUE); -//--- low rank preconditioning - result=0.0; - for(i=0;i<=n-1;i++) - result=result+x[i]*y[i]/(state.m_diagh[i]+state.m_diaghl2[i]); -//--- check - if(vcnt>0) - { - //--- prepare arrays - for(i=0;i<=n-1;i++) - { - work0[i]=x[i]/(state.m_diagh[i]+state.m_diaghl2[i]); - work1[i]=y[i]/(state.m_diagh[i]+state.m_diaghl2[i]); - } - for(i=0;i<=vcnt-1;i++) - { - //--- calculation - v0=0.0; - for(i_=0;i_<=n-1;i_++) - v0+=work0[i_]*state.m_vcorr[i][i_]; - v1=0.0; - for(i_=0;i_<=n-1;i_++) - v1+=work1[i_]*state.m_vcorr[i][i_]; - //--- get result - result=result-v0*v1; - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Internal initialization subroutine | -//+------------------------------------------------------------------+ -static void CMinCG::MinCGInitInternal(const int n,const double diffstep, - CMinCGState &state) - { -//--- create a variable - int i=0; -//--- initialization - state.m_n=n; - state.m_diffstep=diffstep; -//--- function call - MinCGSetCond(state,0,0,0,0); -//--- function call - MinCGSetXRep(state,false); -//--- function call - MinCGSetDRep(state,false); -//--- function call - MinCGSetStpMax(state,0); -//--- function call - MinCGSetCGType(state,-1); -//--- function call - MinCGSetPrecDefault(state); -//--- allocation - ArrayResizeAL(state.m_xk,n); - ArrayResizeAL(state.m_dk,n); - ArrayResizeAL(state.m_xn,n); - ArrayResizeAL(state.m_dn,n); - ArrayResizeAL(state.m_x,n); - ArrayResizeAL(state.m_d,n); - ArrayResizeAL(state.m_g,n); - ArrayResizeAL(state.m_work0,n); - ArrayResizeAL(state.m_work1,n); - ArrayResizeAL(state.m_yk,n); - ArrayResizeAL(state.m_s,n); -//--- copy - for(i=0;i<=n-1;i++) - state.m_s[i]=1.0; - } -//+------------------------------------------------------------------+ -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which| -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinCGCreate() for analytical gradient or | -//| MinCGCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinCGOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinCGOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinCGOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinCGOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinCGCreateF() | work FAIL | -//| MinCGCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinCGOptimize() version. Attemps to use | -//| such combination (for example, to create optimizer with | -//| MinCGCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static bool CMinCG::MinCGIteration(CMinCGState &state) - { -//--- create variables - int n=0; - int i=0; - double betak=0; - double v=0; - double vv=0; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - i=state.m_rstate.ia[1]; - betak=state.m_rstate.ra[0]; - v=state.m_rstate.ra[1]; - vv=state.m_rstate.ra[2]; - } - else - { - //--- initialization - n=-983; - i=-989; - betak=-834; - v=900; - vv=-287; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needfg=false; - //--- function call, return result - return(Func_lbl_18(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change values - state.m_fbase=state.m_f; - i=0; - //--- function call, return result - return(Func_lbl_19(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change values - state.m_fm2=state.m_f; - state.m_x[i]=v-0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=3; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change values - state.m_fm1=state.m_f; - state.m_x[i]=v+0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=4; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change values - state.m_fp1=state.m_f; - state.m_x[i]=v+state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=5; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change values - state.m_fp2=state.m_f; - state.m_x[i]=v; - state.m_g[i]=(8*(state.m_fp1-state.m_fm1)-(state.m_fp2-state.m_fm2))/(6*state.m_diffstep*state.m_s[i]); - i=i+1; - //--- function call, return result - return(Func_lbl_19(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change value - state.m_algpowerup=false; - //--- function call, return result - return(Func_lbl_22(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==7) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_24(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==8) - { - //--- change value - state.m_lsstart=false; - //--- function call, return result - return(Func_lbl_28(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==9) - { - //--- change value - state.m_needfg=false; - //--- function call, return result - return(Func_lbl_33(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==10) - { - //--- change values - state.m_fbase=state.m_f; - i=0; - //--- function call, return result - return(Func_lbl_34(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==11) - { - //--- change values - state.m_fm2=state.m_f; - state.m_x[i]=v-0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=12; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==12) - { - //--- change values - state.m_fm1=state.m_f; - state.m_x[i]=v+0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=13; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==13) - { - //--- change values - state.m_fp1=state.m_f; - state.m_x[i]=v+state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=14; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - return(true); - } -//--- check - if(state.m_rstate.stage==14) - { - //--- change values - state.m_fp2=state.m_f; - state.m_x[i]=v; - state.m_g[i]=(8*(state.m_fp1-state.m_fm1)-(state.m_fp2-state.m_fm2))/(6*state.m_diffstep*state.m_s[i]); - i=i+1; - //--- function call, return result - return(Func_lbl_34(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==15) - { - //--- change value - state.m_lsend=false; - //--- function call, return result - return(Func_lbl_37(state,n,i,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==16) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_39(state,n,i,betak,v,vv)); - } -//--- Routine body -//--- Prepare - n=state.m_n; - state.m_repterminationtype=0; - state.m_repiterationscount=0; - state.m_repnfev=0; - state.m_debugrestartscount=0; -//--- Preparations continue: -//--- * set XK -//--- * calculate F/G -//--- * set DK to -G -//--- * powerup algo (it may change preconditioner) -//--- * apply preconditioner to DK -//--- * report update of X -//--- * check stopping conditions for G - for(i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_x[i_]; -//--- change value - state.m_terminationneeded=false; -//--- function call - ClearRequestFields(state); -//--- check - if(state.m_diffstep!=0.0) - { - state.m_needf=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CMinCG::Func_lbl_rcomm(CMinCGState &state,int n,int i, - double betak,double v,double vv) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=i; - state.m_rstate.ra[0]=betak; - state.m_rstate.ra[1]=v; - state.m_rstate.ra[2]=vv; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_18(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(!state.m_drep) - return(Func_lbl_22(state,n,i,betak,v,vv)); -//--- Report algorithm powerup (if needed) - ClearRequestFields(state); -//--- change values - state.m_algpowerup=true; - state.m_rstate.stage=6; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_19(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(i>n-1) - { - state.m_f=state.m_fbase; - state.m_needf=false; - //--- function call, return result - return(Func_lbl_18(state,n,i,betak,v,vv)); - } -//--- change values - v=state.m_x[i]; - state.m_x[i]=v-state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_22(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- function call - COptServ::TrimPrepare(state.m_f,state.m_trimthreshold); - for(int i_=0;i_<=n-1;i_++) - state.m_dk[i_]=-state.m_g[i_]; -//--- function call - PreconditionedMultiply(state,state.m_dk,state.m_work0,state.m_work1); -//--- check - if(!state.m_xrep) - return(Func_lbl_24(state,n,i,betak,v,vv)); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=7; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_24(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(state.m_terminationneeded) - { - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_xk[i_]; - state.m_repterminationtype=8; - //--- return result - return(false); - } -//--- change value - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_g[i]*state.m_s[i]); -//--- check - if(MathSqrt(v)<=state.m_epsg) - { - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_xk[i_]; - state.m_repterminationtype=4; - //--- return result - return(false); - } -//--- change values - state.m_repnfev=1; - state.m_k=0; - state.m_fold=state.m_f; -//--- Choose initial step. -//--- Apply preconditioner,if we have something other than default. - if(state.m_prectype==2||state.m_prectype==3) - { - //--- because we use preconditioner,step length must be equal - //--- to the norm of DK - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_dk[i_]*state.m_dk[i_]; - state.m_laststep=MathSqrt(v); - } - else - { - //--- No preconditioner is used,we try to use suggested step - if(state.m_suggestedstep>0.0) - state.m_laststep=state.m_suggestedstep; - else - { - //--- change value - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_g[i_]*state.m_g[i_]; - v=MathSqrt(v); - //--- check - if(state.m_stpmax==0.0) - state.m_laststep=MathMin(1.0/v,1); - else - state.m_laststep=MathMin(1.0/v,state.m_stpmax); - } - } -//--- Main cycle - state.m_rstimer=m_rscountdownlen; -//--- function call, return result - return(Func_lbl_26(state,n,i,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_26(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- * clear reset flag -//--- * clear termination flag -//--- * store G[k] for later calculation of Y[k] -//--- * prepare starting point and direction and step length for line search - state.m_innerresetneeded=false; - state.m_terminationneeded=false; - for(int i_=0;i_<=n-1;i_++) - state.m_yk[i_]=-state.m_g[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_d[i_]=state.m_dk[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xk[i_]; -//--- change values - state.m_mcstage=0; - state.m_stp=1.0; -//--- function call - CLinMin::LinMinNormalized(state.m_d,state.m_stp,n); -//--- check - if(state.m_laststep!=0.0) - state.m_stp=state.m_laststep; - state.m_curstpmax=state.m_stpmax; -//--- Report beginning of line search (if needed) -//--- Terminate algorithm,if user request was detected - if(!state.m_drep) - return(Func_lbl_28(state,n,i,betak,v,vv)); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_lsstart=true; - state.m_rstate.stage=8; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_28(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(state.m_terminationneeded) - { - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; - state.m_repterminationtype=8; - //--- return result - return(false); - } -//--- Minimization along D - CLinMin::MCSrch(n,state.m_x,state.m_f,state.m_g,state.m_d,state.m_stp,state.m_curstpmax,m_gtol,state.m_mcinfo,state.m_nfev,state.m_work0,state.m_lstate,state.m_mcstage); -//--- function call, return result - return(Func_lbl_30(state,n,i,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_30(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(state.m_mcstage==0) - return(Func_lbl_31(state,n,i,betak,v,vv)); -//--- Calculate function/gradient using either -//--- analytical gradient supplied by user -//--- or finite difference approximation. -//--- "Trim" function in order to handle near-singularity points. - ClearRequestFields(state); -//--- check - if((double)(state.m_diffstep)!=0.0) - { - state.m_needf=true; - state.m_rstate.stage=10; - //--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=9; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_31(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- * report end of line search -//--- * store current point to XN -//--- * report iteration -//--- * terminate algorithm if user request was detected - if(!state.m_drep) - return(Func_lbl_37(state,n,i,betak,v,vv)); -//--- Report end of line search (if needed) - ClearRequestFields(state); -//--- change values - state.m_lsend=true; - state.m_rstate.stage=15; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_33(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- function call - COptServ::TrimFunction(state.m_f,state.m_g,n,state.m_trimthreshold); -//--- Call MCSRCH again - CLinMin::MCSrch(n,state.m_x,state.m_f,state.m_g,state.m_d,state.m_stp,state.m_curstpmax,m_gtol,state.m_mcinfo,state.m_nfev,state.m_work0,state.m_lstate,state.m_mcstage); -//--- function call, return result - return(Func_lbl_30(state,n,i,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_34(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(i>n-1) - { - state.m_f=state.m_fbase; - state.m_needf=false; - //--- function call, return result - return(Func_lbl_33(state,n,i,betak,v,vv)); - } -//--- change values - v=state.m_x[i]; - state.m_x[i]=v-state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=11; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_37(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; -//--- check - if(!state.m_xrep) - return(Func_lbl_39(state,n,i,betak,v,vv)); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=16; -//--- Saving state - Func_lbl_rcomm(state,n,i,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinCGIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinCG::Func_lbl_39(CMinCGState &state,int &n,int &i, - double &betak,double &v,double &vv) - { -//--- check - if(state.m_terminationneeded) - { - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; - state.m_repterminationtype=8; - //--- return result - return(false); - } -//--- Line search is finished. -//--- * calculate BetaK -//--- * calculate DN -//--- * update timers -//--- * calculate step length - if(state.m_mcinfo==1 && !state.m_innerresetneeded) - { - //--- Standard Wolfe conditions hold - //--- Calculate Y[K] and D[K]'*Y[K] - for(int i_=0;i_<=n-1;i_++) - state.m_yk[i_]=state.m_yk[i_]+state.m_g[i_]; - //--- change value - vv=0.0; - for(int i_=0;i_<=n-1;i_++) - vv+=state.m_yk[i_]*state.m_dk[i_]; - //--- Calculate BetaK according to DY formula - v=PreconditionedMultiply2(state,state.m_g,state.m_g,state.m_work0,state.m_work1); - state.m_betady=v/vv; - //--- Calculate BetaK according to HS formula - v=PreconditionedMultiply2(state,state.m_g,state.m_yk,state.m_work0,state.m_work1); - state.m_betahs=v/vv; - //--- Choose BetaK - if(state.m_cgtype==0) - betak=state.m_betady; - //--- check - if(state.m_cgtype==1) - betak=MathMax(0,MathMin(state.m_betady,state.m_betahs)); - } - else - { - //--- Something is wrong (may be function is too wild or too flat) - //--- or we just have to restart algo. - //--- We'll set BetaK=0,which will restart CG algorithm. - //--- We can stop later (during normal checks) if stopping conditions are met. - betak=0; - state.m_debugrestartscount=state.m_debugrestartscount+1; - } -//--- check - if(state.m_repiterationscount>0&&state.m_repiterationscount%(3+n)==0) - { - //--- clear Beta every N iterations - betak=0; - } -//--- check - if(state.m_mcinfo==1||state.m_mcinfo==5) - state.m_rstimer=m_rscountdownlen; - else - state.m_rstimer=state.m_rstimer-1; - for(int i_=0;i_<=n-1;i_++) - state.m_dn[i_]=-state.m_g[i_]; -//--- function call - PreconditionedMultiply(state,state.m_dn,state.m_work0,state.m_work1); - for(int i_=0;i_<=n-1;i_++) - state.m_dn[i_]=state.m_dn[i_]+betak*state.m_dk[i_]; -//--- change values - state.m_laststep=0; - state.m_lastscaledstep=0.0; - for(i=0;i<=n-1;i++) - { - state.m_laststep=state.m_laststep+CMath::Sqr(state.m_d[i]); - state.m_lastscaledstep=state.m_lastscaledstep+CMath::Sqr(state.m_d[i]/state.m_s[i]); - } -//--- change values - state.m_laststep=state.m_stp*MathSqrt(state.m_laststep); - state.m_lastscaledstep=state.m_stp*MathSqrt(state.m_lastscaledstep); -//--- Update information. -//--- Check stopping conditions. - state.m_repnfev=state.m_repnfev+state.m_nfev; - state.m_repiterationscount=state.m_repiterationscount+1; -//--- check - if(state.m_repiterationscount>=state.m_maxits&&state.m_maxits>0) - { - //--- Too many iterations - state.m_repterminationtype=5; - //--- return result - return(false); - } -//--- change value - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_g[i]*state.m_s[i]); -//--- check - if(MathSqrt(v)<=state.m_epsg) - { - //--- Gradient is small enough - state.m_repterminationtype=4; - //--- return result - return(false); - } -//--- check - if(!state.m_innerresetneeded) - { - //--- These conditions are checked only when no inner reset was requested by user - if(state.m_fold-state.m_f<=state.m_epsf*MathMax(MathAbs(state.m_fold),MathMax(MathAbs(state.m_f),1.0))) - { - //--- F(k+1)-F(k) is small enough - state.m_repterminationtype=1; - //--- return result - return(false); - } - //--- check - if(state.m_lastscaledstep<=state.m_epsx) - { - //--- X(k+1)-X(k) is small enough - state.m_repterminationtype=2; - //--- return result - return(false); - } - } -//--- check - if(state.m_rstimer<=0) - { - //--- Too many subsequent restarts - state.m_repterminationtype=7; - //--- return result - return(false); - } -//--- Shift Xk/Dk,update other information - for(int i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_xn[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_dk[i_]=state.m_dn[i_]; -//--- change values - state.m_fold=state.m_f; - state.m_k=state.m_k+1; -//--- function call, return result - return(Func_lbl_26(state,n,i,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| This object stores nonlinear optimizer state. | -//| You should use functions provided by MinBLEIC subpackage to work | -//| with this object | -//+------------------------------------------------------------------+ -class CMinBLEICState - { -public: - //--- variables - int m_nmain; - int m_nslack; - double m_innerepsg; - double m_innerepsf; - double m_innerepsx; - double m_outerepsx; - double m_outerepsi; - int m_maxits; - bool m_xrep; - double m_stpmax; - double m_diffstep; - int m_prectype; - double m_f; - bool m_needf; - bool m_needfg; - bool m_xupdated; - RCommState m_rstate; - int m_repinneriterationscount; - int m_repouteriterationscount; - int m_repnfev; - int m_repterminationtype; - double m_repdebugeqerr; - double m_repdebugfs; - double m_repdebugff; - double m_repdebugdx; - int m_itsleft; - double m_trimthreshold; - int m_cecnt; - int m_cedim; - double m_v0; - double m_v1; - double m_v2; - double m_t; - double m_errfeas; - double m_gnorm; - double m_mpgnorm; - double m_mba; - int m_variabletofreeze; - double m_valuetofreeze; - double m_fbase; - double m_fm2; - double m_fm1; - double m_fp1; - double m_fp2; - double m_xm1; - double m_xp1; - CMinCGState m_cgstate; - CMinCGReport m_cgrep; - int m_optdim; - //--- arrays - double m_diaghoriginal[]; - double m_diagh[]; - double m_x[]; - double m_g[]; - double m_xcur[]; - double m_xprev[]; - double m_xstart[]; - double m_xend[]; - double m_lastg[]; - int m_ct[]; - double m_xe[]; - bool m_hasbndl[]; - bool m_hasbndu[]; - double m_bndloriginal[]; - double m_bnduoriginal[]; - double m_bndleffective[]; - double m_bndueffective[]; - bool m_activeconstraints[]; - double m_constrainedvalues[]; - double m_transforms[]; - double m_seffective[]; - double m_soriginal[]; - double m_w[]; - double m_tmp0[]; - double m_tmp1[]; - double m_tmp2[]; - double m_r[]; - //--- matrix - CMatrixDouble m_ceoriginal; - CMatrixDouble m_ceeffective; - CMatrixDouble m_cecurrent; - CMatrixDouble m_lmmatrix; - //--- constructor, destructor - CMinBLEICState(void); - ~CMinBLEICState(void); - //--- copy - void Copy(CMinBLEICState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinBLEICState::CMinBLEICState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinBLEICState::~CMinBLEICState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinBLEICState::Copy(CMinBLEICState &obj) - { -//--- copy variables - m_nmain=obj.m_nmain; - m_nslack=obj.m_nslack; - m_innerepsg=obj.m_innerepsg; - m_innerepsf=obj.m_innerepsf; - m_innerepsx=obj.m_innerepsx; - m_outerepsx=obj.m_outerepsx; - m_outerepsi=obj.m_outerepsi; - m_maxits=obj.m_maxits; - m_xrep=obj.m_xrep; - m_stpmax=obj.m_stpmax; - m_diffstep=obj.m_diffstep; - m_prectype=obj.m_prectype; - m_f=obj.m_f; - m_needf=obj.m_needf; - m_needfg=obj.m_needfg; - m_xupdated=obj.m_xupdated; - m_repinneriterationscount=obj.m_repinneriterationscount; - m_repouteriterationscount=obj.m_repouteriterationscount; - m_repnfev=obj.m_repnfev; - m_repterminationtype=obj.m_repterminationtype; - m_repdebugeqerr=obj.m_repdebugeqerr; - m_repdebugfs=obj.m_repdebugfs; - m_repdebugff=obj.m_repdebugff; - m_repdebugdx=obj.m_repdebugdx; - m_itsleft=obj.m_itsleft; - m_trimthreshold=obj.m_trimthreshold; - m_cecnt=obj.m_cecnt; - m_cedim=obj.m_cedim; - m_v0=obj.m_v0; - m_v1=obj.m_v1; - m_v2=obj.m_v2; - m_t=obj.m_t; - m_errfeas=obj.m_errfeas; - m_gnorm=obj.m_gnorm; - m_mpgnorm=obj.m_mpgnorm; - m_mba=obj.m_mba; - m_variabletofreeze=obj.m_variabletofreeze; - m_valuetofreeze=obj.m_valuetofreeze; - m_fbase=obj.m_fbase; - m_fm2=obj.m_fm2; - m_fm1=obj.m_fm1; - m_fp1=obj.m_fp1; - m_fp2=obj.m_fp2; - m_xm1=obj.m_xm1; - m_xp1=obj.m_xp1; - m_optdim=obj.m_optdim; - m_rstate.Copy(obj.m_rstate); - m_cgstate.Copy(obj.m_cgstate); - m_cgrep.Copy(obj.m_cgrep); -//--- copy arrays - ArrayCopy(m_diaghoriginal,obj.m_diaghoriginal); - ArrayCopy(m_diagh,obj.m_diagh); - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_g,obj.m_g); - ArrayCopy(m_xcur,obj.m_xcur); - ArrayCopy(m_xprev,obj.m_xprev); - ArrayCopy(m_xstart,obj.m_xstart); - ArrayCopy(m_xend,obj.m_xend); - ArrayCopy(m_lastg,obj.m_lastg); - ArrayCopy(m_ct,obj.m_ct); - ArrayCopy(m_xe,obj.m_xe); - ArrayCopy(m_hasbndl,obj.m_hasbndl); - ArrayCopy(m_hasbndu,obj.m_hasbndu); - ArrayCopy(m_bndloriginal,obj.m_bndloriginal); - ArrayCopy(m_bnduoriginal,obj.m_bnduoriginal); - ArrayCopy(m_bndleffective,obj.m_bndleffective); - ArrayCopy(m_bndueffective,obj.m_bndueffective); - ArrayCopy(m_activeconstraints,obj.m_activeconstraints); - ArrayCopy(m_constrainedvalues,obj.m_constrainedvalues); - ArrayCopy(m_transforms,obj.m_transforms); - ArrayCopy(m_seffective,obj.m_seffective); - ArrayCopy(m_soriginal,obj.m_soriginal); - ArrayCopy(m_w,obj.m_w); - ArrayCopy(m_tmp0,obj.m_tmp0); - ArrayCopy(m_tmp1,obj.m_tmp1); - ArrayCopy(m_tmp2,obj.m_tmp2); - ArrayCopy(m_r,obj.m_r); -//--- copy matrix - m_ceoriginal=obj.m_ceoriginal; - m_ceeffective=obj.m_ceeffective; - m_cecurrent=obj.m_cecurrent; - m_lmmatrix=obj.m_lmmatrix; - } -//+------------------------------------------------------------------+ -//| This object stores nonlinear optimizer state. | -//| You should use functions provided by MinBLEIC subpackage to work | -//| with this object | -//+------------------------------------------------------------------+ -class CMinBLEICStateShell - { -private: - CMinBLEICState m_innerobj; -public: - //--- constructors, destructor - CMinBLEICStateShell(void); - CMinBLEICStateShell(CMinBLEICState &obj); - ~CMinBLEICStateShell(void); - //--- methods - bool GetNeedF(void); - void SetNeedF(const bool b); - bool GetNeedFG(void); - void SetNeedFG(const bool b); - bool GetXUpdated(void); - void SetXUpdated(const bool b); - double GetF(void); - void SetF(const double d); - CMinBLEICState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinBLEICStateShell::CMinBLEICStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinBLEICStateShell::CMinBLEICStateShell(CMinBLEICState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinBLEICStateShell::~CMinBLEICStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needf | -//+------------------------------------------------------------------+ -bool CMinBLEICStateShell::GetNeedF(void) - { -//--- return result - return(m_innerobj.m_needf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needf | -//+------------------------------------------------------------------+ -void CMinBLEICStateShell::SetNeedF(const bool b) - { -//--- change value - m_innerobj.m_needf=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfg | -//+------------------------------------------------------------------+ -bool CMinBLEICStateShell::GetNeedFG(void) - { -//--- return result - return(m_innerobj.m_needfg); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfg | -//+------------------------------------------------------------------+ -void CMinBLEICStateShell::SetNeedFG(const bool b) - { -//--- change value - m_innerobj.m_needfg=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable xupdated | -//+------------------------------------------------------------------+ -bool CMinBLEICStateShell::GetXUpdated(void) - { -//--- return result - return(m_innerobj.m_xupdated); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable xupdated | -//+------------------------------------------------------------------+ -void CMinBLEICStateShell::SetXUpdated(const bool b) - { -//--- change value - m_innerobj.m_xupdated=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable f | -//+------------------------------------------------------------------+ -double CMinBLEICStateShell::GetF(void) - { -//--- return result - return(m_innerobj.m_f); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable f | -//+------------------------------------------------------------------+ -void CMinBLEICStateShell::SetF(const double d) - { -//--- change value - m_innerobj.m_f=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinBLEICState *CMinBLEICStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| This structure stores optimization report: | -//| * InnerIterationsCount number of inner iterations | -//| * OuterIterationsCount number of outer iterations | -//| * NFEV number of gradient evaluations | -//| * TerminationType termination type (see below) | -//| TERMINATION CODES | -//| TerminationType field contains completion code,which can be: | -//| -10 unsupported combination of algorithm settings: | -//| 1) StpMax is set to non-zero value, | -//| AND 2) non-default preconditioner is used. | -//| You can't use both features at the same moment, | -//| so you have to choose one of them (and to turn | -//| off another one). | -//| -3 inconsistent constraints. Feasible point is | -//| either nonexistent or too hard to find. Try to | -//| restart optimizer with better initial | -//| approximation | -//| 4 conditions on constraints are fulfilled | -//| with error less than or equal to EpsC | -//| 5 MaxIts steps was taken | -//| 7 stopping conditions are too stringent, | -//| further improvement is impossible, | -//| X contains best point found so far. | -//| ADDITIONAL FIELDS | -//| There are additional fields which can be used for debugging: | -//| * DebugEqErr error in the equality constraints | -//| (2-norm) | -//| * DebugFS f,calculated at projection of initial| -//| point to the feasible set | -//| * DebugFF f,calculated at the final point | -//| * DebugDX |X_start-X_final| | -//+------------------------------------------------------------------+ -class CMinBLEICReport - { -public: - //--- variables - int m_inneriterationscount; - int m_outeriterationscount; - int m_nfev; - int m_terminationtype; - double m_debugeqerr; - double m_debugfs; - double m_debugff; - double m_debugdx; - //--- constructor, destructor - CMinBLEICReport(void); - ~CMinBLEICReport(void); - //--- copy - void Copy(CMinBLEICReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinBLEICReport::CMinBLEICReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinBLEICReport::~CMinBLEICReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinBLEICReport::Copy(CMinBLEICReport &obj) - { -//--- copy variables - m_inneriterationscount=obj.m_inneriterationscount; - m_outeriterationscount=obj.m_outeriterationscount; - m_nfev=obj.m_nfev; - m_terminationtype=obj.m_terminationtype; - m_debugeqerr=obj.m_debugeqerr; - m_debugfs=obj.m_debugfs; - m_debugff=obj.m_debugff; - m_debugdx=obj.m_debugdx; - } -//+------------------------------------------------------------------+ -//| This structure stores optimization report: | -//| * InnerIterationsCount number of inner iterations | -//| * OuterIterationsCount number of outer iterations | -//| * NFEV number of gradient evaluations | -//| * TerminationType termination type (see below) | -//| TERMINATION CODES | -//| TerminationType field contains completion code,which can be: | -//| -10 unsupported combination of algorithm settings: | -//| 1) StpMax is set to non-zero value, | -//| AND 2) non-default preconditioner is used. | -//| You can't use both features at the same moment, | -//| so you have to choose one of them (and to turn | -//| off another one). | -//| -3 inconsistent constraints. Feasible point is | -//| either nonexistent or too hard to find. Try to | -//| restart optimizer with better initial | -//| approximation | -//| 4 conditions on constraints are fulfilled | -//| with error less than or equal to EpsC | -//| 5 MaxIts steps was taken | -//| 7 stopping conditions are too stringent, | -//| further improvement is impossible, | -//| X contains best point found so far. | -//| ADDITIONAL FIELDS | -//| There are additional fields which can be used for debugging: | -//| * DebugEqErr error in the equality constraints | -//| (2-norm) | -//| * DebugFS f,calculated at projection of initial| -//| point to the feasible set | -//| * DebugFF f,calculated at the final point | -//| * DebugDX |X_start-X_final| | -//+------------------------------------------------------------------+ -class CMinBLEICReportShell - { -private: - CMinBLEICReport m_innerobj; -public: - //--- constructors, destructor - CMinBLEICReportShell(void); - CMinBLEICReportShell(CMinBLEICReport &obj); - ~CMinBLEICReportShell(void); - //--- methods - int GetInnerIterationsCount(void); - void SetInnerIterationsCount(const int i); - int GetOuterIterationsCount(void); - void SetOuterIterationsCount(const int i); - int GetNFev(void); - void SetNFev(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - double GetDebugEqErr(void); - void SetDebugEqErr(const double d); - double GetDebugFS(void); - void SetDebugFS(const double d); - double GetDebugFF(void); - void SetDebugFF(const double d); - double GetDebugDX(void); - void SetDebugDX(const double d); - CMinBLEICReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinBLEICReportShell::CMinBLEICReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinBLEICReportShell::CMinBLEICReportShell(CMinBLEICReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinBLEICReportShell::~CMinBLEICReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -int CMinBLEICReportShell::GetInnerIterationsCount(void) - { -//--- return result - return(m_innerobj.m_inneriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetInnerIterationsCount(const int i) - { -//--- change value - m_innerobj.m_inneriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -int CMinBLEICReportShell::GetOuterIterationsCount(void) - { -//--- return result - return(m_innerobj.m_outeriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetOuterIterationsCount(const int i) - { -//--- change value - m_innerobj.m_outeriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfev | -//+------------------------------------------------------------------+ -int CMinBLEICReportShell::GetNFev(void) - { -//--- return result - return(m_innerobj.m_nfev); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfev | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetNFev(const int i) - { -//--- change value - m_innerobj.m_nfev=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMinBLEICReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable debugeqerr | -//+------------------------------------------------------------------+ -double CMinBLEICReportShell::GetDebugEqErr(void) - { -//--- return result - return(m_innerobj.m_debugeqerr); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable debugeqerr | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetDebugEqErr(const double d) - { -//--- change value - m_innerobj.m_debugeqerr=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable debugfs | -//+------------------------------------------------------------------+ -double CMinBLEICReportShell::GetDebugFS(void) - { -//--- return result - return(m_innerobj.m_debugfs); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable debugfs | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetDebugFS(const double d) - { -//--- change value - m_innerobj.m_debugfs=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable debugff | -//+------------------------------------------------------------------+ -double CMinBLEICReportShell::GetDebugFF(void) - { -//--- return result - return(m_innerobj.m_debugff); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable debugff | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetDebugFF(const double d) - { -//--- change value - m_innerobj.m_debugff=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable debugdx | -//+------------------------------------------------------------------+ -double CMinBLEICReportShell::GetDebugDX(void) - { -//--- return result - return(m_innerobj.m_debugdx); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable debugdx | -//+------------------------------------------------------------------+ -void CMinBLEICReportShell::SetDebugDX(const double d) - { -//--- change value - m_innerobj.m_debugdx=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinBLEICReport *CMinBLEICReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Bound constrained optimization with additional linear equality | -//| and inequality constraints | -//+------------------------------------------------------------------+ -class CMinBLEIC - { -private: - //--- private methods - static void ClearRequestFields(CMinBLEICState &state); - static void UnscalePoint(CMinBLEICState &state,double &xscaled[],double &xunscaled[]); - static void ProjectPointAndUnscale(CMinBLEICState &state,double &xscaled[],double &xunscaled[],double &rscaled[],double &rnorm2); - static void ScaleGradientAndExpand(CMinBLEICState &state,double &gunscaled[],double &gscaled[]); - static void ModifyTargetFunction(CMinBLEICState &state,double &x[],double &r[],const double rnorm2,double &f,double &g[],double &gnorm,double &mpgnorm); - static bool AdditionalCheckForConstraints(CMinBLEICState &state,double &x[]); - static void RebuildCEXE(CMinBLEICState &state); - static void MakeGradientProjection(CMinBLEICState &state,double &pg[]); - static bool PrepareConstraintMatrix(CMinBLEICState &state,double &x[],double &g[],double &px[],double &pg[]); - static void MinBLEICInitInternal(const int n,double &x[],const double diffstep,CMinBLEICState &state); - //--- auxiliary functions for MinBLEICIteration - static void Func_lbl_rcomm(CMinBLEICState &state,int nmain,int nslack,int m,int i,int j,bool b,double v,double vv); - static bool Func_lbl_14(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_15(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_16(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_17(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_18(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_19(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_22(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_23(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); - static bool Func_lbl_31(CMinBLEICState &state,int &nmain,int &nslack,int &m,int &i,int &j,bool &b,double &v,double &vv); -public: - //--- class constants - static const double m_svdtol; - static const double m_maxouterits; - //--- constructor, destructor - CMinBLEIC(void); - ~CMinBLEIC(void); - //--- public methods - static void MinBLEICCreate(const int n,double &x[],CMinBLEICState &state); - static void MinBLEICCreateF(const int n,double &x[],const double diffstep,CMinBLEICState &state); - static void MinBLEICSetBC(CMinBLEICState &state,double &bndl[],double &bndu[]); - static void MinBLEICSetLC(CMinBLEICState &state,CMatrixDouble &c,int &ct[],const int k); - static void MinBLEICSetInnerCond(CMinBLEICState &state,const double epsg,const double epsf,const double epsx); - static void MinBLEICSetOuterCond(CMinBLEICState &state,const double epsx,const double epsi); - static void MinBLEICSetScale(CMinBLEICState &state,double &s[]); - static void MinBLEICSetPrecDefault(CMinBLEICState &state); - static void MinBLEICSetPrecDiag(CMinBLEICState &state,double &d[]); - static void MinBLEICSetPrecScale(CMinBLEICState &state); - static void MinBLEICSetMaxIts(CMinBLEICState &state,const int maxits); - static void MinBLEICSetXRep(CMinBLEICState &state,const bool needxrep); - static void MinBLEICSetStpMax(CMinBLEICState &state,const double stpmax); - static void MinBLEICResults(CMinBLEICState &state,double &x[],CMinBLEICReport &rep); - static void MinBLEICResultsBuf(CMinBLEICState &state,double &x[],CMinBLEICReport &rep); - static void MinBLEICRestartFrom(CMinBLEICState &state,double &x[]); - static bool MinBLEICIteration(CMinBLEICState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CMinBLEIC::m_svdtol=100; -const double CMinBLEIC::m_maxouterits=20; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinBLEIC::CMinBLEIC(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinBLEIC::~CMinBLEIC(void) - { - - } -//+------------------------------------------------------------------+ -//| BOUND CONSTRAINED OPTIMIZATION | -//| WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS| -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments subject to | -//| any combination of: | -//| * bound constraints | -//| * linear inequality constraints | -//| * linear equality constraints | -//| REQUIREMENTS: | -//| * user must provide function value and gradient | -//| * starting point X0 must be feasible or | -//| not too far away from the feasible set | -//| * grad(f) must be Lipschitz continuous on a level set: | -//| L = { x : f(x)<=f(x0) } | -//| * function must be defined everywhere on the feasible set F | -//| USAGE: | -//| Constrained optimization if far more complex than the | -//| unconstrained one. Here we give very brief outline of the BLEIC | -//| optimizer. We strongly recommend you to read examples in the | -//| ALGLIB Reference Manual and to read ALGLIB User Guide on | -//| optimization, which is available at | -//| http://www.alglib.net/optimization/ | -//| 1. User initializes algorithm state with MinBLEICCreate() call | -//| 2. USer adds boundary and/or linear constraints by calling | -//| MinBLEICSetBC() and MinBLEICSetLC() functions. | -//| 3. User sets stopping conditions for underlying unconstrained | -//| solver with MinBLEICSetInnerCond() call. | -//| This function controls accuracy of underlying optimization | -//| algorithm. | -//| 4. User sets stopping conditions for outer iteration by calling | -//| MinBLEICSetOuterCond() function. | -//| This function controls handling of boundary and inequality | -//| constraints. | -//| 5. Additionally, user may set limit on number of internal | -//| iterations by MinBLEICSetMaxIts() call. | -//| This function allows to prevent algorithm from looping | -//| forever. | -//| 6. User calls MinBLEICOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function | -//| which calculates F/G. | -//| 7. User calls MinBLEICResults() to get solution | -//| 8. Optionally user may call MinBLEICRestartFrom() to solve | -//| another problem with same N but another starting point. | -//| MinBLEICRestartFrom() allows to reuse already initialized | -//| structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension, N>0: | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size ofX | -//| X - starting point, array[N]: | -//| * it is better to set X to a feasible point | -//| * but X can be infeasible, in which case | -//| algorithm will try to find feasible point | -//| first, using X as initial approximation. | -//| OUTPUT PARAMETERS: | -//| State - structure stores algorithm state | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICCreate(const int n,double &x[],CMinBLEICState &state) - { -//--- create matrix - CMatrixDouble c; -//--- create array - int ct[]; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinBLEICSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. CG needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small - dimensional problems only, and to implement analytical| -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICCreateF(const int n,double &x[], - const double diffstep, - CMinBLEICState &state) - { -//--- create matrix - CMatrixDouble c; -//--- create array - int ct[]; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0.0,__FUNCTION__+": DiffStep is non-positive!")) - return; -//--- function call - MinBLEICInitInternal(n,x,diffstep,state); - } -//+------------------------------------------------------------------+ -//| This function sets boundary constraints for BLEIC optimizer. | -//| Boundary constraints are inactive by default (after initial | -//| creation). They are preserved after algorithm restart with | -//| MinBLEICRestartFrom(). | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| BndL - lower bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very small number or -INF. | -//| BndU - upper bounds, array[N]. | -//| If some (all) variables are unbounded, you may | -//| specify very large number or +INF. | -//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case | -//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. | -//| NOTE 2: this solver has following useful properties: | -//| * bound constraints are always satisfied exactly | -//| * function is evaluated only INSIDE area specified by bound | -//| constraints, even when numerical differentiation is used | -//| (algorithm adjusts nodes according to boundary constraints) | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetBC(CMinBLEICState &state,double &bndl[], - double &bndu[]) - { -//--- create variables - int i=0; - int n=0; -//--- initialization - n=state.m_nmain; -//--- check - if(!CAp::Assert(CAp::Len(bndl)>=n,__FUNCTION__+": Length(BndL)=n,__FUNCTION__+": Length(BndU)0, then I-th constraint is | -//| C[i,*]*x >= C[i,n+1] | -//| * if CT[i]=0, then I-th constraint is | -//| C[i,*]*x = C[i,n+1] | -//| * if CT[i]<0, then I-th constraint is | -//| C[i,*]*x <= C[i,n+1] | -//| K - number of equality/inequality constraints, K>=0: | -//| * if given, only leading K elements of C/CT are | -//| used | -//| * if not given, automatically determined from | -//| sizes of C/CT | -//| NOTE 1: linear (non-bound) constraints are satisfied only | -//| approximately: | -//| * there always exists some minor violation (about Epsilon in | -//| magnitude) due to rounding errors | -//| * numerical differentiation, if used, may lead to function | -//| evaluations outside of the feasible area, because algorithm | -//| does NOT change numerical differentiation formula according to | -//| linear constraints. | -//| If you want constraints to be satisfied exactly, try to | -//| reformulate your problem in such manner that all constraints will| -//| become boundary ones (this kind of constraints is always | -//| satisfied exactly, both in the final solution and in all | -//| intermediate points). | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetLC(CMinBLEICState &state,CMatrixDouble &c, - int &ct[],const int k) - { -//--- create variables - int nmain=0; - int i=0; - int i_=0; -//--- initialization - nmain=state.m_nmain; -//--- First,check for errors in the inputs - if(!CAp::Assert(k>=0,__FUNCTION__+": K<0")) - return; -//--- check - if(!CAp::Assert(CAp::Cols(c)>=nmain+1||k==0,__FUNCTION__+": Cols(C)=k,__FUNCTION__+": Rows(C)=k,__FUNCTION__+": Length(CT)=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by | -//| MinBLEICSetScale() | -//| Passing EpsG=0, EpsF=0 and EpsX=0 (simultaneously) will lead to | -//| automatic stopping criterion selection. | -//| These conditions are used to terminate inner iterations. However,| -//| you need to tune termination conditions for outer iterations too.| -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetInnerCond(CMinBLEICState &state,const double epsg, - const double epsf,const double epsx) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsg),__FUNCTION__+": EpsG is not finite number")) - return; -//--- check - if(!CAp::Assert(epsg>=0.0,__FUNCTION__+": negative EpsG")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number")) - return; -//--- check - if(!CAp::Assert(epsx>=0.0,__FUNCTION__+": negative EpsX")) - return; -//--- change values - state.m_innerepsg=epsg; - state.m_innerepsf=epsf; - state.m_innerepsx=epsx; - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for outer iteration of | -//| BLEIC algo. | -//| These conditions control accuracy of constraint handling and | -//| amount of infeasibility allowed in the solution. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsX - >0, stopping condition on outer iteration step | -//| length | -//| EpsI - >0, stopping condition on infeasibility | -//| Both EpsX and EpsI must be non-zero. | -//| MEANING OF EpsX | -//| EpsX is a stopping condition for outer iterations. Algorithm will| -//| stop when solution of the current modified subproblem will be | -//| within EpsX (using 2-norm) of the previous solution. | -//| MEANING OF EpsI | -//| EpsI controls feasibility properties - algorithm won't stop until| -//| all inequality constraints will be satisfied with error (distance| -//| from current point to the feasible area) at most EpsI. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetOuterCond(CMinBLEICState &state,const double epsx, - const double epsi) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number")) - return; -//--- check - if(!CAp::Assert(epsx>0.0,__FUNCTION__+": non-positive EpsX")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsi),__FUNCTION__+": EpsI is not finite number")) - return; -//--- check - if(!CAp::Assert((double)(epsi)>0.0,__FUNCTION__+": non-positive EpsI")) - return; -//--- change values - state.m_outerepsx=epsx; - state.m_outerepsi=epsi; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for BLEIC optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of the | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the BLEIC too) scaling is NOT a form | -//| of preconditioning. It just affects stopping conditions. You | -//| should set preconditioner by separate call to one of the | -//| MinBLEICSetPrec...() functions. | -//| There is a special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should understand| -//| that scaling is not the same thing as preconditioning - these are| -//| two different, although related forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetScale(CMinBLEICState &state,double &s[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(s)>=state.m_nmain,__FUNCTION__+": Length(S)=state.m_nmain,__FUNCTION__+": D is too short")) - return; - for(i=0;i<=state.m_nmain-1;i++) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(d[i]),__FUNCTION__+": D contains infinite or NAN elements")) - return; - //--- check - if(!CAp::Assert((double)(d[i])>0.0,__FUNCTION__+": D contains non-positive elements")) - return; - } -//--- function call - CApServ::RVectorSetLengthAtLeast(state.m_diaghoriginal,state.m_nmain); - state.m_prectype=2; -//--- copy - for(i=0;i<=state.m_nmain-1;i++) - state.m_diaghoriginal[i]=d[i]; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, with H[i] = | -//| = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinBLEICSetScale() call (before or after MinBLEICSetPrecScale() | -//| call). Without knowledge of the scale of your variables | -//| scale-based preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetPrecScale(CMinBLEICState &state) - { -//--- change value - state.m_prectype=3; - } -//+------------------------------------------------------------------+ -//| This function allows to stop algorithm after specified number of | -//| inner iterations. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| MaxIts - maximum number of inner iterations. | -//| If MaxIts=0, the number of iterations is | -//| unlimited. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetMaxIts(CMinBLEICState &state, - const int maxits) - { -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- change value - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinBLEICOptimize(). | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetXRep(CMinBLEICState &state, - const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| IMPORTANT: this feature is hard to combine with preconditioning. | -//| You can't set upper limit on step length, when you solve | -//| optimization problem with linear (non-boundary) constraints AND | -//| preconditioner turned on. | -//| When non-boundary constraints are present, you have to either a) | -//| use preconditioner, or b) use upper limit on step length. YOU | -//| CAN'T USE BOTH! In this case algorithm will terminate with | -//| appropriate error code. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which lead to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICSetStpMax(CMinBLEICState &state, - const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| BLEIC results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report. You should check Rep. | -//| TerminationType in order to distinguish | -//| successful termination from unsuccessful one. | -//| More information about fields of this structure | -//| can be found in the comments on MinBLEICReport | -//| datatype. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICResults(CMinBLEICState &state,double &x[], - CMinBLEICReport &rep) - { -//--- reset memory - ArrayResizeAL(x,0); -//--- function call - MinBLEICResultsBuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| BLEIC results | -//| Buffered implementation of MinBLEICResults() which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICResultsBuf(CMinBLEICState &state,double &x[], - CMinBLEICReport &rep) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(CAp::Len(x)0) - { - for(i_=0;i_<=state.m_nmain-1;i_++) - x[i_]=state.m_xend[i_]; - } - else - { - for(i=0;i<=state.m_nmain-1;i++) - x[i]=CInfOrNaN::NaN(); - } -//--- change values - rep.m_debugeqerr=state.m_repdebugeqerr; - rep.m_debugfs=state.m_repdebugfs; - rep.m_debugff=state.m_repdebugff; - rep.m_debugdx=state.m_repdebugdx; - } -//+------------------------------------------------------------------+ -//| This subroutine restarts algorithm from new point. | -//| All optimization parameters (including constraints) are left | -//| unchanged. | -//| This function allows to solve multiple optimization problems | -//| (which must have same number of dimensions) without object | -//| reallocation penalty. | -//| INPUT PARAMETERS: | -//| State - structure previously allocated with | -//| MinBLEICCreate call. | -//| X - new starting point. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICRestartFrom(CMinBLEICState &state,double &x[]) - { -//--- create variables - int n=0; - int i_=0; -//--- initialization - n=state.m_nmain; -//--- First,check for errors in the inputs - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)state.m_bnduoriginal[i]) - v=state.m_bnduoriginal[i]; - } - xunscaled[i]=v; - } - } -//+------------------------------------------------------------------+ -//| This function: | -//| 1. makes projection of XScaled into equality constrained subspace| -//| (X is modified in-place) | -//| 2. stores residual from the projection into R | -//| 3. unscales projected XScaled and stores result into XUnscaled | -//| with additional enforcement | -//| It calculates set of additional values which are used later for | -//| modification of the target function F. | -//| INPUT PARAMETERS: | -//| State - optimizer state (we use its fields to get | -//| information about constraints) | -//| X - vector being projected | -//| R - preallocated buffer, used to store residual from | -//| projection | -//| OUTPUT PARAMETERS: | -//| X - projection of input X | -//| R - residual | -//| RNorm - residual norm squared, used later to modify | -//| target function | -//+------------------------------------------------------------------+ -static void CMinBLEIC::ProjectPointAndUnscale(CMinBLEICState &state, - double &xscaled[],double &xunscaled[], - double &rscaled[],double &rnorm2) - { -//--- create variables - double v=0; - int i=0; - int nmain=0; - int nslack=0; - int i_=0; -//--- initialization - rnorm2=0; - nmain=state.m_nmain; - nslack=state.m_nslack; -//--- * subtract XE from XScaled -//--- * project XScaled -//--- * calculate norm of deviation from null space,store it in RNorm2 -//--- * calculate residual from projection,store it in R -//--- * add XE to XScaled -//--- * unscale variables - for(i_=0;i_<=nmain+nslack-1;i_++) - xscaled[i_]=xscaled[i_]-state.m_xe[i_]; - rnorm2=0; - for(i=0;i<=nmain+nslack-1;i++) - rscaled[i]=0; -//--- change values - for(i=0;i<=nmain+nslack-1;i++) - { - //--- check - if(state.m_activeconstraints[i]) - { - v=xscaled[i]; - xscaled[i]=0; - rscaled[i]=rscaled[i]+v; - rnorm2=rnorm2+CMath::Sqr(v); - } - } -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=xscaled[i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - xscaled[i_]=xscaled[i_]-v*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - rscaled[i_]=rscaled[i_]+v*state.m_cecurrent[i][i_]; - rnorm2=rnorm2+CMath::Sqr(v); - } - for(i_=0;i_<=nmain+nslack-1;i_++) - xscaled[i_]=xscaled[i_]+state.m_xe[i_]; -//--- function call - UnscalePoint(state,xscaled,xunscaled); - } -//+------------------------------------------------------------------+ -//| This function scales and copies NMain elements of GUnscaled into | -//| GScaled. Other NSlack components of GScaled are set to zero. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::ScaleGradientAndExpand(CMinBLEICState &state, - double &gunscaled[], - double &gscaled[]) - { -//--- create a variable - int i=0; -//--- change values - for(i=0;i<=state.m_nmain-1;i++) - gscaled[i]=gunscaled[i]*state.m_transforms[i]; - for(i=0;i<=state.m_nslack-1;i++) - gscaled[state.m_nmain+i]=0; - } -//+------------------------------------------------------------------+ -//| This subroutine applies modifications to the target function | -//| given by its value F and gradient G at the projected point X | -//| which lies in the equality constrained subspace. | -//| Following modifications are applied: | -//| * modified barrier functions to handle inequality constraints | -//| (both F and G are modified) | -//| * projection of gradient into equality constrained subspace | -//| (only G is modified) | -//| * quadratic penalty for deviations from equality constrained | -//| subspace (both F and G are modified) | -//| It also calculates gradient norm (three different norms for three| -//| different types of gradient), feasibility and complementary | -//| slackness errors. | -//| INPUT PARAMETERS: | -//| State - optimizer state (we use its fields to get | -//| information about constraints) | -//| X - point (projected into equality constrained | -//| subspace) | -//| R - residual from projection | -//| RNorm2 - residual norm squared | -//| F - function value at X | -//| G - function gradient at X | -//| OUTPUT PARAMETERS: | -//| F - modified function value at X | -//| G - modified function gradient at X | -//| GNorm - 2-norm of unmodified G | -//| MPGNorm - 2-norm of modified G | -//| MBA - minimum argument of barrier functions. | -//| If X is strictly feasible, it is greater than | -//| zero. | -//| If X lies on a boundary, it is zero. | -//| It is negative for infeasible X. | -//| FIErr - 2-norm of feasibility error with respect to | -//| inequality/bound constraints | -//| CSErr - 2-norm of complementarity slackness error | -//+------------------------------------------------------------------+ -static void CMinBLEIC::ModifyTargetFunction(CMinBLEICState &state,double &x[], - double &r[],const double rnorm2, - double &f,double &g[], - double &gnorm,double &mpgnorm) - { -//--- create variables - double v=0; - int i=0; - int nmain=0; - int nslack=0; - bool hasconstraints; - int i_=0; -//--- initialization - gnorm=0; - mpgnorm=0; - nmain=state.m_nmain; - nslack=state.m_nslack; - hasconstraints=false; -//--- GNorm - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=g[i_]*g[i_]; - gnorm=MathSqrt(v); -//--- Process equality constraints: -//--- * modify F to handle penalty term for equality constraints -//--- * project gradient on null space of equality constraints -//--- * add penalty term for equality constraints to gradient - f=f+rnorm2; - for(i=0;i<=nmain+nslack-1;i++) - { - //--- check - if(state.m_activeconstraints[i]) - g[i]=0; - } - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - //--- change values - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=g[i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - g[i_]=g[i_]-v*state.m_cecurrent[i][i_]; - } - for(i_=0;i_<=nmain+nslack-1;i_++) - g[i_]=g[i_]+2*r[i_]; -//--- MPGNorm - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=g[i_]*g[i_]; - mpgnorm=MathSqrt(v); - } -//+------------------------------------------------------------------+ -//| This function makes additional check for constraints which can be| -//| activated. | -//| We try activate constraints one by one, but it is possible that | -//| several constraints should be activated during one iteration. It | -//| this case only one of them (probably last) will be activated. | -//| This function will fix it - it will pass through constraints and | -//| activate those which are at the boundary or beyond it. | -//| It will return True, if at least one constraint was activated by | -//| this function. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::AdditionalCheckForConstraints(CMinBLEICState &state, - double &x[]) - { -//--- create variables - bool result; - int i=0; - int nmain=0; - int nslack=0; -//--- initialization - result=false; - nmain=state.m_nmain; - nslack=state.m_nslack; -//--- calculation - for(i=0;i<=nmain-1;i++) - { - //--- check - if(!state.m_activeconstraints[i]) - { - //--- check - if(state.m_hasbndl[i]) - { - //--- check - if(x[i]<=state.m_bndleffective[i]) - { - state.m_activeconstraints[i]=true; - state.m_constrainedvalues[i]=state.m_bndleffective[i]; - result=true; - } - } - //--- check - if(state.m_hasbndu[i]) - { - //--- check - if(x[i]>=state.m_bndueffective[i]) - { - state.m_activeconstraints[i]=true; - state.m_constrainedvalues[i]=state.m_bndueffective[i]; - result=true; - } - } - } - } - for(i=0;i<=nslack-1;i++) - { - //--- check - if(!state.m_activeconstraints[nmain+i]) - { - //--- check - if(x[nmain+i]<=0.0) - { - state.m_activeconstraints[nmain+i]=true; - state.m_constrainedvalues[nmain+i]=0; - result=true; - } - } - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| This function rebuilds CECurrent and XE according to current set | -//| of active bound constraints. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::RebuildCEXE(CMinBLEICState &state) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int nmain=0; - int nslack=0; - double v=0; - int i_=0; -//--- initialization - nmain=state.m_nmain; - nslack=state.m_nslack; -//--- function call - CAblas::RMatrixCopy(state.m_cecnt,nmain+nslack+1,state.m_ceeffective,0,0,state.m_cecurrent,0,0); -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - //--- "Subtract" active bound constraints from I-th linear constraint - for(j=0;j<=nmain+nslack-1;j++) - { - //--- check - if(state.m_activeconstraints[j]) - { - state.m_cecurrent[i].Set(nmain+nslack,state.m_cecurrent[i][nmain+nslack]-state.m_cecurrent[i][j]*state.m_constrainedvalues[j]); - state.m_cecurrent[i].Set(j,0.0); - } - } - //--- Reorthogonalize I-th constraint with respect to previous ones - //--- NOTE: we also update right part,which is CECurrent[...,NMain+NSlack]. - for(k=0;k<=i-1;k++) - { - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=state.m_cecurrent[k][i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack;i_++) - state.m_cecurrent[i].Set(i_,state.m_cecurrent[i][i_]-v*state.m_cecurrent[k][i_]); - } - //--- Calculate norm of I-th row of CECurrent. Fill by zeros,if it is - //--- too small. Normalize otherwise. - //--- NOTE: we also scale last column of CECurrent (right part) - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=state.m_cecurrent[i][i_]*state.m_cecurrent[i][i_]; - v=MathSqrt(v); - //--- check - if(v>10000*CMath::m_machineepsilon) - { - v=1/v; - for(i_=0;i_<=nmain+nslack;i_++) - state.m_cecurrent[i].Set(i_,v*state.m_cecurrent[i][i_]); - } - else - { - for(j=0;j<=nmain+nslack;j++) - state.m_cecurrent[i].Set(j,0); - } - } -//--- change values - for(j=0;j<=nmain+nslack-1;j++) - state.m_xe[j]=0; - for(i=0;i<=nmain+nslack-1;i++) - { - //--- check - if(state.m_activeconstraints[i]) - state.m_xe[i]=state.m_xe[i]+state.m_constrainedvalues[i]; - } -//--- change values - for(i=0;i<=state.m_cecnt-1;i++) - { - v=state.m_cecurrent[i][nmain+nslack]; - for(i_=0;i_<=nmain+nslack-1;i_++) - state.m_xe[i_]=state.m_xe[i_]+v*state.m_cecurrent[i][i_]; - } - } -//+------------------------------------------------------------------+ -//| This function projects gradient onto equality constrained | -//| subspace | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MakeGradientProjection(CMinBLEICState &state, - double &pg[]) - { -//--- create variables - int i=0; - int nmain=0; - int nslack=0; - double v=0; - int i_=0; -//--- initialization - nmain=state.m_nmain; - nslack=state.m_nslack; - for(i=0;i<=nmain+nslack-1;i++) - { - //--- check - if(state.m_activeconstraints[i]) - pg[i]=0; - } -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=pg[i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - pg[i_]=pg[i_]-v*state.m_cecurrent[i][i_]; - } - } -//+------------------------------------------------------------------+ -//| This function prepares equality constrained subproblem: | -//| 1. X is used to activate constraints (if there are ones which are| -//| still inactive, but should be activated). | -//| 2. constraints matrix CEOrt is copied to CECurrent and modified | -//| according to the list of active bound constraints | -//| (corresponding elements are filled by zeros and | -//| reorthogonalized). | -//| 3. XE - least squares solution of equality constraints - is | -//| recalculated | -//| 4. X is copied to PX and projected onto equality constrained | -//| subspace | -//| 5. inactive constraints are checked against PX - if there is at | -//| least one which should be activated, we activate it and move | -//| back to (2) | -//| 6. as result, PX is feasible with respect to bound constraints - | -//| step (5) guarantees it. But PX can be infeasible with respect | -//| to equality ones, because step (2) is done without checks for | -//| consistency. As the final step, we check that PX is feasible. | -//| If not, we return False. True is returned otherwise. | -//| If this algorithm returned True, then: | -//| * X is not changed | -//| * PX contains projection of X onto constrained subspace | -//| * G is not changed | -//| * PG contains projection of G onto constrained subspace | -//| * PX is feasible with respect to all constraints | -//| * all constraints which are active at PX, are activated | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::PrepareConstraintMatrix(CMinBLEICState &state,double &x[], - double &g[],double &px[],double &pg[]) - { -//--- create variables - int i=0; - int nmain=0; - int nslack=0; - double v=0; - double ferr=0; - int i_=0; -//--- initialization - nmain=state.m_nmain; - nslack=state.m_nslack; -//--- Step 1 - AdditionalCheckForConstraints(state,x); -//--- Steps 2-5 - do - { - //--- Steps 2-3 - RebuildCEXE(state); - //--- Step 4 - //--- Calculate PX,PG - for(i_=0;i_<=nmain+nslack-1;i_++) - px[i_]=x[i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - px[i_]=px[i_]-state.m_xe[i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - pg[i_]=g[i_]; - for(i=0;i<=nmain+nslack-1;i++) - { - //--- check - if(state.m_activeconstraints[i]) - { - px[i]=0; - pg[i]=0; - } - } - //--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - //--- change values - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=px[i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - px[i_]=px[i_]-v*state.m_cecurrent[i][i_]; - //--- change values - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=pg[i_]*state.m_cecurrent[i][i_]; - for(i_=0;i_<=nmain+nslack-1;i_++) - pg[i_]=pg[i_]-v*state.m_cecurrent[i][i_]; - } - for(i_=0;i_<=nmain+nslack-1;i_++) - px[i_]=px[i_]+state.m_xe[i_]; - //--- Step 5 (loop condition below) - } - while(AdditionalCheckForConstraints(state,px)); -//--- Step 6 - ferr=0; - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=px[i_]*state.m_ceeffective[i][i_]; - //--- change values - v=v-state.m_ceeffective[i][nmain+nslack]; - ferr=MathMax(ferr,MathAbs(v)); - } -//--- check - if(ferr<=state.m_outerepsi) - return(true); -//--- return result - return(false); - } -//+------------------------------------------------------------------+ -//| Internal initialization subroutine | -//+------------------------------------------------------------------+ -static void CMinBLEIC::MinBLEICInitInternal(const int n,double &x[], - const double diffstep, - CMinBLEICState &state) - { -//--- create a variable - int i=0; -//--- create matrix - CMatrixDouble c; -//--- create array - int ct[]; -//--- initialization - state.m_nmain=n; - state.m_optdim=0; - state.m_diffstep=diffstep; -//--- allocation - ArrayResizeAL(state.m_bndloriginal,n); - ArrayResizeAL(state.m_bndleffective,n); - ArrayResizeAL(state.m_hasbndl,n); - ArrayResizeAL(state.m_bnduoriginal,n); - ArrayResizeAL(state.m_bndueffective,n); - ArrayResizeAL(state.m_hasbndu,n); - ArrayResizeAL(state.m_xstart,n); - ArrayResizeAL(state.m_soriginal,n); - ArrayResizeAL(state.m_x,n); - ArrayResizeAL(state.m_g,n); - for(i=0;i<=n-1;i++) - { - state.m_bndloriginal[i]=CInfOrNaN::NegativeInfinity(); - state.m_hasbndl[i]=false; - state.m_bnduoriginal[i]=CInfOrNaN::PositiveInfinity(); - state.m_hasbndu[i]=false; - state.m_soriginal[i]=1.0; - } -//--- function call - MinBLEICSetLC(state,c,ct,0); -//--- function call - MinBLEICSetInnerCond(state,0.0,0.0,0.0); -//--- function call - MinBLEICSetOuterCond(state,1.0E-6,1.0E-6); -//--- function call - MinBLEICSetMaxIts(state,0); -//--- function call - MinBLEICSetXRep(state,false); -//--- function call - MinBLEICSetStpMax(state,0.0); -//--- function call - MinBLEICSetPrecDefault(state); -//--- function call - MinBLEICRestartFrom(state,x); - } -//+------------------------------------------------------------------+ -//| NOTES: | -//| 1. This function has two different implementations: one which | -//| uses exact (analytical) user-supplied gradient, and one which | -//| uses function value only and numerically differentiates | -//| function in order to obtain gradient. | -//| Depending on the specific function used to create optimizer | -//| object (either MinBLEICCreate() for analytical gradient or | -//| MinBLEICCreateF() for numerical differentiation) you should | -//| choose appropriate variant of MinBLEICOptimize() - one which | -//| accepts function AND gradient or one which accepts function | -//| ONLY. | -//| Be careful to choose variant of MinBLEICOptimize() which | -//| corresponds to your optimization scheme! Table below lists | -//| different combinations of callback (function/gradient) passed | -//| to MinBLEICOptimize() and specific function used to create | -//| optimizer. | -//| | USER PASSED TO MinBLEICOptimize() | -//| CREATED WITH | function only | function and gradient | -//| ------------------------------------------------------------ | -//| MinBLEICCreateF() | work FAIL | -//| MinBLEICCreate() | FAIL work | -//| Here "FAIL" denotes inappropriate combinations of optimizer | -//| creation function and MinBLEICOptimize() version. Attemps to | -//| use such combination (for example, to create optimizer with | -//| MinBLEICCreateF() and to pass gradient information to | -//| MinCGOptimize()) will lead to exception being thrown. Either | -//| you did not pass gradient when it WAS needed or you passed | -//| gradient when it was NOT needed. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::MinBLEICIteration(CMinBLEICState &state) - { -//--- create variables - int nmain=0; - int nslack=0; - int m=0; - int i=0; - int j=0; - double v=0; - double vv=0; - bool b; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - nmain=state.m_rstate.ia[0]; - nslack=state.m_rstate.ia[1]; - m=state.m_rstate.ia[2]; - i=state.m_rstate.ia[3]; - j=state.m_rstate.ia[4]; - b=state.m_rstate.ba[0]; - v=state.m_rstate.ra[0]; - vv=state.m_rstate.ra[1]; - } - else - { - //--- initialization - nmain=-983; - nslack=-989; - m=-834; - i=900; - j=-287; - b=false; - v=214; - vv=-338; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needfg=false; - //--- function call, return result - return(Func_lbl_14(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change value - state.m_needf=false; - //--- function call, return result - return(Func_lbl_14(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change value - state.m_needfg=false; - //--- function call, return result - return(Func_lbl_22(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change values - state.m_fbase=state.m_f; - i=0; - //--- function call, return result - return(Func_lbl_23(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change values - state.m_fm2=state.m_f; - state.m_x[i]=v-0.5*state.m_diffstep*state.m_soriginal[i]; - state.m_rstate.stage=5; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change values - state.m_fm1=state.m_f; - state.m_x[i]=v+0.5*state.m_diffstep*state.m_soriginal[i]; - state.m_rstate.stage=6; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change values - state.m_fp1=state.m_f; - state.m_x[i]=v+state.m_diffstep*state.m_soriginal[i]; - state.m_rstate.stage=7; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==7) - { - //--- change values - state.m_fp2=state.m_f; - state.m_g[i]=(8*(state.m_fp1-state.m_fm1)-(state.m_fp2-state.m_fm2))/(6*state.m_diffstep*state.m_soriginal[i]); - state.m_x[i]=v; - i=i+1; - //--- function call, return result - return(Func_lbl_23(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==8) - { - //--- change values - state.m_fm1=state.m_f; - state.m_xp1=MathMin(v+state.m_diffstep*state.m_soriginal[i],state.m_bnduoriginal[i]); - state.m_x[i]=state.m_xp1; - state.m_rstate.stage=9; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==9) - { - //--- change values - state.m_fp1=state.m_f; - state.m_g[i]=(state.m_fp1-state.m_fm1)/(state.m_xp1-state.m_xm1); - state.m_x[i]=v; - i=i+1; - //--- function call, return result - return(Func_lbl_23(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==10) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_17(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==11) - { - //--- change value - state.m_needfg=false; - //--- function call, return result - return(Func_lbl_31(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_rstate.stage==12) - { - //--- change value - state.m_needf=false; - //--- function call, return result - return(Func_lbl_31(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- Routine body -//--- Prepare: -//--- * calculate number of slack variables -//--- * initialize locals -//--- * initialize debug fields -//--- * make quick check - nmain=state.m_nmain; - nslack=0; - for(i=0;i<=state.m_cecnt-1;i++) - { - //--- check - if(state.m_ct[i]!=0) - nslack=nslack+1; - } -//--- change values - state.m_nslack=nslack; - state.m_repterminationtype=0; - state.m_repinneriterationscount=0; - state.m_repouteriterationscount=0; - state.m_repnfev=0; - state.m_repdebugeqerr=0.0; - state.m_repdebugfs=CInfOrNaN::NaN(); - state.m_repdebugff=CInfOrNaN::NaN(); - state.m_repdebugdx=CInfOrNaN::NaN(); -//--- check - if(state.m_stpmax!=0.0 && state.m_prectype!=0) - { - state.m_repterminationtype=-10; - //--- return result - return(false); - } -//--- allocate - CApServ::RVectorSetLengthAtLeast(state.m_r,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_diagh,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_tmp0,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_tmp1,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_tmp2,nmain+nslack); - CApServ::RMatrixSetLengthAtLeast(state.m_cecurrent,state.m_cecnt,nmain+nslack+1); - CApServ::BVectorSetLengthAtLeast(state.m_activeconstraints,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_constrainedvalues,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_lastg,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_xe,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_xcur,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_xprev,nmain+nslack); - CApServ::RVectorSetLengthAtLeast(state.m_xend,nmain); -//--- Create/restart optimizer. -//--- State.OptDim is used to determine current state of optimizer. - if(state.m_optdim!=nmain+nslack) - { - for(i=0;i<=nmain+nslack-1;i++) - state.m_tmp1[i]=0.0; - //--- function call - CMinCG::MinCGCreate(nmain+nslack,state.m_tmp1,state.m_cgstate); - state.m_optdim=nmain+nslack; - } -//--- Prepare transformation. -//--- MinBLEIC's handling of preconditioner matrix is somewhat unusual - -//--- instead of incorporating it into algorithm and making implicit -//--- scaling (as most optimizers do) BLEIC optimizer uses explicit -//--- scaling - it solves problem in the scaled parameters space S, -//--- making transition between scaled (S) and unscaled (X) variables -//--- every time we ask for function value. -//--- Following fields are calculated here: -//--- * TransformS X[i]=TransformS[i]*S[i],array[NMain] -//--- * SEffective "effective" scale of the variables after -//--- transformation,array[NMain+NSlack] - CApServ::RVectorSetLengthAtLeast(state.m_transforms,nmain); - for(i=0;i<=nmain-1;i++) - { - //--- check - if(state.m_prectype==2) - { - state.m_transforms[i]=1/MathSqrt(state.m_diaghoriginal[i]); - continue; - } - //--- check - if(state.m_prectype==3) - { - state.m_transforms[i]=state.m_soriginal[i]; - continue; - } - state.m_transforms[i]=1; - } -//--- function call - CApServ::RVectorSetLengthAtLeast(state.m_seffective,nmain+nslack); - for(i=0;i<=nmain-1;i++) - state.m_seffective[i]=state.m_soriginal[i]/state.m_transforms[i]; - for(i=0;i<=nslack-1;i++) - state.m_seffective[nmain+i]=1; -//--- function call - CMinCG::MinCGSetScale(state.m_cgstate,state.m_seffective); -//--- Pre-process constraints -//--- * check consistency of bound constraints -//--- * add slack vars,convert problem to the bound/equality -//--- constrained one -//--- We calculate here: -//--- * BndLEffective - lower bounds after transformation of variables (see above) -//--- * BndUEffective - upper bounds after transformation of variables (see above) -//--- * CEEffective - matrix of equality constraints for transformed variables - for(i=0;i<=nmain-1;i++) - { - //--- check - if(state.m_hasbndl[i]) - state.m_bndleffective[i]=state.m_bndloriginal[i]/state.m_transforms[i]; - //--- check - if(state.m_hasbndu[i]) - state.m_bndueffective[i]=state.m_bnduoriginal[i]/state.m_transforms[i]; - } - for(i=0;i<=nmain-1;i++) - { - //--- check - if(state.m_hasbndl[i] && state.m_hasbndu[i]) - { - //--- check - if(state.m_bndleffective[i]>state.m_bndueffective[i]) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } - } - } -//--- function call - CApServ::RMatrixSetLengthAtLeast(state.m_ceeffective,state.m_cecnt,nmain+nslack+1); -//--- change value - m=0; -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - //--- NOTE: when we add slack variable,we use V=max(abs(CE[i,...])) as - //--- coefficient before it in order to make linear equations better - //--- conditioned. - v=0; - for(j=0;j<=nmain-1;j++) - { - state.m_ceeffective[i].Set(j,state.m_ceoriginal[i][j]*state.m_transforms[j]); - v=MathMax(v,MathAbs(state.m_ceeffective[i][j])); - } - //--- check - if(v==0.0) - v=1; - for(j=0;j<=nslack-1;j++) - state.m_ceeffective[i].Set(nmain+j,0.0); - state.m_ceeffective[i].Set(nmain+nslack,state.m_ceoriginal[i][nmain]); - //--- check - if(state.m_ct[i]<0) - { - state.m_ceeffective[i].Set(nmain+m,v); - m=m+1; - } - //--- check - if(state.m_ct[i]>0) - { - state.m_ceeffective[i].Set(nmain+m,-v); - m=m+1; - } - } -//--- Find feasible point. -//--- 0. Convert from unscaled values (as stored in XStart) to scaled -//--- ones -//--- 1. calculate values of slack variables such that starting -//--- point satisfies inequality constraints (after conversion to -//--- equality ones) as much as possible. -//--- 2. use PrepareConstraintMatrix() function,which forces X -//--- to be strictly feasible. - for(i=0;i<=nmain-1;i++) - state.m_tmp0[i]=state.m_xstart[i]/state.m_transforms[i]; -//--- change value - m=0; -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - for(i_=0;i_<=nmain-1;i_++) - v+=state.m_ceeffective[i][i_]*state.m_tmp0[i_]; - //--- check - if(state.m_ct[i]<0) - { - state.m_tmp0[nmain+m]=state.m_ceeffective[i][nmain+nslack]-v; - m=m+1; - } - //--- check - if(state.m_ct[i]>0) - { - state.m_tmp0[nmain+m]=v-state.m_ceeffective[i][nmain+nslack]; - m=m+1; - } - } -//--- change values - for(i=0;i<=nmain+nslack-1;i++) - state.m_tmp1[i]=0; - for(i=0;i<=nmain+nslack-1;i++) - state.m_activeconstraints[i]=false; -//--- function call - b=PrepareConstraintMatrix(state,state.m_tmp0,state.m_tmp1,state.m_xcur,state.m_tmp2); - state.m_repdebugeqerr=0.0; -//--- calculation - for(i=0;i<=state.m_cecnt-1;i++) - { - v=0.0; - for(i_=0;i_<=nmain+nslack-1;i_++) - v+=state.m_ceeffective[i][i_]*state.m_xcur[i_]; - state.m_repdebugeqerr=state.m_repdebugeqerr+CMath::Sqr(v-state.m_ceeffective[i][nmain+nslack]); - } - state.m_repdebugeqerr=MathSqrt(state.m_repdebugeqerr); -//--- check - if(!b) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } -//--- Initialize RepDebugFS with function value at initial point - UnscalePoint(state,state.m_xcur,state.m_x); - ClearRequestFields(state); -//--- check - if(state.m_diffstep!=0.0) - { - state.m_needf=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CMinBLEIC::Func_lbl_rcomm(CMinBLEICState &state,int nmain, - int nslack,int m,int i,int j, - bool b,double v,double vv) - { -//--- save - state.m_rstate.ia[0]=nmain; - state.m_rstate.ia[1]=nslack; - state.m_rstate.ia[2]=m; - state.m_rstate.ia[3]=i; - state.m_rstate.ia[4]=j; - state.m_rstate.ba[0]=b; - state.m_rstate.ra[0]=v; - state.m_rstate.ra[1]=vv; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_14(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- function call - COptServ::TrimPrepare(state.m_f,state.m_trimthreshold); - state.m_repnfev=state.m_repnfev+1; - state.m_repdebugfs=state.m_f; -//--- Outer cycle - state.m_itsleft=state.m_maxits; -//--- copy - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_xprev[i_]=state.m_xcur[i_]; -//--- function call, return result - return(Func_lbl_15(state,nmain,nslack,m,i,j,b,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_15(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- check - if(!CAp::Assert(state.m_prectype==0 || state.m_stpmax==0.0,"MinBLEIC: internal error (-10)")) - return(false); -//--- Inner cycle: CG with projections and penalty functions - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_tmp0[i_]=state.m_xcur[i_]; - for(i=0;i<=nmain+nslack-1;i++) - { - state.m_tmp1[i]=0; - state.m_activeconstraints[i]=false; - } -//--- check - if(!PrepareConstraintMatrix(state,state.m_tmp0,state.m_tmp1,state.m_xcur,state.m_tmp2)) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } - for(i=0;i<=nmain+nslack-1;i++) - state.m_activeconstraints[i]=false; - RebuildCEXE(state); -//--- function call - CMinCG::MinCGRestartFrom(state.m_cgstate,state.m_xcur); -//--- function call - CMinCG::MinCGSetCond(state.m_cgstate,state.m_innerepsg,state.m_innerepsf,state.m_innerepsx,state.m_itsleft); -//--- function call - CMinCG::MinCGSetXRep(state.m_cgstate,state.m_xrep); -//--- function call - CMinCG::MinCGSetDRep(state.m_cgstate,true); -//--- function call - CMinCG::MinCGSetStpMax(state.m_cgstate,state.m_stpmax); -//--- function call, return result - return(Func_lbl_17(state,nmain,nslack,m,i,j,b,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_16(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- We've stopped,fill debug information - state.m_repdebugeqerr=0.0; - for(i=0;i<=state.m_cecnt-1;i++) - { - //--- change value - v=0.0; - for(int i_=0;i_<=nmain+nslack-1;i_++) - v+=state.m_ceeffective[i][i_]*state.m_xcur[i_]; - state.m_repdebugeqerr=state.m_repdebugeqerr+CMath::Sqr(v-state.m_ceeffective[i][nmain+nslack]); - } -//--- change values - state.m_repdebugeqerr=MathSqrt(state.m_repdebugeqerr); - state.m_repdebugdx=0; - for(i=0;i<=nmain-1;i++) - state.m_repdebugdx=state.m_repdebugdx+CMath::Sqr(state.m_xcur[i]-state.m_xstart[i]); - state.m_repdebugdx=MathSqrt(state.m_repdebugdx); -//--- return result - return(false); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_17(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- check - if(!CMinCG::MinCGIteration(state.m_cgstate)) - return(Func_lbl_18(state,nmain,nslack,m,i,j,b,v,vv)); -//--- process different requests/reports of inner optimizer - if(state.m_cgstate.m_algpowerup) - { - for(i=0;i<=nmain+nslack-1;i++) - state.m_activeconstraints[i]=false; - //--- cycle - do - { - //--- function call - RebuildCEXE(state); - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_tmp1[i_]=state.m_cgstate.m_g[i_]; - //--- function call - MakeGradientProjection(state,state.m_tmp1); - b=false; - for(i=0;i<=nmain-1;i++) - { - //--- check - if(!state.m_activeconstraints[i]) - { - //--- check - if(state.m_hasbndl[i]) - { - //--- check - if(state.m_cgstate.m_x[i]==state.m_bndleffective[i] && state.m_tmp1[i]>=0.0) - { - //--- change values - state.m_activeconstraints[i]=true; - state.m_constrainedvalues[i]=state.m_bndleffective[i]; - b=true; - } - } - //--- check - if(state.m_hasbndu[i]) - { - //--- check - if(state.m_cgstate.m_x[i]==state.m_bndueffective[i] && state.m_tmp1[i]<=0.0) - { - //--- change values - state.m_activeconstraints[i]=true; - state.m_constrainedvalues[i]=state.m_bndueffective[i]; - b=true; - } - } - } - } - for(i=0;i<=nslack-1;i++) - { - //--- check - if(!state.m_activeconstraints[nmain+i]) - { - //--- check - if(state.m_cgstate.m_x[nmain+i]==0.0 && state.m_tmp1[nmain+i]>=0.0) - { - //--- change values - state.m_activeconstraints[nmain+i]=true; - state.m_constrainedvalues[nmain+i]=0; - b=true; - } - } - } - } - while(b); - //--- copy - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_cgstate.m_g[i_]=state.m_tmp1[i_]; - //--- function call, return result - return(Func_lbl_17(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_cgstate.m_lsstart) - { - //--- Beginning of the line search: set upper limit on step size - //--- to prevent algo from leaving feasible area. - state.m_variabletofreeze=-1; - //--- check - if((double)(state.m_cgstate.m_curstpmax)==0.0) - state.m_cgstate.m_curstpmax=1.0E50; - for(i=0;i<=nmain-1;i++) - { - //--- check - if(state.m_hasbndl[i] && state.m_cgstate.m_d[i]<0.0) - { - //--- change values - v=state.m_cgstate.m_curstpmax; - vv=state.m_cgstate.m_x[i]-state.m_bndleffective[i]; - //--- check - if(vv<0.0) - vv=0; - state.m_cgstate.m_curstpmax=CApServ::SafeMinPosRV(vv,-state.m_cgstate.m_d[i],state.m_cgstate.m_curstpmax); - //--- check - if(state.m_cgstate.m_curstpmax0.0) - { - //--- change values - v=state.m_cgstate.m_curstpmax; - vv=state.m_bndueffective[i]-state.m_cgstate.m_x[i]; - //--- check - if(vv<0.0) - vv=0; - state.m_cgstate.m_curstpmax=CApServ::SafeMinPosRV(vv,state.m_cgstate.m_d[i],state.m_cgstate.m_curstpmax); - //--- check - if(state.m_cgstate.m_curstpmax=state.m_cgstate.m_curstpmax && state.m_variabletofreeze>=0; - //--- check - if(b) - { - state.m_activeconstraints[state.m_variabletofreeze]=true; - state.m_constrainedvalues[state.m_variabletofreeze]=state.m_valuetofreeze; - } - //--- Additional activation of constraints - b=b || AdditionalCheckForConstraints(state,state.m_cgstate.m_x); - //--- If at least one constraint was activated we have to rebuild constraint matrices - if(b) - { - //--- copy - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_tmp0[i_]=state.m_cgstate.m_x[i_]; - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_tmp1[i_]=state.m_lastg[i_]; - //--- check - if(!PrepareConstraintMatrix(state,state.m_tmp0,state.m_tmp1,state.m_cgstate.m_x,state.m_cgstate.m_g)) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } - state.m_cgstate.m_innerresetneeded=true; - } - //--- function call, return result - return(Func_lbl_17(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(!state.m_cgstate.m_needfg) - return(Func_lbl_19(state,nmain,nslack,m,i,j,b,v,vv)); -//--- copy - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_tmp1[i_]=state.m_cgstate.m_x[i_]; -//--- function call - ProjectPointAndUnscale(state,state.m_tmp1,state.m_x,state.m_r,vv); -//--- function call - ClearRequestFields(state); -//--- check - if(state.m_diffstep!=0.0) - { - //--- change values - state.m_needf=true; - state.m_rstate.stage=3; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_18(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- function call - CMinCG::MinCGResults(state.m_cgstate,state.m_xcur,state.m_cgrep); -//--- function call - UnscalePoint(state,state.m_xcur,state.m_xend); -//--- change values - state.m_repinneriterationscount=state.m_repinneriterationscount+state.m_cgrep.m_iterationscount; - state.m_repouteriterationscount=state.m_repouteriterationscount+1; - state.m_repnfev=state.m_repnfev+state.m_cgrep.m_nfev; -//--- Update RepDebugFF with function value at current point - UnscalePoint(state,state.m_xcur,state.m_x); - ClearRequestFields(state); -//--- check - if(state.m_diffstep!=0.0) - { - //--- change values - state.m_needf=true; - state.m_rstate.stage=12; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=11; -//--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_19(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- check - if(!state.m_cgstate.m_xupdated) - return(Func_lbl_17(state,nmain,nslack,m,i,j,b,v,vv)); -//--- Report - UnscalePoint(state,state.m_cgstate.m_x,state.m_x); - state.m_f=state.m_cgstate.m_f; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=10; -//--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_22(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- check - if(state.m_fnmain-1) - { - //--- change values - state.m_f=state.m_fbase; - state.m_needf=false; - //--- function call, return result - return(Func_lbl_22(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- change values - v=state.m_x[i]; - b=false; -//--- check - if(state.m_hasbndl[i]) - b=b || v-state.m_diffstep*state.m_soriginal[i]state.m_bnduoriginal[i]; -//--- check - if(b) - { - //--- change values - state.m_xm1=MathMax(v-state.m_diffstep*state.m_soriginal[i],state.m_bndloriginal[i]); - state.m_x[i]=state.m_xm1; - state.m_rstate.stage=8; - //--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_x[i]=v-state.m_diffstep*state.m_soriginal[i]; - state.m_rstate.stage=4; -//--- Saving state - Func_lbl_rcomm(state,nmain,nslack,m,i,j,b,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinBLEICIteration. Is a product to get rid| -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinBLEIC::Func_lbl_31(CMinBLEICState &state,int &nmain, - int &nslack,int &m,int &i,int &j, - bool &b,double &v,double &vv) - { -//--- change values - state.m_repnfev=state.m_repnfev+1; - state.m_repdebugff=state.m_f; -//--- Check for stopping: -//--- * "normal",outer step size is small enough,infeasibility is within bounds -//--- * "inconsistent", if Lagrange multipliers increased beyond threshold given by MaxLagrangeMul -//--- * "too stringent",in other cases - v=0; - for(i=0;i<=nmain-1;i++) - v=v+CMath::Sqr((state.m_xcur[i]-state.m_xprev[i])/state.m_seffective[i]); - v=MathSqrt(v); -//--- check - if(v<=(double)(state.m_outerepsx)) - { - state.m_repterminationtype=4; - //--- function call, return result - return(Func_lbl_16(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- check - if(state.m_maxits>0) - { - state.m_itsleft=state.m_itsleft-state.m_cgrep.m_iterationscount; - //--- check - if(state.m_itsleft<=0) - { - state.m_repterminationtype=5; - //--- function call, return result - return(Func_lbl_16(state,nmain,nslack,m,i,j,b,v,vv)); - } - } -//--- check - if(state.m_repouteriterationscount>=m_maxouterits) - { - state.m_repterminationtype=5; - //--- function call, return result - return(Func_lbl_16(state,nmain,nslack,m,i,j,b,v,vv)); - } -//--- Next iteration - for(int i_=0;i_<=nmain+nslack-1;i_++) - state.m_xprev[i_]=state.m_xcur[i_]; -//--- function call, return result - return(Func_lbl_15(state,nmain,nslack,m,i,j,b,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CMinLBFGS | -//+------------------------------------------------------------------+ -class CMinLBFGSState - { -public: - //--- variables - int m_n; - int m_m; - double m_epsg; - double m_epsf; - double m_epsx; - int m_maxits; - bool m_xrep; - double m_stpmax; - double m_diffstep; - int m_nfev; - int m_mcstage; - int m_k; - int m_q; - int m_p; - double m_stp; - double m_fold; - double m_trimthreshold; - int m_prectype; - double m_gammak; - double m_fbase; - double m_fm2; - double m_fm1; - double m_fp1; - double m_fp2; - double m_f; - bool m_needf; - bool m_needfg; - bool m_xupdated; - RCommState m_rstate; - int m_repiterationscount; - int m_repnfev; - int m_repterminationtype; - CLinMinState m_lstate; - //--- arrays - double m_s[]; - double m_rho[]; - double m_theta[]; - double m_d[]; - double m_work[]; - double m_diagh[]; - double m_autobuf[]; - double m_x[]; - double m_g[]; - //--- matrix - CMatrixDouble m_yk; - CMatrixDouble m_sk; - CMatrixDouble m_denseh; - //--- constructor, destructor - CMinLBFGSState(void); - ~CMinLBFGSState(void); - //--- copy - void Copy(CMinLBFGSState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLBFGSState::CMinLBFGSState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLBFGSState::~CMinLBFGSState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinLBFGSState::Copy(CMinLBFGSState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_m=obj.m_m; - m_epsg=obj.m_epsg; - m_epsf=obj.m_epsf; - m_epsx=obj.m_epsx; - m_maxits=obj.m_maxits; - m_xrep=obj.m_xrep; - m_stpmax=obj.m_stpmax; - m_diffstep=obj.m_diffstep; - m_nfev=obj.m_nfev; - m_mcstage=obj.m_mcstage; - m_k=obj.m_k; - m_q=obj.m_q; - m_p=obj.m_p; - m_stp=obj.m_stp; - m_fold=obj.m_fold; - m_trimthreshold=obj.m_trimthreshold; - m_prectype=obj.m_prectype; - m_gammak=obj.m_gammak; - m_fbase=obj.m_fbase; - m_fm2=obj.m_fm2; - m_fm1=obj.m_fm1; - m_fp1=obj.m_fp1; - m_fp2=obj.m_fp2; - m_f=obj.m_f; - m_needf=obj.m_needf; - m_needfg=obj.m_needfg; - m_xupdated=obj.m_xupdated; - m_repiterationscount=obj.m_repiterationscount; - m_repnfev=obj.m_repnfev; - m_repterminationtype=obj.m_repterminationtype; - m_rstate.Copy(obj.m_rstate); - m_lstate.Copy(obj.m_lstate); -//--- copy arrays - ArrayCopy(m_s,obj.m_s); - ArrayCopy(m_rho,obj.m_rho); - ArrayCopy(m_theta,obj.m_theta); - ArrayCopy(m_d,obj.m_d); - ArrayCopy(m_work,obj.m_work); - ArrayCopy(m_diagh,obj.m_diagh); - ArrayCopy(m_autobuf,obj.m_autobuf); - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_g,obj.m_g); -//--- copy matrix - m_yk=obj.m_yk; - m_sk=obj.m_sk; - m_denseh=obj.m_denseh; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CMinLBFGSState | -//+------------------------------------------------------------------+ -class CMinLBFGSStateShell - { -private: - CMinLBFGSState m_innerobj; -public: - //--- constructors, destructor - CMinLBFGSStateShell(void); - CMinLBFGSStateShell(CMinLBFGSState &obj); - ~CMinLBFGSStateShell(void); - //--- methods - bool GetNeedF(void); - void SetNeedF(const bool b); - bool GetNeedFG(void); - void SetNeedFG(const bool b); - bool GetXUpdated(void); - void SetXUpdated(const bool b); - double GetF(void); - void SetF(const double d); - CMinLBFGSState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLBFGSStateShell::CMinLBFGSStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinLBFGSStateShell::CMinLBFGSStateShell(CMinLBFGSState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLBFGSStateShell::~CMinLBFGSStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needf | -//+------------------------------------------------------------------+ -bool CMinLBFGSStateShell::GetNeedF(void) - { -//--- return result - return(m_innerobj.m_needf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needf | -//+------------------------------------------------------------------+ -void CMinLBFGSStateShell::SetNeedF(const bool b) - { -//--- change value - m_innerobj.m_needf=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfg | -//+------------------------------------------------------------------+ -bool CMinLBFGSStateShell::GetNeedFG(void) - { -//--- return result - return(m_innerobj.m_needfg); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfg | -//+------------------------------------------------------------------+ -void CMinLBFGSStateShell::SetNeedFG(const bool b) - { -//--- change value - m_innerobj.m_needfg=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable xupdated | -//+------------------------------------------------------------------+ -bool CMinLBFGSStateShell::GetXUpdated(void) - { -//--- return result - return(m_innerobj.m_xupdated); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable xupdated | -//+------------------------------------------------------------------+ -void CMinLBFGSStateShell::SetXUpdated(const bool b) - { -//--- change value - m_innerobj.m_xupdated=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable f | -//+------------------------------------------------------------------+ -double CMinLBFGSStateShell::GetF(void) - { -//--- return result - return(m_innerobj.m_f); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable f | -//+------------------------------------------------------------------+ -void CMinLBFGSStateShell::SetF(const double d) - { -//--- change value - m_innerobj.m_f=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinLBFGSState *CMinLBFGSStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CMinLFBFGS | -//+------------------------------------------------------------------+ -class CMinLBFGSReport - { -public: - //--- variables - int m_iterationscount; - int m_nfev; - int m_terminationtype; - //--- constructor, destructor - CMinLBFGSReport(void); - ~CMinLBFGSReport(void); - //--- copy - void Copy(CMinLBFGSReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLBFGSReport::CMinLBFGSReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLBFGSReport::~CMinLBFGSReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinLBFGSReport::Copy(CMinLBFGSReport &obj) - { -//--- copy variables - m_iterationscount=obj.m_iterationscount; - m_nfev=obj.m_nfev; - m_terminationtype=obj.m_terminationtype; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CMinLBFGSReport | -//+------------------------------------------------------------------+ -class CMinLBFGSReportShell - { -private: - CMinLBFGSReport m_innerobj; -public: - //--- constructors, destructor - CMinLBFGSReportShell(void); - CMinLBFGSReportShell(CMinLBFGSReport &obj); - ~CMinLBFGSReportShell(void); - //--- methods - int GetIterationsCount(void); - void SetIterationsCount(const int i); - int GetNFev(void); - void SetNFev(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - CMinLBFGSReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLBFGSReportShell::CMinLBFGSReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinLBFGSReportShell::CMinLBFGSReportShell(CMinLBFGSReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLBFGSReportShell::~CMinLBFGSReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable iterationscount | -//+------------------------------------------------------------------+ -int CMinLBFGSReportShell::GetIterationsCount(void) - { -//--- return result - return(m_innerobj.m_iterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable iterationscount | -//+------------------------------------------------------------------+ -void CMinLBFGSReportShell::SetIterationsCount(const int i) - { -//--- change value - m_innerobj.m_iterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfev | -//+------------------------------------------------------------------+ -int CMinLBFGSReportShell::GetNFev(void) - { -//--- return result - return(m_innerobj.m_nfev); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfev | -//+------------------------------------------------------------------+ -void CMinLBFGSReportShell::SetNFev(const int i) - { -//--- change value - m_innerobj.m_nfev=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMinLBFGSReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMinLBFGSReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinLBFGSReport *CMinLBFGSReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Limited memory BFGS method for large scale optimization | -//+------------------------------------------------------------------+ -class CMinLBFGS - { -private: - //--- private method - static void ClearRequestFields(CMinLBFGSState &state); - //--- auxiliary functions for MinLBFGSiteration - static void Func_lbl_rcomm(CMinLBFGSState &state,int n,int m,int i,int j,int ic,int mcinfo,double v,double vv); - static bool Func_lbl_16(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); - static bool Func_lbl_19(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); - static bool Func_lbl_21(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); - static bool Func_lbl_23(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); - static bool Func_lbl_27(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); - static bool Func_lbl_30(CMinLBFGSState &state,int &n,int &m,int &i,int &j,int &ic,int &mcinfo,double &v,double &vv); -public: - //--- constant - static const double m_gtol; - //--- constructor, destructor - CMinLBFGS(void); - ~CMinLBFGS(void); - //--- public methods - static void MinLBFGSCreate(const int n,const int m,double &x[],CMinLBFGSState &state); - static void MinLBFGSCreateF(const int n,const int m,double &x[],const double diffstep,CMinLBFGSState &state); - static void MinLBFGSSetCond(CMinLBFGSState &state,const double epsg,const double epsf,double epsx,const int maxits); - static void MinLBFGSSetXRep(CMinLBFGSState &state,const bool needxrep); - static void MinLBFGSSetStpMax(CMinLBFGSState &state,const double stpmax); - static void MinLBFGSSetScale(CMinLBFGSState &state,double &s[]); - static void MinLBFGSCreateX(const int n,const int m,double &x[],int flags,const double diffstep,CMinLBFGSState &state); - static void MinLBFGSSetPrecDefault(CMinLBFGSState &state); - static void MinLBFGSSetPrecCholesky(CMinLBFGSState &state,CMatrixDouble &p,const bool isupper); - static void MinLBFGSSetPrecDiag(CMinLBFGSState &state,double &d[]); - static void MinLBFGSSetPrecScale(CMinLBFGSState &state); - static void MinLBFGSResults(CMinLBFGSState &state,double &x[],CMinLBFGSReport &rep); - static void MinLBFGSresultsbuf(CMinLBFGSState &state,double &x[],CMinLBFGSReport &rep); - static void MinLBFGSRestartFrom(CMinLBFGSState &state,double &x[]); - static bool MinLBFGSIteration(CMinLBFGSState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const double CMinLBFGS::m_gtol=0.4; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLBFGS::CMinLBFGS(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLBFGS::~CMinLBFGS(void) - { - - } -//+------------------------------------------------------------------+ -//| LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION | -//| DESCRIPTION: | -//| The subroutine minimizes function F(x) of N arguments by using a | -//| quasi - Newton method (LBFGS scheme) which is optimized to use a | -//| minimum amount of memory. | -//| The subroutine generates the approximation of an inverse Hessian | -//| matrix by using information about the last M steps of the | -//| algorithm (instead of N). It lessens a required amount of memory | -//| from a value of order N^2 to a value of order 2*N*M. | -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function value F and its gradient G (simultaneously) at given | -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with MinLBFGSCreate() call | -//| 2. User tunes solver parameters with MinLBFGSSetCond() | -//| MinLBFGSSetStpMax() and other functions | -//| 3. User calls MinLBFGSOptimize() function which takes algorithm | -//| state and pointer (delegate, etc.) to callback function which | -//| calculates F/G. | -//| 4. User calls MinLBFGSResults() to get solution | -//| 5. Optionally user may call MinLBFGSRestartFrom() to solve | -//| another problem with same N/M but another starting point | -//| and/or another function. MinLBFGSRestartFrom() allows to reuse| -//| already initialized structure. | -//| INPUT PARAMETERS: | -//| N - problem dimension. N>0 | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause | -//| a fall in the performance. M<=N. | -//| X - initial solution approximation, array[0..N-1]. | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLBFGSSetCond() | -//| function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLBFGSSetStpMax() function to | -//| bound algorithm's steps. However, L-BFGS rarely needs such a | -//| tuning. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSCreate(const int n,const int m,double &x[], - CMinLBFGSState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1")) - return; -//--- check - if(!CAp::Assert(m<=n,__FUNCTION__+": M>N")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0: | -//| * if given, only leading N elements of X are used| -//| * if not given, automatically determined from | -//| size of X | -//| M - number of corrections in the BFGS scheme of | -//| Hessian approximation update. Recommended value: | -//| 3<=M<=7. The smaller value causes worse | -//| convergence, the bigger will not cause a | -//| considerably better convergence, but will cause a| -//| fall in the performance. M<=N. | -//| X - starting point, array[0..N-1]. | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. algorithm uses 4-point central formula for differentiation. | -//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]| -//| where S[] is scaling vector which can be set by | -//| MinLBFGSSetScale() call. | -//| 3. we recommend you to use moderate values of differentiation | -//| step. Too large step will result in too large truncation | -//| errors, while too small step will result in too large | -//| numerical errors. 1.0E-6 can be good value to start with. | -//| 4. Numerical differentiation is very inefficient - one gradient | -//| calculation needs 4*N function evaluations. This function will| -//| work for any N - either small (1...10), moderate (10...100) or| -//| large (100...). However, performance penalty will be too | -//| severe for any N's except for small ones. | -//| We should also say that code which relies on numerical | -//| differentiation is less robust and precise. LBFGS needs exact | -//| gradient values. Imprecise gradient may slow down convergence,| -//| especially on highly nonlinear problems. | -//| Thus we recommend to use this function for fast prototyping on| -//| small- dimensional problems only, and to implement analytical | -//| gradient as soon as possible. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSCreateF(const int n,const int m,double &x[], - const double diffstep,CMinLBFGSState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N too small!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1")) - return; -//--- check - if(!CAp::Assert(m<=n,__FUNCTION__+": M>N")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0.0,__FUNCTION__+": DiffStep is non-positive!")) - return; -//--- function call - MinLBFGSCreateX(n,m,x,0,diffstep,state); - } -//+------------------------------------------------------------------+ -//| This function sets stopping conditions for L-BFGS optimization | -//| algorithm. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| EpsG - >=0 | -//| The subroutine finishes its work if the condition| -//| |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by | -//| MinLBFGSSetScale() | -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetCond(CMinLBFGSState &state,const double epsg, - const double epsf,double epsx, - const int maxits) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsg),__FUNCTION__+": EpsG is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsg>=0.0,__FUNCTION__+": negative EpsG!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsx>=0.0,__FUNCTION__+": negative EpsX!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- check - if(((epsg==0.0 && epsf==0.0) && epsx==0.0) && maxits==0) - epsx=1.0E-6; -//--- change values - state.m_epsg=epsg; - state.m_epsf=epsf; - state.m_epsx=epsx; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinLBFGSOptimize(). | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetXRep(CMinLBFGSState &state,const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0 | -//| (default), if you don't want to limit step | -//| length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetStpMax(CMinLBFGSState &state, - const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for LBFGS optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Scaling is also used by finite difference variant of the | -//| optimizer - step along I-th axis is equal to DiffStep*S[I]. | -//| In most optimizers (and in the LBFGS too) scaling is NOT a form | -//| of preconditioning. It just affects stopping conditions. You | -//| should set preconditioner by separate call to one of the | -//| MinLBFGSSetPrec...() functions. | -//| There is special preconditioning mode, however, which uses | -//| scaling coefficients to form diagonal preconditioning matrix. | -//| You can turn this mode on, if you want. But you should | -//| understand that scaling is not the same thing as | -//| preconditioning - these are two different, although related | -//| forms of tuning solver. | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetScale(CMinLBFGSState &state,double &s[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(s)>=state.m_n,__FUNCTION__+": Length(S)=1,__FUNCTION__+": N too small!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M too small!")) - return; -//--- check - if(!CAp::Assert(m<=n,__FUNCTION__+": M too large!")) - return; -//--- Initialize - state.m_diffstep=diffstep; - state.m_n=n; - state.m_m=m; - allocatemem=flags%2==0; - flags=flags/2; -//--- check - if(allocatemem) - { - //--- allocation - ArrayResizeAL(state.m_rho,m); - ArrayResizeAL(state.m_theta,m); - state.m_yk.Resize(m,n); - state.m_sk.Resize(m,n); - ArrayResizeAL(state.m_d,n); - ArrayResizeAL(state.m_x,n); - ArrayResizeAL(state.m_s,n); - ArrayResizeAL(state.m_g,n); - ArrayResizeAL(state.m_work,n); - } -//--- function call - MinLBFGSSetCond(state,0,0,0,0); -//--- function call - MinLBFGSSetXRep(state,false); -//--- function call - MinLBFGSSetStpMax(state,0); -//--- function call - MinLBFGSRestartFrom(state,x); -//--- change values - for(i=0;i<=n-1;i++) - state.m_s[i]=1.0; - state.m_prectype=0; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: default preconditioner | -//| (simple scaling, same for all elements of X) is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetPrecDefault(CMinLBFGSState &state) - { -//--- change value - state.m_prectype=0; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: Cholesky factorization of | -//| approximate Hessian is used. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| P - triangular preconditioner, Cholesky factorization| -//| of the approximate Hessian. array[0..N-1,0..N-1],| -//| (if larger, only leading N elements are used). | -//| IsUpper - whether upper or lower triangle of P is given | -//| (other triangle is not referenced) | -//| After call to this function preconditioner is changed to P (P is | -//| copied into the internal buffer). | -//| NOTE: you can change preconditioner "on the fly", during | -//| algorithm iterations. | -//| NOTE 2: P should be nonsingular. Exception will be thrown | -//| otherwise. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetPrecCholesky(CMinLBFGSState &state, - CMatrixDouble &p, - const bool isupper) - { -//--- create variables - int i=0; - double mx=0; -//--- check - if(!CAp::Assert(CApServ::IsFiniteRTrMatrix(p,state.m_n,isupper),__FUNCTION__+": P contains infinite or NAN values!")) - return; -//--- initialization - mx=0; - for(i=0;i<=state.m_n-1;i++) - mx=MathMax(mx,MathAbs(p[i][i])); -//--- check - if(!CAp::Assert((double)(mx)>0.0,__FUNCTION__+": P is strictly singular!")) - return; -//--- check - if(CAp::Rows(state.m_denseh)=state.m_n,__FUNCTION__+": D is too short")) - return; - for(i=0;i<=state.m_n-1;i++) - { - //--- check - if(!CAp::Assert(CMath::IsFinite(d[i]),__FUNCTION__+": D contains infinite or NAN elements")) - return; - //--- check - if(!CAp::Assert((double)(d[i])>0.0,__FUNCTION__+": D contains non-positive elements")) - return; - } -//--- function call - CApServ::RVectorSetLengthAtLeast(state.m_diagh,state.m_n); -//--- change values - state.m_prectype=2; - for(i=0;i<=state.m_n-1;i++) - state.m_diagh[i]=d[i]; - } -//+------------------------------------------------------------------+ -//| Modification of the preconditioner: scale-based diagonal | -//| preconditioning. | -//| This preconditioning mode can be useful when you don't have | -//| approximate diagonal of Hessian, but you know that your variables| -//| are badly scaled (for example, one variable is in [1,10], and | -//| another in [1000,100000]), and most part of the ill-conditioning | -//| comes from different scales of vars. | -//| In this case simple scale-based preconditioner, with H[i] = | -//| = 1/(s[i]^2), can greatly improve convergence. | -//| IMPRTANT: you should set scale of your variables with | -//| MinLBFGSSetScale() call (before or after MinLBFGSSetPrecScale() | -//| call). Without knowledge of the scale of your variables | -//| scale-based preconditioner will be just unit matrix. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSSetPrecScale(CMinLBFGSState &state) - { -//--- change values - state.m_prectype=3; - } -//+------------------------------------------------------------------+ -//| L-BFGS algorithm results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * -2 rounding errors prevent further | -//| improvement. X contains best point | -//| found. | -//| * -1 incorrect parameters were specified | -//| * 1 relative function improvement is no | -//| more than EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient norm is no more than EpsG | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSResults(CMinLBFGSState &state,double &x[], - CMinLBFGSReport &rep) - { -//--- reset memory - ArrayResizeAL(x,0); -//--- function call - MinLBFGSresultsbuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| L-BFGS algorithm results | -//| Buffered implementation of MinLBFGSResults which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::MinLBFGSresultsbuf(CMinLBFGSState &state,double &x[], - CMinLBFGSReport &rep) - { -//--- create a variable - int i_=0; -//--- check - if(CAp::Len(x)=state.m_n,__FUNCTION__+": Length(X)=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - m=state.m_rstate.ia[1]; - i=state.m_rstate.ia[2]; - j=state.m_rstate.ia[3]; - ic=state.m_rstate.ia[4]; - mcinfo=state.m_rstate.ia[5]; - v=state.m_rstate.ra[0]; - vv=state.m_rstate.ra[1]; - } - else - { - //--- initialization - n=-983; - m=-989; - i=-834; - j=900; - ic=-287; - mcinfo=364; - v=214; - vv=-338; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needfg=false; - //--- function call - COptServ::TrimPrepare(state.m_f,state.m_trimthreshold); - //--- check - if(!state.m_xrep) - return(Func_lbl_19(state,n,m,i,j,ic,mcinfo,v,vv)); - //--- function call - ClearRequestFields(state); - //--- change values - state.m_xupdated=true; - state.m_rstate.stage=6; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change values - state.m_fbase=state.m_f; - i=0; - //--- function call, return result - return(Func_lbl_16(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change values - state.m_fm2=state.m_f; - state.m_x[i]=v-0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=3; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change values - state.m_fm1=state.m_f; - state.m_x[i]=v+0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=4; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change values - state.m_fp1=state.m_f; - state.m_x[i]=v+state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=5; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change values - state.m_fp2=state.m_f; - state.m_x[i]=v; - state.m_g[i]=(8*(state.m_fp1-state.m_fm1)-(state.m_fp2-state.m_fm2))/(6*state.m_diffstep*state.m_s[i]); - i=i+1; - //--- function call, return result - return(Func_lbl_16(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_19(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==7) - { - //--- change value - state.m_needfg=false; - //--- function call - COptServ::TrimFunction(state.m_f,state.m_g,n,state.m_trimthreshold); - //--- function call - CLinMin::MCSrch(n,state.m_x,state.m_f,state.m_g,state.m_d,state.m_stp,state.m_stpmax,m_gtol,mcinfo,state.m_nfev,state.m_work,state.m_lstate,state.m_mcstage); - //--- function call, return result - return(Func_lbl_23(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==8) - { - //--- change values - state.m_fbase=state.m_f; - i=0; - //--- function call, return result - return(Func_lbl_27(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==9) - { - //--- change values - state.m_fm2=state.m_f; - state.m_x[i]=v-0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=10; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==10) - { - //--- change values - state.m_fm1=state.m_f; - state.m_x[i]=v+0.5*state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=11; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==11) - { - //--- change values - state.m_fp1=state.m_f; - state.m_x[i]=v+state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=12; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==12) - { - //--- change values - state.m_fp2=state.m_f; - state.m_x[i]=v; - state.m_g[i]=(8*(state.m_fp1-state.m_fm1)-(state.m_fp2-state.m_fm2))/(6*state.m_diffstep*state.m_s[i]); - i=i+1; - //--- function call, return result - return(Func_lbl_27(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- check - if(state.m_rstate.stage==13) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_30(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- Routine body -//--- Unload frequently used variables from State structure -//--- (just for typing convinience) - n=state.m_n; - m=state.m_m; - state.m_repterminationtype=0; - state.m_repiterationscount=0; - state.m_repnfev=0; -//--- Calculate F/G at the initial point - ClearRequestFields(state); -//--- check - if(state.m_diffstep!=0.0) - { - //--- change values - state.m_needf=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CMinLBFGS::Func_lbl_rcomm(CMinLBFGSState &state,int n,int m, - int i,int j,int ic,int mcinfo, - double v,double vv) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=m; - state.m_rstate.ia[2]=i; - state.m_rstate.ia[3]=j; - state.m_rstate.ia[4]=ic; - state.m_rstate.ia[5]=mcinfo; - state.m_rstate.ra[0]=v; - state.m_rstate.ra[1]=vv; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_16(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- check - if(i>n-1) - { - //--- change values - state.m_f=state.m_fbase; - state.m_needf=false; - //--- function call - COptServ::TrimPrepare(state.m_f,state.m_trimthreshold); - //--- check - if(!state.m_xrep) - return(Func_lbl_19(state,n,m,i,j,ic,mcinfo,v,vv)); - //--- function call - ClearRequestFields(state); - //--- change values - state.m_xupdated=true; - state.m_rstate.stage=6; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- change values - v=state.m_x[i]; - state.m_x[i]=v-state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_19(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- change values - state.m_repnfev=1; - state.m_fold=state.m_f; -//--- calculation - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_g[i]*state.m_s[i]); -//--- check - if(MathSqrt(v)<=state.m_epsg) - { - state.m_repterminationtype=4; - //--- return result - return(false); - } -//--- Choose initial step and direction. -//--- Apply preconditioner, if we have something other than default. - for(int i_=0;i_<=n-1;i_++) - state.m_d[i_]=-state.m_g[i_]; -//--- check - if(state.m_prectype==0) - { - //--- Default preconditioner is used, but we can't use it before iterations will start - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_g[i_]*state.m_g[i_]; - v=MathSqrt(v); - //--- check - if(state.m_stpmax==0.0) - state.m_stp=MathMin(1.0/v,1); - else - state.m_stp=MathMin(1.0/v,state.m_stpmax); - } -//--- check - if(state.m_prectype==1) - { - //--- Cholesky preconditioner is used - CFbls::FblsCholeskySolve(state.m_denseh,1.0,n,true,state.m_d,state.m_autobuf); - state.m_stp=1; - } -//--- check - if(state.m_prectype==2) - { - //--- diagonal approximation is used - for(i=0;i<=n-1;i++) - state.m_d[i]=state.m_d[i]/state.m_diagh[i]; - state.m_stp=1; - } -//--- check - if(state.m_prectype==3) - { - //--- scale-based preconditioner is used - for(i=0;i<=n-1;i++) - state.m_d[i]=state.m_d[i]*state.m_s[i]*state.m_s[i]; - state.m_stp=1; - } -//--- Main cycle - state.m_k=0; -//--- function call, return result - return(Func_lbl_21(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_21(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- Main cycle: prepare to 1-D line search - state.m_p=state.m_k % m; - state.m_q=MathMin(state.m_k, m-1); -//--- Store X[k], G[k] - for(int i_=0;i_<=n-1;i_++) - state.m_sk[state.m_p].Set(i_,-state.m_x[i_]); - for(int i_=0;i_<=n-1;i_++) - state.m_yk[state.m_p].Set(i_,-state.m_g[i_]); -//--- Minimize F(x+alpha*d) -//--- Calculate S[k], Y[k] - state.m_mcstage=0; -//--- check - if(state.m_k!=0) - state.m_stp=1.0; -//--- function call - CLinMin::LinMinNormalized(state.m_d,state.m_stp,n); -//--- function call - CLinMin::MCSrch(n,state.m_x,state.m_f,state.m_g,state.m_d,state.m_stp,state.m_stpmax,m_gtol,mcinfo,state.m_nfev,state.m_work,state.m_lstate,state.m_mcstage); -//--- function call, return result - return(Func_lbl_23(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_23(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- check - if(state.m_mcstage==0) - { - //--- check - if(!state.m_xrep) - return(Func_lbl_30(state,n,m,i,j,ic,mcinfo,v,vv)); - //--- report - ClearRequestFields(state); - //--- change values - state.m_xupdated=true; - state.m_rstate.stage=13; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- function call - ClearRequestFields(state); -//--- check - if((double)(state.m_diffstep)!=0.0) - { - //--- change values - state.m_needf=true; - state.m_rstate.stage=8; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); - //--- return result - return(true); - } -//--- change values - state.m_needfg=true; - state.m_rstate.stage=7; -//--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_27(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- check - if(i>n-1) - { - //--- change values - state.m_f=state.m_fbase; - state.m_needf=false; - //--- function call - COptServ::TrimFunction(state.m_f,state.m_g,n,state.m_trimthreshold); - //--- function call - CLinMin::MCSrch(n,state.m_x,state.m_f,state.m_g,state.m_d,state.m_stp,state.m_stpmax,m_gtol,mcinfo,state.m_nfev,state.m_work,state.m_lstate,state.m_mcstage); - //--- function call, return result - return(Func_lbl_23(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//--- change values - v=state.m_x[i]; - state.m_x[i]=v-state.m_diffstep*state.m_s[i]; - state.m_rstate.stage=9; -//--- Saving state - Func_lbl_rcomm(state,n,m,i,j,ic,mcinfo,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLBFGSIteration. Is a product to get | -//| rid of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLBFGS::Func_lbl_30(CMinLBFGSState &state,int &n,int &m, - int &i,int &j,int &ic,int &mcinfo, - double &v,double &vv) - { -//--- change values - state.m_repnfev=state.m_repnfev+state.m_nfev; - state.m_repiterationscount=state.m_repiterationscount+1; -//--- calculation - for(int i_=0;i_<=n-1;i_++) - state.m_sk[state.m_p].Set(i_,state.m_sk[state.m_p][i_]+state.m_x[i_]); - for(int i_=0;i_<=n-1;i_++) - state.m_yk[state.m_p].Set(i_,state.m_yk[state.m_p][i_]+state.m_g[i_]); -//--- Stopping conditions - if(state.m_repiterationscount>=state.m_maxits&&state.m_maxits>0) - { - //--- Too many iterations - state.m_repterminationtype=5; - //--- return result - return(false); - } -//--- change value - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_g[i]*state.m_s[i]); -//--- check - if(MathSqrt(v)<=state.m_epsg) - { - //--- Gradient is small enough - state.m_repterminationtype=4; - //--- return result - return(false); - } -//--- check - if(state.m_fold-state.m_f<=state.m_epsf*MathMax(MathAbs(state.m_fold),MathMax(MathAbs(state.m_f),1.0))) - { - //--- F(k+1)-F(k) is small enough - state.m_repterminationtype=1; - //--- return result - return(false); - } -//--- change value - v=0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_sk[state.m_p][i]/state.m_s[i]); -//--- check - if((double)(MathSqrt(v))<=(double)(state.m_epsx)) - { - //--- X(k+1)-X(k) is small enough - state.m_repterminationtype=2; - //--- return result - return(false); - } -//--- If Wolfe conditions are satisfied, we can update -//--- limited memory model. -//--- However, if conditions are not satisfied (NFEV limit is met, -//--- function is too wild, ...), we'll skip L-BFGS update - if(mcinfo!=1) - { - //--- Skip update. - //--- In such cases we'll initialize search direction by - //--- antigradient vector, because it leads to more - //--- transparent code with less number of special cases - state.m_fold=state.m_f; - for(int i_=0;i_<=n-1;i_++) - state.m_d[i_]=-state.m_g[i_]; - } - else - { - //--- Calculate Rho[k], GammaK - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_yk[state.m_p][i_]*state.m_sk[state.m_p][i_]; - //--- change value - vv=0.0; - for(int i_=0;i_<=n-1;i_++) - vv+=state.m_yk[state.m_p][i_]*state.m_yk[state.m_p][i_]; - //--- check - if(v==0.0 || vv==0.0) - { - //--- Rounding errors make further iterations impossible. - state.m_repterminationtype=-2; - //--- return result - return(false); - } - //--- change values - state.m_rho[state.m_p]=1/v; - state.m_gammak=v/vv; - //--- Calculate d(k+1)=-H(k+1)*g(k+1) - //--- for I:=K downto K-Q do - //--- V=s(i)^T * work(iteration:I) - //--- theta(i)=V - //--- work(iteration:I+1)=work(iteration:I)-V*Rho(i)*y(i) - //--- work(last iteration)=H0*work(last iteration)-preconditioner - //--- for I:=K-Q to K do - //--- V=y(i)^T*work(iteration:I) - //--- work(iteration:I+1)=work(iteration:I) +(-V+theta(i))*Rho(i)*s(i) - //--- NOW WORK CONTAINS d(k+1) - for(int i_=0;i_<=n-1;i_++) - state.m_work[i_]=state.m_g[i_]; - for(i=state.m_k;i>=state.m_k-state.m_q;i--) - { - ic=i%m; - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_sk[ic][i_]*state.m_work[i_]; - //--- change values - state.m_theta[ic]=v; - vv=v*state.m_rho[ic]; - for(int i_=0;i_<=n-1;i_++) - state.m_work[i_]=state.m_work[i_]-vv*state.m_yk[ic][i_]; - } - //--- check - if(state.m_prectype==0) - { - //--- Simple preconditioner is used - v=state.m_gammak; - for(int i_=0;i_<=n-1;i_++) - state.m_work[i_]=v*state.m_work[i_]; - } - //--- check - if(state.m_prectype==1) - { - //--- Cholesky preconditioner is used - CFbls::FblsCholeskySolve(state.m_denseh,1,n,true,state.m_work,state.m_autobuf); - } - //--- check - if(state.m_prectype==2) - { - //--- diagonal approximation is used - for(i=0;i<=n-1;i++) - { - state.m_work[i]=state.m_work[i]/state.m_diagh[i]; - } - } - //--- check - if(state.m_prectype==3) - { - //--- scale-based preconditioner is used - for(i=0;i<=n-1;i++) - state.m_work[i]=state.m_work[i]*state.m_s[i]*state.m_s[i]; - } - //--- calculation - for(i=state.m_k-state.m_q;i<=state.m_k;i++) - { - ic=i%m; - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_yk[ic][i_]*state.m_work[i_]; - //--- change value - vv=state.m_rho[ic]*(-v+state.m_theta[ic]); - for(int i_=0;i_<=n-1;i_++) - { - state.m_work[i_]=state.m_work[i_]+vv*state.m_sk[ic][i_]; - } - } - for(int i_=0;i_<=n-1;i_++) - state.m_d[i_]=-state.m_work[i_]; - //--- Next step - state.m_fold=state.m_f; - state.m_k=state.m_k+1; - } -//--- function call, return result - return(Func_lbl_21(state,n,m,i,j,ic,mcinfo,v,vv)); - } -//+------------------------------------------------------------------+ -//| This object stores nonlinear optimizer state. | -//| You should use functions provided by MinQP subpackage to work | -//| with this object | -//+------------------------------------------------------------------+ -class CMinQPState - { -public: - //--- variables - int m_n; - int m_algokind; - int m_akind; - bool m_havex; - double m_constterm; - int m_repinneriterationscount; - int m_repouteriterationscount; - int m_repncholesky; - int m_repnmv; - int m_repterminationtype; - CApBuff m_buf; - //--- arrays - double m_diaga[]; - double m_b[]; - double m_bndl[]; - double m_bndu[]; - bool m_havebndl[]; - bool m_havebndu[]; - double m_xorigin[]; - double m_startx[]; - double m_xc[]; - double m_gc[]; - int m_activeconstraints[]; - int m_prevactiveconstraints[]; - double m_workbndl[]; - double m_workbndu[]; - double m_tmp0[]; - double m_tmp1[]; - int m_itmp0[]; - int m_p2[]; - double m_bufb[]; - double m_bufx[]; - //--- matrix - CMatrixDouble m_densea; - CMatrixDouble m_bufa; - //--- constructor, destructor - CMinQPState(void); - ~CMinQPState(void); - //--- copy - void Copy(CMinQPState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinQPState::CMinQPState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinQPState::~CMinQPState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinQPState::Copy(CMinQPState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_algokind=obj.m_algokind; - m_akind=obj.m_akind; - m_havex=obj.m_havex; - m_constterm=obj.m_constterm; - m_repinneriterationscount=obj.m_repinneriterationscount; - m_repouteriterationscount=obj.m_repouteriterationscount; - m_repncholesky=obj.m_repncholesky; - m_repnmv=obj.m_repnmv; - m_repterminationtype=obj.m_repterminationtype; - m_buf.Copy(obj.m_buf); -//--- copy arrays - ArrayCopy(m_diaga,obj.m_diaga); - ArrayCopy(m_b,obj.m_b); - ArrayCopy(m_bndl,obj.m_bndl); - ArrayCopy(m_bndu,obj.m_bndu); - ArrayCopy(m_havebndl,obj.m_havebndl); - ArrayCopy(m_havebndu,obj.m_havebndu); - ArrayCopy(m_xorigin,obj.m_xorigin); - ArrayCopy(m_startx,obj.m_startx); - ArrayCopy(m_xc,obj.m_xc); - ArrayCopy(m_gc,obj.m_gc); - ArrayCopy(m_activeconstraints,obj.m_activeconstraints); - ArrayCopy(m_prevactiveconstraints,obj.m_prevactiveconstraints); - ArrayCopy(m_workbndl,obj.m_workbndl); - ArrayCopy(m_workbndu,obj.m_workbndu); - ArrayCopy(m_tmp0,obj.m_tmp0); - ArrayCopy(m_tmp1,obj.m_tmp1); - ArrayCopy(m_itmp0,obj.m_itmp0); - ArrayCopy(m_p2,obj.m_p2); - ArrayCopy(m_bufb,obj.m_bufb); - ArrayCopy(m_bufx,obj.m_bufx); -//--- copy matrix - m_densea=obj.m_densea; - m_bufa=obj.m_bufa; - } -//+------------------------------------------------------------------+ -//| This object stores nonlinear optimizer state. | -//| You should use functions provided by MinQP subpackage to work | -//| with this object | -//+------------------------------------------------------------------+ -class CMinQPStateShell - { -private: - CMinQPState m_innerobj; -public: - //--- constructors, destructor - CMinQPStateShell(void); - CMinQPStateShell(CMinQPState &obj); - ~CMinQPStateShell(void); - //--- method - CMinQPState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinQPStateShell::CMinQPStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinQPStateShell::CMinQPStateShell(CMinQPState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinQPStateShell::~CMinQPStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinQPState *CMinQPStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| This structure stores optimization report: | -//| * InnerIterationsCount number of inner iterations | -//| * OuterIterationsCount number of outer iterations | -//| * NCholesky number of Cholesky decomposition | -//| * NMV number of matrix-vector products | -//| (only products calculated as part of | -//| iterative process are counted) | -//| * TerminationType completion code (see below) | -//| Completion codes: | -//| * -5 inappropriate solver was used: | -//| * Cholesky solver for semidefinite or indefinite problems| -//| * Cholesky solver for problems with non-boundary | -//| constraints | -//| * -3 inconsistent constraints (or, maybe, feasible point is | -//| too hard to find). If you are sure that constraints are | -//| feasible, try to restart optimizer with better initial | -//| approximation. | -//| * 4 successful completion | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too stringent, | -//| further improvement is impossible, | -//| X contains best point found so far. | -//+------------------------------------------------------------------+ -class CMinQPReport - { -public: - //--- variables - int m_inneriterationscount; - int m_outeriterationscount; - int m_nmv; - int m_ncholesky; - int m_terminationtype; - //--- constructor, destructor - CMinQPReport(void); - ~CMinQPReport(void); - //--- copy - void Copy(CMinQPReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinQPReport::CMinQPReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinQPReport::~CMinQPReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinQPReport::Copy(CMinQPReport &obj) - { -//--- copy variables - m_inneriterationscount=obj.m_inneriterationscount; - m_outeriterationscount=obj.m_outeriterationscount; - m_nmv=obj.m_nmv; - m_ncholesky=obj.m_ncholesky; - m_terminationtype=obj.m_terminationtype; - } -//+------------------------------------------------------------------+ -//| This structure stores optimization report: | -//| * InnerIterationsCount number of inner iterations | -//| * OuterIterationsCount number of outer iterations | -//| * NCholesky number of Cholesky decomposition | -//| * NMV number of matrix-vector products | -//| (only products calculated as part of | -//| iterative process are counted) | -//| * TerminationType completion code (see below) | -//| Completion codes: | -//| * -5 inappropriate solver was used: | -//| * Cholesky solver for semidefinite or indefinite problems| -//| * Cholesky solver for problems with non-boundary | -//| constraints | -//| * -3 inconsistent constraints (or, maybe, feasible point is | -//| too hard to find). If you are sure that constraints are | -//| feasible, try to restart optimizer with better initial | -//| approximation. | -//| * 4 successful completion | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too stringent, | -//| further improvement is impossible, | -//| X contains best point found so far. | -//+------------------------------------------------------------------+ -class CMinQPReportShell - { -private: - CMinQPReport m_innerobj; -public: - //--- constructors, destructor - CMinQPReportShell(void); - CMinQPReportShell(CMinQPReport &obj); - ~CMinQPReportShell(void); - //--- methods - int GetInnerIterationsCount(void); - void SetInnerIterationsCount(const int i); - int GetOuterIterationsCount(void); - void SetOuterIterationsCount(const int i); - int GetNMV(void); - void SetNMV(const int i); - int GetNCholesky(void); - void SetNCholesky(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - CMinQPReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinQPReportShell::CMinQPReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinQPReportShell::CMinQPReportShell(CMinQPReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinQPReportShell::~CMinQPReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -int CMinQPReportShell::GetInnerIterationsCount(void) - { -//--- return result - return(m_innerobj.m_inneriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable inneriterationscount | -//+------------------------------------------------------------------+ -void CMinQPReportShell::SetInnerIterationsCount(const int i) - { -//--- change value - m_innerobj.m_inneriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -int CMinQPReportShell::GetOuterIterationsCount(void) - { -//--- return result - return(m_innerobj.m_outeriterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable outeriterationscount | -//+------------------------------------------------------------------+ -void CMinQPReportShell::SetOuterIterationsCount(const int i) - { -//--- change value - m_innerobj.m_outeriterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nmv | -//+------------------------------------------------------------------+ -int CMinQPReportShell::GetNMV(void) - { -//--- return result - return(m_innerobj.m_nmv); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nmv | -//+------------------------------------------------------------------+ -void CMinQPReportShell::SetNMV(const int i) - { -//--- change value - m_innerobj.m_nmv=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ncholesky | -//+------------------------------------------------------------------+ -int CMinQPReportShell::GetNCholesky(void) - { -//--- return result - return(m_innerobj.m_ncholesky); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ncholesky | -//+------------------------------------------------------------------+ -void CMinQPReportShell::SetNCholesky(const int i) - { -//--- change value - m_innerobj.m_ncholesky=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMinQPReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMinQPReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinQPReport *CMinQPReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Constrained quadratic programming | -//+------------------------------------------------------------------+ -class CMinQP - { -private: - //--- private methods - static void MinQPGrad(CMinQPState &state); - static double MinQPXTAX(CMinQPState &state,double &x[]); -public: - //--- constructor, destructor - CMinQP(void); - ~CMinQP(void); - //--- public methods - static void MinQPCreate(const int n,CMinQPState &state); - static void MinQPSetLinearTerm(CMinQPState &state,double &b[]); - static void MinQPSetQuadraticTerm(CMinQPState &state,CMatrixDouble &a,const bool isupper); - static void MinQPSetStartingPoint(CMinQPState &state,double &x[]); - static void MinQPSetOrigin(CMinQPState &state,double &xorigin[]); - static void MinQPSetAlgoCholesky(CMinQPState &state); - static void MinQPSetBC(CMinQPState &state,double &bndl[],double &bndu[]); - static void MinQPOptimize(CMinQPState &state); - static void MinQPResults(CMinQPState &state,double &x[],CMinQPReport &rep); - static void MinQPResultsBuf(CMinQPState &state,double &x[],CMinQPReport &rep); - static void MinQPSetLinearTermFast(CMinQPState &state,double &b[]); - static void MinQPSetQuadraticTermFast(CMinQPState &state,CMatrixDouble &a,const bool isupper,const double s); - static void MinQPRewriteDiagonal(CMinQPState &state,double &s[]); - static void MinQPSetStartingPointFast(CMinQPState &state,double &x[]); - static void MinQPSetOriginFast(CMinQPState &state,double &xorigin[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinQP::CMinQP(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinQP::~CMinQP(void) - { - - } -//+------------------------------------------------------------------+ -//| CONSTRAINED QUADRATIC PROGRAMMING | -//| The subroutine creates QP optimizer. After initial creation, it | -//| contains default optimization problem with zero quadratic and | -//| linear terms and no constraints. You should set quadratic/linear | -//| terms with calls to functions provided by MinQP subpackage. | -//| INPUT PARAMETERS: | -//| N - problem size | -//| OUTPUT PARAMETERS: | -//| State - optimizer with zero quadratic/linear terms | -//| and no constraints | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPCreate(const int n,CMinQPState &state) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1")) - return; -//--- initialize QP solver - state.m_n=n; - state.m_akind=-1; - state.m_repterminationtype=0; -//--- allocation - ArrayResizeAL(state.m_b,n); - ArrayResizeAL(state.m_bndl,n); - ArrayResizeAL(state.m_bndu,n); - ArrayResizeAL(state.m_workbndl,n); - ArrayResizeAL(state.m_workbndu,n); - ArrayResizeAL(state.m_havebndl,n); - ArrayResizeAL(state.m_havebndu,n); - ArrayResizeAL(state.m_startx,n); - ArrayResizeAL(state.m_xorigin,n); - ArrayResizeAL(state.m_xc,n); - ArrayResizeAL(state.m_gc,n); -//--- initialization - for(i=0;i<=n-1;i++) - { - state.m_b[i]=0.0; - state.m_workbndl[i]=CInfOrNaN::NegativeInfinity(); - state.m_workbndu[i]=CInfOrNaN::PositiveInfinity(); - state.m_havebndl[i]=false; - state.m_havebndu[i]=false; - state.m_startx[i]=0.0; - state.m_xorigin[i]=0.0; - } - state.m_havex=false; -//--- function call - MinQPSetAlgoCholesky(state); - } -//+------------------------------------------------------------------+ -//| This function sets linear term for QP solver. | -//| By default, linear term is zero. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| B - linear term, array[N]. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPSetLinearTerm(CMinQPState &state,double &b[]) - { -//--- create a variable - int n=0; -//--- initialization - n=state.m_n; -//--- check - if(!CAp::Assert(CAp::Len(b)>=n,__FUNCTION__+": Length(B)=n,__FUNCTION__+": Rows(A)=n,__FUNCTION__+": Cols(A)=n,__FUNCTION__+": Length(B)=n,__FUNCTION__+": Length(B)=n,__FUNCTION__+": Length(BndL)=n,__FUNCTION__+": Length(BndU)state.m_bndu[i]) - { - state.m_repterminationtype=-3; - return; - } - } - } -//--- count number of bound and linear constraints - nbc=0; - nlc=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_havebndl[i]) - nbc=nbc+1; - //--- check - if(state.m_havebndu[i]) - nbc=nbc+1; - } -//--- Our formulation of quadratic problem includes origin point, -//--- i.m_e. we have F(x-x_origin) which is minimized subject to -//--- constraints on x,instead of having simply F(x). -//--- Here we make transition from non-zero origin to zero one. -//--- In order to make such transition we have to: -//--- 1. subtract x_origin from x_start -//--- 2. modify constraints -//--- 3. solve problem -//--- 4. add x_origin to solution -//--- There is alternate solution - to modify quadratic function -//--- by expansion of multipliers containing (x-x_origin),but -//--- we prefer to modify constraints,because it is a) more precise -//--- and b) easier to to. -//--- Parts (1)-(2) are done here. After this block is over, -//--- we have: -//--- * XC,which stores shifted XStart (if we don't have XStart, -//--- value of XC will be ignored later) -//--- * WorkBndL,WorkBndU,which store modified boundary constraints. - for(i=0;i<=n-1;i++) - { - state.m_xc[i]=state.m_startx[i]-state.m_xorigin[i]; - //--- check - if(state.m_havebndl[i]) - state.m_workbndl[i]=state.m_bndl[i]-state.m_xorigin[i]; - //--- check - if(state.m_havebndu[i]) - state.m_workbndu[i]=state.m_bndu[i]-state.m_xorigin[i]; - } -//--- modify starting point XC according to boundary constraints - if(state.m_havex) - { - //--- We have starting point in XC,so we just have to bound it - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_havebndl[i]) - { - //--- check - if(state.m_xc[i]state.m_workbndu[i]) - state.m_xc[i]=state.m_workbndu[i]; - } - } - } - else - { - //--- We don't have starting point,so we deduce it from - //--- constraints (if they are present). - //--- NOTE: XC contains some meaningless values from previous block - //--- which are ignored by code below. - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_havebndl[i] && state.m_havebndu[i]) - { - state.m_xc[i]=0.5*(state.m_workbndl[i]+state.m_workbndu[i]); - //--- check - if(state.m_xc[i]state.m_workbndu[i]) - state.m_xc[i]=state.m_workbndu[i]; - //--- continue iteration - continue; - } - //--- check - if(state.m_havebndl[i]) - { - state.m_xc[i]=state.m_workbndl[i]; - continue; - } - //--- check - if(state.m_havebndu[i]) - { - state.m_xc[i]=state.m_workbndu[i]; - continue; - } - state.m_xc[i]=0; - } - } -//--- Select algo - if(state.m_algokind==1 && state.m_akind==0) - { - //--- Cholesky-based algorithm for dense bound constrained problems. - //--- This algorithm exists in two variants: - //--- * unconstrained one,which can solve problem using only one NxN - //--- double matrix - //--- * bound constrained one,which needs two NxN matrices - //--- We will try to solve problem using unconstrained algorithm, - //--- and will use bound constrained version only when constraints - //--- are actually present - if(nbc==0 && nlc==0) - { - //--- "Simple" unconstrained version - CApServ::RVectorSetLengthAtLeast(state.m_tmp0,n); - //--- function call - CApServ::RVectorSetLengthAtLeast(state.m_bufb,n); - //--- calculation - state.m_densea[0].Set(0,state.m_diaga[0]); - for(k=1;k<=n-1;k++) - { - for(i_=0;i_<=k-1;i_++) - state.m_densea[i_].Set(k,state.m_densea[k][i_]); - state.m_densea[k].Set(k,state.m_diaga[k]); - } - //--- change values - for(i_=0;i_<=n-1;i_++) - state.m_bufb[i_]=state.m_b[i_]; - state.m_repncholesky=1; - //--- check - if(!CTrFac::SPDMatrixCholeskyRec(state.m_densea,0,n,true,state.m_tmp0)) - { - state.m_repterminationtype=-5; - return; - } - //--- function call - CFbls::FblsCholeskySolve(state.m_densea,1.0,n,true,state.m_bufb,state.m_tmp0); - for(i_=0;i_<=n-1;i_++) - state.m_xc[i_]=-state.m_bufb[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_xc[i_]=state.m_xc[i_]+state.m_xorigin[i_]; - //--- change values - state.m_repouteriterationscount=1; - state.m_repterminationtype=4; - //--- exit the function - return; - } - //--- General bound constrained algo - CApServ::RMatrixSetLengthAtLeast(state.m_bufa,n,n); - //--- function call - CApServ::RVectorSetLengthAtLeast(state.m_bufb,n); - //--- function call - CApServ::RVectorSetLengthAtLeast(state.m_bufx,n); - //--- function call - CApServ::IVectorSetLengthAtLeast(state.m_activeconstraints,n); - //--- function call - CApServ::IVectorSetLengthAtLeast(state.m_prevactiveconstraints,n); - //--- function call - CApServ::RVectorSetLengthAtLeast(state.m_tmp0,n); - //--- Prepare constraints vectors: - //--- * ActiveConstraints - constraints active at current step - //--- * PrevActiveConstraints - constraints which were active at previous step - //--- Elements of constraints vectors can be: - //--- * 0 - inactive - //--- * 1 - active - //--- * -1 - undefined (used to initialize PrevActiveConstraints before first iteration) - for(i=0;i<=n-1;i++) - state.m_prevactiveconstraints[i]=-1; - //--- Main cycle - fprev=CMath::m_maxrealnumber; - while(true) - { - //--- * calculate gradient at XC - //--- * determine active constraints - //--- * break if there is no free variables or - //--- there were no changes in the list of active constraints - MinQPGrad(state); - nactive=0; - for(i=0;i<=n-1;i++) - { - state.m_activeconstraints[i]=0; - //--- check - if(state.m_havebndl[i]) - { - //--- check - if(state.m_xc[i]<=state.m_workbndl[i] && state.m_gc[i]>=0.0) - state.m_activeconstraints[i]=1; - } - //--- check - if(state.m_havebndu[i]) - { - //--- check - if(state.m_xc[i]>=state.m_workbndu[i] && state.m_gc[i]<=0.0) - state.m_activeconstraints[i]=1; - } - //--- check - if(state.m_havebndl[i] && state.m_havebndu[i]) - { - //--- check - if(state.m_workbndl[i]==state.m_workbndu[i]) - state.m_activeconstraints[i]=1; - } - //--- check - if(state.m_activeconstraints[i]>0) - nactive=nactive+1; - } - nfree=n-nactive; - //--- check - if(nfree==0) - break; - b=false; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_activeconstraints[i]!=state.m_prevactiveconstraints[i]) - b=true; - } - //--- check - if(!b) - break; - //--- * copy A,B and X to buffer - //--- * rearrange BufA,BufB and BufX,in such way that active variables come first, - //--- inactive are moved to the tail. We use sorting subroutine - //--- to solve this problem. - state.m_bufa[0].Set(0,state.m_diaga[0]); - for(k=1;k<=n-1;k++) - { - for(i_=0;i_<=k-1;i_++) - state.m_bufa[k].Set(i_,state.m_densea[k][i_]); - for(i_=0;i_<=k-1;i_++) - state.m_bufa[i_].Set(k,state.m_densea[k][i_]); - state.m_bufa[k].Set(k,state.m_diaga[k]); - } - //--- change values - for(i_=0;i_<=n-1;i_++) - state.m_bufb[i_]=state.m_b[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_bufx[i_]=state.m_xc[i_]; - for(i=0;i<=n-1;i++) - state.m_tmp0[i]=state.m_activeconstraints[i]; - //--- function call - CTSort::TagSortBuf(state.m_tmp0,n,state.m_itmp0,state.m_p2,state.m_buf); - for(k=0;k<=n-1;k++) - { - //--- check - if(state.m_p2[k]!=k) - { - //--- swap - v=state.m_bufb[k]; - state.m_bufb[k]=state.m_bufb[state.m_p2[k]]; - state.m_bufb[state.m_p2[k]]=v; - v=state.m_bufx[k]; - state.m_bufx[k]=state.m_bufx[state.m_p2[k]]; - state.m_bufx[state.m_p2[k]]=v; - } - } - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=n-1;i_++) - state.m_tmp0[i_]=state.m_bufa[i][i_]; - for(k=0;k<=n-1;k++) - { - //--- check - if(state.m_p2[k]!=k) - { - //--- swap - v=state.m_tmp0[k]; - state.m_tmp0[k]=state.m_tmp0[state.m_p2[k]]; - state.m_tmp0[state.m_p2[k]]=v; - } - } - for(i_=0;i_<=n-1;i_++) - state.m_bufa[i].Set(i_,state.m_tmp0[i_]); - } - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_p2[i]!=i) - { - for(i_=0;i_<=n-1;i_++) - state.m_tmp0[i_]=state.m_bufa[i][i_]; - for(i_=0;i_<=n-1;i_++) - state.m_bufa[i].Set(i_,state.m_bufa[state.m_p2[i]][i_]); - for(i_=0;i_<=n-1;i_++) - state.m_bufa[state.m_p2[i]].Set(i_,state.m_tmp0[i_]); - } - } - //--- Now we have A and B in BufA and BufB,variables are rearranged - //--- into two groups: Xf - free variables,Xc - active (fixed) variables, - //--- and our quadratic problem can be written as - //--- ( Af Ac ) ( Xf ) ( Xf ) - //--- F(X)=0.5* ( Xf' Xc' ) * ( ) * ( ) + ( Bf' Bc' ) * ( ) - //--- ( Ac' Acc ) ( Xc ) ( Xc ) - //--- we want to convert to the optimization with respect to Xf, - //--- treating Xc as constant term. After expansion of expression above - //--- we get - //--- F(Xf)=0.5*Xf'*Af*Xf + (Bf+Ac*Xc)'*Xf + 0.5*Xc'*Acc*Xc - //--- We will update BufB using this expression and calculate - //--- constant term. - CAblas::RMatrixMVect(nfree,nactive,state.m_bufa,0,nfree,0,state.m_bufx,nfree,state.m_tmp0,0); - for(i_=0;i_<=nfree-1;i_++) - state.m_bufb[i_]=state.m_bufb[i_]+state.m_tmp0[i_]; - state.m_constterm=0.0; - for(i=nfree;i<=n-1;i++) - { - state.m_constterm=state.m_constterm+0.5*state.m_bufx[i]*state.m_bufa[i][i]*state.m_bufx[i]; - for(j=i+1;j<=n-1;j++) - state.m_constterm=state.m_constterm+state.m_bufx[i]*state.m_bufa[i][j]*state.m_bufx[j]; - } - //--- Now we are ready to minimize F(Xf)... - state.m_repncholesky=state.m_repncholesky+1; - //--- check - if(!CTrFac::SPDMatrixCholeskyRec(state.m_bufa,0,nfree,true,state.m_tmp0)) - { - state.m_repterminationtype=-5; - return; - } - //--- function call - CFbls::FblsCholeskySolve(state.m_bufa,1.0,nfree,true,state.m_bufb,state.m_tmp0); - for(i_=0;i_<=nfree-1;i_++) - state.m_bufx[i_]=-state.m_bufb[i_]; - //--- ...m_and to copy results back to XC. - //--- It is done in several steps: - //--- * original order of variables is restored - //--- * result is copied back to XC - //--- * XC is bounded with respect to bound constraints - for(k=n-1;k>=0;k--) - { - //--- check - if(state.m_p2[k]!=k) - { - v=state.m_bufx[k]; - state.m_bufx[k]=state.m_bufx[state.m_p2[k]]; - state.m_bufx[state.m_p2[k]]=v; - } - } - for(i_=0;i_<=n-1;i_++) - state.m_xc[i_]=state.m_bufx[i_]; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_havebndl[i]) - { - //--- check - if(state.m_xc[i]state.m_workbndu[i]) - state.m_xc[i]=state.m_workbndu[i]; - } - } - //--- Calculate F,compare it with FPrev. - //--- Break if F>=FPrev - //--- (sometimes possible at extremum due to numerical noise). - f=0.0; - for(i_=0;i_<=n-1;i_++) - f+=state.m_b[i_]*state.m_xc[i_]; - f=f+MinQPXTAX(state,state.m_xc); - //--- check - if(f>=fprev) - break; - fprev=f; - //--- Update PrevActiveConstraints - for(i=0;i<=n-1;i++) - state.m_prevactiveconstraints[i]=state.m_activeconstraints[i]; - //--- Update report-related fields - state.m_repouteriterationscount=state.m_repouteriterationscount+1; - } - //--- change values - state.m_repterminationtype=4; - for(i_=0;i_<=n-1;i_++) - state.m_xc[i_]=state.m_xc[i_]+state.m_xorigin[i_]; - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| QP solver results | -//| INPUT PARAMETERS: | -//| State - algorithm state | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report. You should check Rep. | -//| TerminationType, which contains completion code, | -//| and you may check another fields which contain | -//| another information about algorithm functioning. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPResults(CMinQPState &state,double &x[],CMinQPReport &rep) - { -//--- reset memory - ArrayResizeAL(x,0); -//--- function call - MinQPResultsBuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| QP results | -//| Buffered implementation of MinQPResults() which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPResultsBuf(CMinQPState &state,double &x[], - CMinQPReport &rep) - { -//--- create a variable - int i_=0; -//--- check - if(CAp::Len(x)0)")) - return; -//--- initialization - n=state.m_n; - for(k=0;k<=n-1;k++) - state.m_diaga[k]=s[k]; - } -//+------------------------------------------------------------------+ -//| Fast version of MinQPSetStartingPoint(), which doesn't check its | -//| arguments. For internal use only. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPSetStartingPointFast(CMinQPState &state,double &x[]) - { -//--- create variables - int n=0; - int i_=0; -//--- initialization - n=state.m_n; - for(i_=0;i_<=n-1;i_++) - state.m_startx[i_]=x[i_]; - state.m_havex=true; - } -//+------------------------------------------------------------------+ -//| Fast version of MinQPSetOrigin(), which doesn't check its | -//| arguments. For internal use only. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPSetOriginFast(CMinQPState &state,double &xorigin[]) - { -//--- create variables - int n=0; - int i_=0; -//--- initialization - n=state.m_n; - for(i_=0;i_<=n-1;i_++) - state.m_xorigin[i_]=xorigin[i_]; - } -//+------------------------------------------------------------------+ -//| This function calculates gradient of quadratic function at XC and| -//| stores it in the GC. | -//+------------------------------------------------------------------+ -static void CMinQP::MinQPGrad(CMinQPState &state) - { -//--- create variables - int n=0; - int i=0; - double v=0; - int i_=0; -//--- initialization - n=state.m_n; -//--- check - if(!CAp::Assert(state.m_akind==-1||state.m_akind==0,__FUNCTION__+": internal error")) - return; -//--- zero A - if(state.m_akind==-1) - { - for(i_=0;i_<=n-1;i_++) - state.m_gc[i_]=state.m_b[i_]; - //--- exit the function - return; - } -//--- dense A - if(state.m_akind==0) - { - for(i_=0;i_<=n-1;i_++) - state.m_gc[i_]=state.m_b[i_]; - state.m_gc[0]=state.m_gc[0]+state.m_diaga[0]*state.m_xc[0]; - //--- calculation - for(i=1;i<=n-1;i++) - { - v=0.0; - for(i_=0;i_<=i-1;i_++) - v+=state.m_densea[i][i_]*state.m_xc[i_]; - state.m_gc[i]=state.m_gc[i]+v+state.m_diaga[i]*state.m_xc[i]; - v=state.m_xc[i]; - //--- change values - for(i_=0;i_<=i-1;i_++) - state.m_gc[i_]=state.m_gc[i_]+v*state.m_densea[i][i_]; - } - //--- exit the function - return; - } - } -//+------------------------------------------------------------------+ -//| This function calculates x'*A*x for given X. | -//+------------------------------------------------------------------+ -static double CMinQP::MinQPXTAX(CMinQPState &state,double &x[]) - { -//--- create variables - double result=0; - int n=0; - int i=0; - int j=0; -//--- initialization - n=state.m_n; -//--- check - if(!CAp::Assert(state.m_akind==-1 || state.m_akind==0,__FUNCTION__+": internal error")) - return(EMPTY_VALUE); - result=0; -//--- zero A - if(state.m_akind==-1) - return(0.0); -//--- dense A - if(state.m_akind==0) - { - result=0; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=i-1;j++) - result=result+state.m_densea[i][j]*x[i]*x[j]; - //--- get result - result=result+0.5*state.m_diaga[i]*CMath::Sqr(x[i]); - } - //--- return result - return(result); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Levenberg-Marquardt optimizer. | -//| This structure should be created using one of the | -//| MinLMCreate() functions. You should not access its fields | -//| directly; use ALGLIB functions to work with it. | -//+------------------------------------------------------------------+ -class CMinLMState - { -public: - //--- variables - int m_n; - int m_m; - double m_diffstep; - double m_epsg; - double m_epsf; - double m_epsx; - int m_maxits; - bool m_xrep; - double m_stpmax; - int m_maxmodelage; - bool m_makeadditers; - double m_f; - bool m_needf; - bool m_needfg; - bool m_needfgh; - bool m_needfij; - bool m_needfi; - bool m_xupdated; - int m_algomode; - bool m_hasf; - bool m_hasfi; - bool m_hasg; - double m_fbase; - double m_lambdav; - double m_nu; - int m_modelage; - bool m_deltaxready; - bool m_deltafready; - int m_repiterationscount; - int m_repterminationtype; - int m_repnfunc; - int m_repnjac; - int m_repngrad; - int m_repnhess; - int m_repncholesky; - RCommState m_rstate; - double m_actualdecrease; - double m_predicteddecrease; - double m_xm1; - double m_xp1; - CMinLBFGSState m_internalstate; - CMinLBFGSReport m_internalrep; - CMinQPState m_qpstate; - CMinQPReport m_qprep; - //--- arrays - double m_x[]; - double m_fi[]; - double m_g[]; - double m_xbase[]; - double m_fibase[]; - double m_gbase[]; - double m_bndl[]; - double m_bndu[]; - bool m_havebndl[]; - bool m_havebndu[]; - double m_s[]; - double m_xdir[]; - double m_deltax[]; - double m_deltaf[]; - double m_choleskybuf[]; - double m_tmp0[]; - double m_fm1[]; - double m_fp1[]; - //--- matrix - CMatrixDouble m_j; - CMatrixDouble m_h; - CMatrixDouble m_quadraticmodel; - //--- constructor, destructor - CMinLMState(void); - ~CMinLMState(void); - //--- copy - void Copy(CMinLMState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLMState::CMinLMState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLMState::~CMinLMState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinLMState::Copy(CMinLMState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_m=obj.m_m; - m_diffstep=obj.m_diffstep; - m_epsg=obj.m_epsg; - m_epsf=obj.m_epsf; - m_epsx=obj.m_epsx; - m_maxits=obj.m_maxits; - m_xrep=obj.m_xrep; - m_stpmax=obj.m_stpmax; - m_maxmodelage=obj.m_maxmodelage; - m_makeadditers=obj.m_makeadditers; - m_f=obj.m_f; - m_needf=obj.m_needf; - m_needfg=obj.m_needfg; - m_needfgh=obj.m_needfgh; - m_needfij=obj.m_needfij; - m_needfi=obj.m_needfi; - m_xupdated=obj.m_xupdated; - m_algomode=obj.m_algomode; - m_hasf=obj.m_hasf; - m_hasfi=obj.m_hasfi; - m_hasg=obj.m_hasg; - m_fbase=obj.m_fbase; - m_lambdav=obj.m_lambdav; - m_nu=obj.m_nu; - m_modelage=obj.m_modelage; - m_deltaxready=obj.m_deltaxready; - m_deltafready=obj.m_deltafready; - m_repiterationscount=obj.m_repiterationscount; - m_repterminationtype=obj.m_repterminationtype; - m_repnfunc=obj.m_repnfunc; - m_repnjac=obj.m_repnjac; - m_repngrad=obj.m_repngrad; - m_repnhess=obj.m_repnhess; - m_repncholesky=obj.m_repncholesky; - m_actualdecrease=obj.m_actualdecrease; - m_predicteddecrease=obj.m_predicteddecrease; - m_xm1=obj.m_xm1; - m_xp1=obj.m_xp1; - m_rstate.Copy(obj.m_rstate); - m_internalstate.Copy(obj.m_internalstate); - m_internalrep.Copy(obj.m_internalrep); - m_qpstate.Copy(obj.m_qpstate); - m_qprep.Copy(obj.m_qprep); -//--- copy arrays - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_fi,obj.m_fi); - ArrayCopy(m_g,obj.m_g); - ArrayCopy(m_xbase,obj.m_xbase); - ArrayCopy(m_fibase,obj.m_fibase); - ArrayCopy(m_gbase,obj.m_gbase); - ArrayCopy(m_bndl,obj.m_bndl); - ArrayCopy(m_bndu,obj.m_bndu); - ArrayCopy(m_havebndl,obj.m_havebndl); - ArrayCopy(m_havebndu,obj.m_havebndu); - ArrayCopy(m_s,obj.m_s); - ArrayCopy(m_xdir,obj.m_xdir); - ArrayCopy(m_deltax,obj.m_deltax); - ArrayCopy(m_deltaf,obj.m_deltaf); - ArrayCopy(m_choleskybuf,obj.m_choleskybuf); - ArrayCopy(m_tmp0,obj.m_tmp0); - ArrayCopy(m_fm1,obj.m_fm1); - ArrayCopy(m_fp1,obj.m_fp1); -//--- copy matrix - m_j=obj.m_j; - m_h=obj.m_h; - m_quadraticmodel=obj.m_quadraticmodel; - } -//+------------------------------------------------------------------+ -//| Levenberg-Marquardt optimizer. | -//| This structure should be created using one of the | -//| MinLMCreate() functions. You should not access its fields | -//| directly; use ALGLIB functions to work with it. | -//+------------------------------------------------------------------+ -class CMinLMStateShell - { -private: - CMinLMState m_innerobj; -public: - //--- constructors, destructor - CMinLMStateShell(void); - CMinLMStateShell(CMinLMState &obj); - ~CMinLMStateShell(void); - //--- methods - bool GetNeedF(void); - void SetNeedF(const bool b); - bool GetNeedFG(void); - void SetNeedFG(const bool b); - bool GetNeedFGH(void); - void SetNeedFGH(const bool b); - bool GetNeedFI(void); - void SetNeedFI(const bool b); - bool GetNeedFIJ(void); - void SetNeedFIJ(const bool b); - bool GetXUpdated(void); - void SetXUpdated(const bool b); - double GetF(void); - void SetF(const double d); - CMinLMState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLMStateShell::CMinLMStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinLMStateShell::CMinLMStateShell(CMinLMState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLMStateShell::~CMinLMStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needf | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetNeedF(void) - { -//--- return result - return(m_innerobj.m_needf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needf | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetNeedF(const bool b) - { -//--- change value - m_innerobj.m_needf=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfg | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetNeedFG(void) - { -//--- return result - return(m_innerobj.m_needfg); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfg | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetNeedFG(const bool b) - { -//--- change value - m_innerobj.m_needfg=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfgh | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetNeedFGH(void) - { -//--- return result - return(m_innerobj.m_needfgh); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfgh | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetNeedFGH(const bool b) - { -//--- change value - m_innerobj.m_needfgh=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfi | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetNeedFI(void) - { -//--- return result - return(m_innerobj.m_needfi); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfi | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetNeedFI(const bool b) - { -//--- change value - m_innerobj.m_needfi=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfij | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetNeedFIJ(void) - { -//--- return result - return(m_innerobj.m_needfij); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfij | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetNeedFIJ(const bool b) - { -//--- change value - m_innerobj.m_needfij=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable xupdated | -//+------------------------------------------------------------------+ -bool CMinLMStateShell::GetXUpdated(void) - { -//--- return result - return(m_innerobj.m_xupdated); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable xupdated | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetXUpdated(const bool b) - { -//--- change value - m_innerobj.m_xupdated=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable f | -//+------------------------------------------------------------------+ -double CMinLMStateShell::GetF(void) - { -//--- return result - return(m_innerobj.m_f); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable f | -//+------------------------------------------------------------------+ -void CMinLMStateShell::SetF(const double d) - { -//--- change value - m_innerobj.m_f=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinLMState *CMinLMStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Optimization report, filled by MinLMResults() function | -//| FIELDS: | -//| * TerminationType, completetion code: | -//| * -9 derivative correctness check failed; | -//| see Rep.WrongNum, Rep.WrongI, Rep.WrongJ for | -//| more information. | -//| * 1 relative function improvement is no more than | -//| EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient is no more than EpsG. | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too stringent, | -//| further improvement is impossible | -//| * IterationsCount, contains iterations count | -//| * NFunc, number of function calculations | -//| * NJac, number of Jacobi matrix calculations | -//| * NGrad, number of gradient calculations | -//| * NHess, number of Hessian calculations | -//| * NCholesky, number of Cholesky decomposition calculations | -//+------------------------------------------------------------------+ -class CMinLMReport - { -public: - //--- variables - int m_iterationscount; - int m_terminationtype; - int m_nfunc; - int m_njac; - int m_ngrad; - int m_nhess; - int m_ncholesky; - //--- constructor, destructor - CMinLMReport(void); - ~CMinLMReport(void); - //--- copy - void Copy(CMinLMReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLMReport::CMinLMReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLMReport::~CMinLMReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinLMReport::Copy(CMinLMReport &obj) - { -//--- copy variables - m_iterationscount=obj.m_iterationscount; - m_terminationtype=obj.m_terminationtype; - m_nfunc=obj.m_nfunc; - m_njac=obj.m_njac; - m_ngrad=obj.m_ngrad; - m_nhess=obj.m_nhess; - m_ncholesky=obj.m_ncholesky; - } -//+------------------------------------------------------------------+ -//| Optimization report, filled by MinLMResults() function | -//| FIELDS: | -//| * TerminationType, completetion code: | -//| * -9 derivative correctness check failed; | -//| see Rep.WrongNum, Rep.WrongI, Rep.WrongJ for | -//| more information. | -//| * 1 relative function improvement is no more than | -//| EpsF. | -//| * 2 relative step is no more than EpsX. | -//| * 4 gradient is no more than EpsG. | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too stringent, | -//| further improvement is impossible | -//| * IterationsCount, contains iterations count | -//| * NFunc, number of function calculations | -//| * NJac, number of Jacobi matrix calculations | -//| * NGrad, number of gradient calculations | -//| * NHess, number of Hessian calculations | -//| * NCholesky, number of Cholesky decomposition calculations | -//+------------------------------------------------------------------+ -class CMinLMReportShell - { -private: - CMinLMReport m_innerobj; -public: - //--- constructors, destructor - CMinLMReportShell(void); - CMinLMReportShell(CMinLMReport &obj); - ~CMinLMReportShell(void); - //--- methods - int GetIterationsCount(void); - void SetIterationsCount(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - int GetNFunc(void); - void SetNFunc(const int i); - int GetNJAC(void); - void SetNJAC(const int i); - int GetNGrad(void); - void SetNGrad(const int i); - int GetNHess(void); - void SetNHess(const int i); - int GetNCholesky(void); - void SetNCholesky(const int i); - CMinLMReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLMReportShell::CMinLMReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinLMReportShell::CMinLMReportShell(CMinLMReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLMReportShell::~CMinLMReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable iterationscount | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetIterationsCount(void) - { -//--- return result - return(m_innerobj.m_iterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable iterationscount | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetIterationsCount(const int i) - { -//--- change value - m_innerobj.m_iterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfunc | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetNFunc(void) - { -//--- return result - return(m_innerobj.m_nfunc); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfunc | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetNFunc(const int i) - { -//--- change value - m_innerobj.m_nfunc=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable njac | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetNJAC(void) - { -//--- return result - return(m_innerobj.m_njac); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable njac | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetNJAC(const int i) - { -//--- change value - m_innerobj.m_njac=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ngrad | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetNGrad(void) - { -//--- return result - return(m_innerobj.m_ngrad); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ngrad | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetNGrad(const int i) - { -//--- change value - m_innerobj.m_ngrad=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nhess | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetNHess(void) - { -//--- return result - return(m_innerobj.m_nhess); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nhess | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetNHess(const int i) - { -//--- change value - m_innerobj.m_nhess=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable ncholesky | -//+------------------------------------------------------------------+ -int CMinLMReportShell::GetNCholesky(void) - { -//--- return result - return(m_innerobj.m_ncholesky); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable ncholesky | -//+------------------------------------------------------------------+ -void CMinLMReportShell::SetNCholesky(const int i) - { -//--- change value - m_innerobj.m_ncholesky=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinLMReport *CMinLMReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Levenberg-Marquardt method | -//+------------------------------------------------------------------+ -class CMinLM - { -private: - //--- private methods - static void LMPRepare(const int n,const int m,bool havegrad,CMinLMState &state); - static void ClearRequestFields(CMinLMState &state); - static bool IncreaseLambda(double &lambdav,double &nu); - static void DecreaseLambda(double &lambdav,double &nu); - static double BoundedScaledAntigradNorm(CMinLMState &state,double &x[],double &g[]); - //--- auxiliary functions for MinLMIteration - static void Func_lbl_rcomm(CMinLMState &state,int n,int m,int iflag,int i,int k,bool bflag,double v,double s,double t); - static bool Func_lbl_16(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_19(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_20(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_21(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_22(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_24(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_25(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_28(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_31(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_39(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_40(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_41(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_48(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_49(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); - static bool Func_lbl_55(CMinLMState &state,int &n,int &m,int &iflag,int &i,int &k,bool &bflag,double &v,double &s,double &t); -public: - //--- class constants - static const int m_lmmodefj; - static const int m_lmmodefgj; - static const int m_lmmodefgh; - static const int m_lmflagnopreLBFGS; - static const int m_lmflagnointLBFGS; - static const int m_lmpreLBFGSm; - static const int m_lmintLBFGSits; - static const int m_lbfgsnorealloc; - static const double m_lambdaup; - static const double m_lambdadown; - static const double m_suspiciousnu; - static const int m_smallmodelage; - static const int m_additers; - //--- constructor, destructor - CMinLM(void); - ~CMinLM(void); - //--- public methods - static void MinLMCreateVJ(const int n,const int m,double &x[],CMinLMState &state); - static void MinLMCreateV(const int n,const int m,double &x[],const double diffstep,CMinLMState &state); - static void MinLMCreateFGH(const int n,double &x[],CMinLMState &state); - static void MinLMSetCond(CMinLMState &state,const double epsg,const double epsf,double epsx,const int maxits); - static void MinLMSetXRep(CMinLMState &state,const bool needxrep); - static void MinLMSetStpMax(CMinLMState &state,const double stpmax); - static void MinLMSetScale(CMinLMState &state,double &s[]); - static void MinLMSetBC(CMinLMState &state,double &bndl[],double &bndu[]); - static void MinLMSetAccType(CMinLMState &state,int acctype); - static void MinLMResults(CMinLMState &state,double &x[],CMinLMReport &rep); - static void MinLMResultsBuf(CMinLMState &state,double &x[],CMinLMReport &rep); - static void MinLMRestartFrom(CMinLMState &state,double &x[]); - static void MinLMCreateVGJ(const int n,const int m,double &x[],CMinLMState &state); - static void MinLMCreateFGJ(const int n,const int m,double &x[],CMinLMState &state); - static void MinLMCreateFJ(const int n,const int m,double &x[],CMinLMState &state); - static bool MinLMIteration(CMinLMState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CMinLM::m_lmmodefj=0; -const int CMinLM::m_lmmodefgj=1; -const int CMinLM::m_lmmodefgh=2; -const int CMinLM::m_lmflagnopreLBFGS=1; -const int CMinLM::m_lmflagnointLBFGS=2; -const int CMinLM::m_lmpreLBFGSm=5; -const int CMinLM::m_lmintLBFGSits=5; -const int CMinLM::m_lbfgsnorealloc=1; -const double CMinLM::m_lambdaup=2.0; -const double CMinLM::m_lambdadown=0.33; -const double CMinLM::m_suspiciousnu=16; -const int CMinLM::m_smallmodelage=3; -const int CMinLM::m_additers=5; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinLM::CMinLM(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinLM::~CMinLM(void) - { - - } -//+------------------------------------------------------------------+ -//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR | -//| NON-LINEAR LEAST SQUARES OPTIMIZATION | -//| DESCRIPTION: | -//| This function is used to find minimum of function which is | -//| represented as sum of squares: | -//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + | -//| + f[m-1]^2(x[0],...,x[n-1]) | -//| using value of function vector f[] and Jacobian of f[]. | -//| REQUIREMENTS: | -//| This algorithm will request following information during its | -//| operation: | -//| * function vector f[] at given point X | -//| * function vector f[] and Jacobian of f[] (simultaneously) at | -//| given point | -//| There are several overloaded versions of MinLMOptimize() | -//| function which correspond to different LM-like optimization | -//| algorithms provided by this unit. You should choose version which| -//| accepts fvec() and jac() callbacks. First one is used to | -//| calculate f[] at given point, second one calculates f[] and | -//| Jacobian df[i]/dx[j]. | -//| You can try to initialize MinLMState structure with VJ function | -//| and then use incorrect version of MinLMOptimize() (for example,| -//| version which works with general form function and does not | -//| provide Jacobian), but it will lead to exception being thrown | -//| after first attempt to calculate Jacobian. | -//| USAGE: | -//| 1. User initializes algorithm state with MinLMCreateVJ() call | -//| 2. User tunes solver parameters with MinLMSetCond(), | -//| MinLMSetStpMax() and other functions | -//| 3. User calls MinLMOptimize() function which takes algorithm | -//| state and callback functions. | -//| 4. User calls MinLMResults() to get solution | -//| 5. Optionally, user may call MinLMRestartFrom() to solve another | -//| problem with same N/M but another starting point and/or | -//| another function. MinLMRestartFrom() allows to reuse already | -//| initialized structure. | -//| INPUT PARAMETERS: | -//| N - dimension, N>1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMCreateVJ(const int n,const int m,double &x[], - CMinLMState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| M - number of functions f[i] | -//| X - initial solution, array[0..N-1] | -//| DiffStep- differentiation step, >0 | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| See also MinLMIteration, MinLMResults. | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMCreateV(const int n,const int m,double &x[], - const double diffstep,CMinLMState &state) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(diffstep),__FUNCTION__+": DiffStep is not finite!")) - return; -//--- check - if(!CAp::Assert(diffstep>0.0,__FUNCTION__+": DiffStep<=0!")) - return; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)1 | -//| * if given, only leading N elements of X are | -//| used | -//| * if not given, automatically determined from | -//| size of X | -//| X - initial solution, array[0..N-1] | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with MinLMSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use MinLMSetStpMax() function to | -//| bound algorithm's steps. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMCreateFGH(const int n,double &x[],CMinLMState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=0 | -//| The subroutine finishes its work if the | -//| condition |v|=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |F(k+1)-F(k)| <= | -//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. | -//| EpsX - >=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition |v|<=EpsX is fulfilled, | -//| where: | -//| * |.| means Euclidian norm | -//| * v - scaled step vector, v[i]=dx[i]/s[i] | -//| * dx - ste pvector, dx=X(k+1)-X(k) | -//| * s - scaling coefficients set by MinLMSetScale()| -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. Only | -//| Levenberg-Marquardt iterations are counted | -//| (L-BFGS/CG iterations are NOT counted because | -//| their cost is very low compared to that of LM). | -//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will| -//| lead to automatic stopping criterion selection (small EpsX). | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMSetCond(CMinLMState &state,const double epsg, - const double epsf,double epsx, - const int maxits) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsg),__FUNCTION__+": EpsG is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsg>=0.0,__FUNCTION__+": negative EpsG!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsx>=0.0,__FUNCTION__+": negative EpsX!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- check - if(((epsg==0.0 && epsf==0.0) && epsx==0.0) && maxits==0) - epsx=1.0E-6; -//--- change values - state.m_epsg=epsg; - state.m_epsf=epsf; - state.m_epsx=epsx; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to MinLMOptimize(). Both Levenberg-Marquardt | -//| and internal L-BFGS iterations are reported. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMSetXRep(CMinLMState &state,const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when you optimize target function which | -//| contains exp() or other fast growing functions, and optimization | -//| algorithm makes too large steps which leads to overflow. This | -//| function allows us to reject steps that are too large (and | -//| therefore expose us to the possible overflow) without actually | -//| calculating function value at the x+stp*d. | -//| NOTE: non-zero StpMax leads to moderate performance degradation | -//| because intermediate step of preconditioned L-BFGS optimization | -//| is incompatible with limits on step size. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMSetStpMax(CMinLMState &state,const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| This function sets scaling coefficients for LM optimizer. | -//| ALGLIB optimizers use scaling matrices to test stopping | -//| conditions (step size and gradient are scaled before comparison | -//| with tolerances). Scale of the I-th variable is a translation | -//| invariant measure of: | -//| a) "how large" the variable is | -//| b) how large the step should be to make significant changes in | -//| the function | -//| Generally, scale is NOT considered to be a form of | -//| preconditioner. But LM optimizer is unique in that it uses | -//| scaling matrix both in the stopping condition tests and as | -//| Marquardt damping factor. | -//| Proper scaling is very important for the algorithm performance. | -//| It is less important for the quality of results, but still has | -//| some influence (it is easier to converge when variables are | -//| properly scaled, so premature stopping is possible when very | -//| badly scalled variables are combined with relaxed stopping | -//| conditions). | -//| INPUT PARAMETERS: | -//| State - structure stores algorithm state | -//| S - array[N], non-zero scaling coefficients | -//| S[i] may be negative, sign doesn't matter. | -//+------------------------------------------------------------------+ -static void CMinLM::MinLMSetScale(CMinLMState &state,double &s[]) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(CAp::Len(s)>=state.m_n,__FUNCTION__+": Length(S)=n,__FUNCTION__+": Length(BndL)=n,__FUNCTION__+": Length(BndU)=state.m_n,__FUNCTION__+": Length(X)=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)0.25*lnmax) - { - //--- return result - return(result); - } -//--- check - if(lnnu+MathLog(2)>lnmax) - return(result); -//--- change values - lambdav=lambdav*m_lambdaup*nu; - nu=nu*2; - result=true; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Decreases lambda, but leaves it unchanged when there is danger of| -//| underflow. | -//+------------------------------------------------------------------+ -static void CMinLM::DecreaseLambda(double &lambdav,double &nu) - { -//--- initialization - nu=1; -//--- check - if(MathLog(lambdav)+MathLog(m_lambdadown)0)and(x[i]=bndu[i])) | -//| v[i]=-g[i]*s[i] otherwise, where s[i] is a scale for I-th | -//| variable | -//| This function may be used to check a stopping criterion. | -//+------------------------------------------------------------------+ -static double CMinLM::BoundedScaledAntigradNorm(CMinLMState &state, - double &x[],double &g[]) - { -//--- create variables - double result=0; - int n=0; - int i=0; - double v=0; -//--- initialization - result=0; - n=state.m_n; - for(i=0;i<=n-1;i++) - { - v=-(g[i]*state.m_s[i]); - //--- check - if(state.m_havebndl[i]) - { - //--- check - if(x[i]<=state.m_bndl[i] && (double)(-g[i])<0.0) - v=0; - } - //--- check - if(state.m_havebndu[i]) - { - //--- check - if(x[i]>=state.m_bndu[i] && (double)(-g[i])>0.0) - v=0; - } - result=result+CMath::Sqr(v); - } -//--- return result - return(MathSqrt(result)); - } -//+------------------------------------------------------------------+ -//| NOTES: | -//| 1. Depending on function used to create state structure, this | -//| algorithm may accept Jacobian and/or Hessian and/or gradient. | -//| According to the said above, there ase several versions of | -//| this function, which accept different sets of callbacks. | -//| This flexibility opens way to subtle errors - you may create | -//| state with MinLMCreateFGH() (optimization using Hessian), but | -//| call function which does not accept Hessian. So when | -//| algorithm will request Hessian, there will be no callback to | -//| call. In this case exception will be thrown. | -//| Be careful to avoid such errors because there is no way to | -//| find them at compile time - you can see them at runtime only. | -//+------------------------------------------------------------------+ -static bool CMinLM::MinLMIteration(CMinLMState &state) - { -//--- create variables - int n=0; - int m=0; - bool bflag; - int iflag=0; - double v=0; - double s=0; - double t=0; - int i=0; - int k=0; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - m=state.m_rstate.ia[1]; - iflag=state.m_rstate.ia[2]; - i=state.m_rstate.ia[3]; - k=state.m_rstate.ia[4]; - bflag=state.m_rstate.ba[0]; - v=state.m_rstate.ra[0]; - s=state.m_rstate.ra[1]; - t=state.m_rstate.ra[2]; - } - else - { - //--- initialization - n=-983; - m=-989; - iflag=-834; - i=900; - k=-287; - bflag=false; - v=214; - s=-338; - t=-686; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needf=false; - //--- function call, return result - return(Func_lbl_19(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change values - state.m_needfi=false; - v=0.0; - for(i_=0;i_<=m-1;i_++) - v+=state.m_fi[i_]*state.m_fi[i_]; - state.m_f=v; - //--- function call, return result - return(Func_lbl_19(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_16(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change value - state.m_repnfunc=state.m_repnfunc+1; - //--- copy - for(i_=0;i_<=m-1;i_++) - state.m_fm1[i_]=state.m_fi[i_]; - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_x[k]=state.m_x[k]+state.m_s[k]*state.m_diffstep; - //--- check - if(state.m_havebndl[k]) - state.m_x[k]=MathMax(state.m_x[k],state.m_bndl[k]); - //--- check - if(state.m_havebndu[k]) - state.m_x[k]=MathMin(state.m_x[k],state.m_bndu[k]); - state.m_xp1=state.m_x[k]; - //--- function call - ClearRequestFields(state); - state.m_needfi=true; - state.m_rstate.stage=4; - //--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change value - state.m_repnfunc=state.m_repnfunc+1; - //--- copy - for(i_=0;i_<=m-1;i_++) - state.m_fp1[i_]=state.m_fi[i_]; - v=state.m_xp1-state.m_xm1; - //--- check - if(v!=0.0) - { - v=1/v; - for(i_=0;i_<=m-1;i_++) - state.m_j[i_].Set(k,v*state.m_fp1[i_]); - for(i_=0;i_<=m-1;i_++) - state.m_j[i_].Set(k,state.m_j[i_][k]-v*state.m_fm1[i_]); - } - else - { - for(i=0;i<=m-1;i++) - state.m_j[i].Set(k,0); - } - k=k+1; - //--- function call, return result - return(Func_lbl_28(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change values - state.m_needfi=false; - state.m_repnfunc=state.m_repnfunc+1; - state.m_repnjac=state.m_repnjac+1; - //--- New model - state.m_modelage=0; - //--- function call, return result - return(Func_lbl_25(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change values - state.m_needfij=false; - state.m_repnfunc=state.m_repnfunc+1; - state.m_repnjac=state.m_repnjac+1; - //--- New model - state.m_modelage=0; - //--- function call, return result - return(Func_lbl_25(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==7) - { - //--- change values - state.m_needfgh=false; - state.m_repnfunc=state.m_repnfunc+1; - state.m_repngrad=state.m_repngrad+1; - state.m_repnhess=state.m_repnhess+1; - //--- function call - CAblas::RMatrixCopy(n,n,state.m_h,0,0,state.m_quadraticmodel,0,0); - for(i_=0;i_<=n-1;i_++) - state.m_gbase[i_]=state.m_g[i_]; - state.m_fbase=state.m_f; - //--- set control variables - bflag=true; - state.m_modelage=0; - //--- function call, return result - return(Func_lbl_31(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==8) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==9) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==10) - { - //--- change values - state.m_needfi=false; - v=0.0; - for(i_=0;i_<=m-1;i_++) - v+=state.m_fi[i_]*state.m_fi[i_]; - state.m_f=v; - //--- copy - for(i_=0;i_<=m-1;i_++) - state.m_deltaf[i_]=state.m_fi[i_]; - for(i_=0;i_<=m-1;i_++) - state.m_deltaf[i_]=state.m_deltaf[i_]-state.m_fibase[i_]; - state.m_deltafready=true; - //--- function call, return result - return(Func_lbl_48(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==11) - { - //--- change value - state.m_needf=false; - //--- function call, return result - return(Func_lbl_48(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==12) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==13) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_55(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_rstate.stage==14) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==15) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- Routine body -//--- prepare - n=state.m_n; - m=state.m_m; - state.m_repiterationscount=0; - state.m_repterminationtype=0; - state.m_repnfunc=0; - state.m_repnjac=0; - state.m_repngrad=0; - state.m_repnhess=0; - state.m_repncholesky=0; -//--- check consistency of constraints -//--- set constraints - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_havebndl[i] && state.m_havebndu[i]) - { - //--- check - if(state.m_bndl[i]>state.m_bndu[i]) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } - } - } -//--- function call - CMinQP::MinQPSetBC(state.m_qpstate,state.m_bndl,state.m_bndu); -//--- Initial report of current point -//--- Note 1: we rewrite State.X twice because -//--- user may accidentally change it after first call. -//--- Note 2: we set NeedF or NeedFI depending on what -//--- information about function we have. - if(!state.m_xrep) - return(Func_lbl_16(state,n,m,iflag,i,k,bflag,v,s,t)); - for(i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; -//--- function call - ClearRequestFields(state); -//--- check - if(!state.m_hasf) - { - //--- check - if(!CAp::Assert(state.m_hasfi,"MinLM: internal error 2!")) - return(false); - //--- change values - state.m_needfi=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); - //--- return result - return(true); - } -//--- change values - state.m_needf=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CMinLM::Func_lbl_rcomm(CMinLMState &state,int n,int m,int iflag, - int i,int k,bool bflag,double v, - double s,double t) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=m; - state.m_rstate.ia[2]=iflag; - state.m_rstate.ia[3]=i; - state.m_rstate.ia[4]=k; - state.m_rstate.ba[0]=bflag; - state.m_rstate.ra[0]=v; - state.m_rstate.ra[1]=s; - state.m_rstate.ra[2]=t; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_16(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- Prepare control variables - state.m_nu=1; - state.m_lambdav=-CMath::m_maxrealnumber; - state.m_modelage=state.m_maxmodelage+1; - state.m_deltaxready=false; - state.m_deltafready=false; -//--- Main cycle. -//--- We move through it until either: -//--- * one of the stopping conditions is met -//--- * we decide that stopping conditions are too stringent -//--- and break from cycle - return(Func_lbl_20(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_19(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- change value - state.m_repnfunc=state.m_repnfunc+1; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_20(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- First,we have to prepare quadratic model for our function. -//--- We use BFlag to ensure that model is prepared; -//--- if it is false at the end of this block,something went wrong. -//--- We may either calculate brand new model or update old one. -//--- Before this block we have: -//--- * State.XBase - current position. -//--- * State.DeltaX - if DeltaXReady is True -//--- * State.DeltaF - if DeltaFReady is True -//--- After this block is over,we will have: -//--- * State.XBase - base point (unchanged) -//--- * State.FBase - F(XBase) -//--- * State.GBase - linear term -//--- * State.QuadraticModel - quadratic term -//--- * State.LambdaV - current estimate for lambda -//--- We also clear DeltaXReady/DeltaFReady flags -//--- after initialization is done. - bflag=false; - if(!(state.m_algomode==0 || state.m_algomode==1)) - return(Func_lbl_22(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- Calculate f[] and Jacobian - if(!(state.m_modelage>state.m_maxmodelage||!(state.m_deltaxready &state.m_deltafready))) - return(Func_lbl_24(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- Refresh model (using either finite differences or analytic Jacobian) - if(state.m_algomode!=0) - { - //--- Obtain f[] and Jacobian - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - //--- function call - ClearRequestFields(state); - //--- change values - state.m_needfij=true; - state.m_rstate.stage=6; - //--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); - //--- return result - return(true); - } -//--- Optimization using F values only. -//--- Use finite differences to estimate Jacobian. - if(!CAp::Assert(state.m_hasfi,"MinLMIteration: internal error when estimating Jacobian (no f[])")) - return(false); - k=0; -//--- function call, return result - return(Func_lbl_28(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_21(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- Lambda is too large,we have to break iterations. - state.m_repterminationtype=7; - if(!state.m_xrep) - return(false); - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_f=state.m_fbase; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=15; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_22(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- check - if(state.m_algomode!=2) - return(Func_lbl_31(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- check - if(!CAp::Assert(!state.m_hasfi,"MinLMIteration: internal error (HasFI is True in Hessian-based mode)")) - return(false); -//--- Obtain F,G,H - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_needfgh=true; - state.m_rstate.stage=7; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_24(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- State.J contains Jacobian or its current approximation; -//--- refresh it using secant updates: -//--- f(x0+dx)=f(x0) + J*dx, -//--- J_new=J_old + u*h' -//--- h=x_new-x_old -//--- u=(f_new - f_old - J_old*h)/(h'h) -//--- We can explicitly generate h and u,but it is -//--- preferential to do in-place calculations. Only -//--- I-th row of J_old is needed to calculate u[I], -//--- so we can update J row by row in one pass. -//--- NOTE: we expect that State.XBase contains new point, -//--- State.FBase contains old point,State.DeltaX and -//--- State.DeltaY contain updates from last step. - if(!CAp::Assert(state.m_deltaxready && state.m_deltafready,"MinLMIteration: uninitialized DeltaX/DeltaF")) - return(false); - t=0.0; - for(int i_=0;i_<=n-1;i_++) - t+=state.m_deltax[i_]*state.m_deltax[i_]; -//--- check - if(!CAp::Assert(t!=0.0,"MinLM: internal error (T=0)")) - return(false); - for(i=0;i<=m-1;i++) - { - //--- change value - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_j[i][i_]*state.m_deltax[i_]; - v=(state.m_deltaf[i]-v)/t; - for(int i_=0;i_<=n-1;i_++) - state.m_j[i].Set(i_,state.m_j[i][i_]+v*state.m_deltax[i_]); - } - for(int i_=0;i_<=m-1;i_++) - state.m_fi[i_]=state.m_fibase[i_]; - for(int i_=0;i_<=m-1;i_++) - state.m_fi[i_]=state.m_fi[i_]+state.m_deltaf[i_]; -//--- Increase model age - state.m_modelage=state.m_modelage+1; -//--- function call, return result - return(Func_lbl_25(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_25(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- Generate quadratic model: -//--- f(xbase+dx)= -//--- =(f0 + J*dx)'(f0 + J*dx) -//--- =f0^2 + dx'J'f0 + f0*J*dx + dx'J'J*dx -//--- =f0^2 + 2*f0*J*dx + dx'J'J*dx -//--- Note that we calculate 2*(J'J) instead of J'J because -//--- our quadratic model is based on Tailor decomposition, -//--- i.m_e. it has 0.5 before quadratic term. - CAblas::RMatrixGemm(n,n,m,2.0,state.m_j,0,0,1,state.m_j,0,0,0,0.0,state.m_quadraticmodel,0,0); - CAblas::RMatrixMVect(n,m,state.m_j,0,0,1,state.m_fi,0,state.m_gbase,0); - for(int i_=0;i_<=n-1;i_++) - state.m_gbase[i_]=2*state.m_gbase[i_]; -//--- change value - v=0.0; - for(int i_=0;i_<=m-1;i_++) - v+=state.m_fi[i_]*state.m_fi[i_]; - state.m_fbase=v; -//--- copy - for(int i_=0;i_<=m-1;i_++) - state.m_fibase[i_]=state.m_fi[i_]; -//--- set control variables - bflag=true; -//--- function call, return result - return(Func_lbl_22(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_28(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- check - if(k>n-1) - { - //--- Calculate F(XBase) - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - //--- function call - ClearRequestFields(state); - //--- change values - state.m_needfi=true; - state.m_rstate.stage=5; - //--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); - //--- return result - return(true); - } -//--- We guard X[k] from leaving [BndL,BndU]. -//--- In case BndL=BndU,we assume that derivative in this direction is zero. - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_x[k]=state.m_x[k]-state.m_s[k]*state.m_diffstep; -//--- check - if(state.m_havebndl[k]) - state.m_x[k]=MathMax(state.m_x[k],state.m_bndl[k]); -//--- check - if(state.m_havebndu[k]) - state.m_x[k]=MathMin(state.m_x[k],state.m_bndu[k]); - state.m_xm1=state.m_x[k]; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_needfi=true; - state.m_rstate.stage=3; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_31(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- check - if(!CAp::Assert(bflag,"MinLM: internal integrity check failed!")) - return(false); -//--- change values - state.m_deltaxready=false; - state.m_deltafready=false; -//--- If Lambda is not initialized,initialize it using quadratic model - if(state.m_lambdav<0.0) - { - state.m_lambdav=0; - for(i=0;i<=n-1;i++) - state.m_lambdav=MathMax(state.m_lambdav,MathAbs(state.m_quadraticmodel[i][i])*CMath::Sqr(state.m_s[i])); - state.m_lambdav=0.001*state.m_lambdav; - //--- check - if(state.m_lambdav==0.0) - state.m_lambdav=1; - } -//--- Test stopping conditions for function gradient - if(BoundedScaledAntigradNorm(state,state.m_xbase,state.m_gbase)>state.m_epsg) - { - //--- Find value of Levenberg-Marquardt damping parameter which: - //--- * leads to positive definite damped model - //--- * within bounds specified by StpMax - //--- * generates step which decreases function value - //--- After this block IFlag is set to: - //--- * -3,if constraints are infeasible - //--- * -2,if model update is needed (either Lambda growth is too large - //--- or step is too short,but we can't rely on model and stop iterations) - //--- * -1,if model is fresh,Lambda have grown too large,termination is needed - //--- * 0,if everything is OK,continue iterations - //--- State.Nu can have any value on enter,but after exit it is set to 1.0 - iflag=-99; - //--- function call, return result - return(Func_lbl_39(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(state.m_modelage!=0) - { - //--- Model is not fresh,we should refresh it and test - //--- conditions once more - state.m_modelage=state.m_maxmodelage+1; - //--- function call, return result - return(Func_lbl_20(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- Model is fresh,we can rely on it and terminate algorithm - state.m_repterminationtype=4; -//--- check - if(!state.m_xrep) - return(false); - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_f=state.m_fbase; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=8; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_39(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- Do we need model update? - if(state.m_modelage>0 && state.m_nu>=m_suspiciousnu) - { - iflag=-2; - //--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- Setup quadratic solver and solve quadratic programming problem. -//--- After problem is solved we'll try to bound step by StpMax -//--- (Lambda will be increased if step size is too large). -//--- We use BFlag variable to indicate that we have to increase Lambda. -//--- If it is False,we will try to increase Lambda and move to new iteration. - bflag=true; -//--- function call - CMinQP::MinQPSetStartingPointFast(state.m_qpstate,state.m_xbase); -//--- function call - CMinQP::MinQPSetOriginFast(state.m_qpstate,state.m_xbase); -//--- function call - CMinQP::MinQPSetLinearTermFast(state.m_qpstate,state.m_gbase); -//--- function call - CMinQP::MinQPSetQuadraticTermFast(state.m_qpstate,state.m_quadraticmodel,true,0.0); - for(i=0;i<=n-1;i++) - state.m_tmp0[i]=state.m_quadraticmodel[i][i]+state.m_lambdav/CMath::Sqr(state.m_s[i]); -//--- function call - CMinQP::MinQPRewriteDiagonal(state.m_qpstate,state.m_tmp0); -//--- function call - CMinQP::MinQPOptimize(state.m_qpstate); -//--- function call - CMinQP::MinQPResultsBuf(state.m_qpstate,state.m_xdir,state.m_qprep); -//--- check - if(state.m_qprep.m_terminationtype>0) - { - //--- successful solution of QP problem - for(int i_=0;i_<=n-1;i_++) - state.m_xdir[i_]=state.m_xdir[i_]-state.m_xbase[i_]; - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_xdir[i_]*state.m_xdir[i_]; - //--- check - if(CMath::IsFinite(v)) - { - v=MathSqrt(v); - //--- check - if((state.m_stpmax>0.0)&&(v>state.m_stpmax)) - bflag=false; - } - else - bflag=false; - } - else - { - //--- Either problem is non-convex (increase LambdaV) or constraints are inconsistent - if(!CAp::Assert(state.m_qprep.m_terminationtype==-3 || state.m_qprep.m_terminationtype==-5,"MinLM: unexpected completion code from QP solver")) - return(false); - //--- check - if(state.m_qprep.m_terminationtype==-3) - { - iflag=-3; - //--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } - bflag=false; - } -//--- check - if(!bflag) - { - //--- Solution failed: - //--- try to increase lambda to make matrix positive definite and continue. - if(!IncreaseLambda(state.m_lambdav,state.m_nu)) - { - iflag=-1; - //--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } - //--- function call, return result - return(Func_lbl_39(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- Step in State.XDir and it is bounded by StpMax. -//--- We should check stopping conditions on step size here. -//--- DeltaX,which is used for secant updates,is initialized here. -//--- This code is a bit tricky because sometimes XDir<>0,but -//--- it is so small that XDir+XBase==XBase (in finite precision -//--- arithmetics). So we set DeltaX to XBase,then -//--- add XDir,and then subtract XBase to get exact value of -//--- DeltaX. -//--- Step length is estimated using DeltaX. -//--- NOTE: stopping conditions are tested -//--- for fresh models only (ModelAge=0) - for(int i_=0;i_<=n-1;i_++) - state.m_deltax[i_]=state.m_xbase[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_deltax[i_]=state.m_deltax[i_]+state.m_xdir[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_deltax[i_]=state.m_deltax[i_]-state.m_xbase[i_]; - state.m_deltaxready=true; -//--- change value - v=0.0; - for(i=0;i<=n-1;i++) - v=v+CMath::Sqr(state.m_deltax[i]/state.m_s[i]); - v=MathSqrt(v); -//--- check - if(v>state.m_epsx) - return(Func_lbl_41(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- check - if(state.m_modelage!=0) - { - //--- Step is suspiciously short,but model is not fresh - //--- and we can't rely on it. - iflag=-2; - //--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- Step is too short,model is fresh and we can rely on it. -//--- Terminating. - state.m_repterminationtype=2; - if(!state.m_xrep) - return(false); -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_f=state.m_fbase; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=9; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_40(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { - state.m_nu=1; -//--- check - if(!CAp::Assert(iflag>=-3 && iflag<=0,"MinLM: internal integrity check failed!")) - return(false); -//--- check - if(iflag==-3) - { - state.m_repterminationtype=-3; - //--- return result - return(false); - } -//--- check - if(iflag==-2) - { - state.m_modelage=state.m_maxmodelage+1; - //--- function call, return result - return(Func_lbl_20(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(iflag==-1) - return(Func_lbl_21(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- Levenberg-Marquardt step is ready. -//--- Compare predicted vs. actual decrease and decide what to do with lambda. -//--- NOTE: we expect that State.DeltaX contains direction of step, -//--- State.F contains function value at new point. - if(!CAp::Assert(state.m_deltaxready,"MinLM: deltaX is not ready")) - return(false); - t=0; - for(i=0;i<=n-1;i++) - { - //--- change values - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_quadraticmodel[i][i_]*state.m_deltax[i_]; - t=t+state.m_deltax[i]*state.m_gbase[i]+0.5*state.m_deltax[i]*v; - } -//--- change values - state.m_predicteddecrease=-t; - state.m_actualdecrease=-(state.m_f-state.m_fbase); -//--- check - if(state.m_predicteddecrease<=0.0) - return(Func_lbl_21(state,n,m,iflag,i,k,bflag,v,s,t)); - v=state.m_actualdecrease/state.m_predicteddecrease; -//--- check - if(v>=0.1) - return(Func_lbl_49(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- check - if(IncreaseLambda(state.m_lambdav,state.m_nu)) - return(Func_lbl_49(state,n,m,iflag,i,k,bflag,v,s,t)); -//--- Lambda is too large,we have to break iterations. - state.m_repterminationtype=7; -//--- check - if(!state.m_xrep) - return(false); - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_f=state.m_fbase; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=12; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_41(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- Let's evaluate new step: -//--- a) if we have Fi vector,we evaluate it using rcomm,and -//--- then we manually calculate State.F as sum of squares of Fi[] -//--- b) if we have F value,we just evaluate it through rcomm interface -//--- We prefer (a) because we may need Fi vector for additional -//--- iterations - if(!CAp::Assert(state.m_hasfi|state.m_hasf,"MinLM: internal error 2!")) - return(false); - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+state.m_xdir[i_]; -//--- function call - ClearRequestFields(state); -//--- check - if(!state.m_hasfi) - { - //--- change values - state.m_needf=true; - state.m_rstate.stage=11; - //--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); - //--- return result - return(true); - } -//--- change values - state.m_needfi=true; - state.m_rstate.stage=10; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_48(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { - state.m_repnfunc=state.m_repnfunc+1; -//--- check - if(state.m_f>=state.m_fbase) - { - //--- Increase lambda and continue - if(!IncreaseLambda(state.m_lambdav,state.m_nu)) - { - iflag=-1; - //--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } - //--- function call, return result - return(Func_lbl_39(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- We've found our step! - iflag=0; -//--- function call, return result - return(Func_lbl_40(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_49(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { -//--- check - if(v>0.5) - DecreaseLambda(state.m_lambdav,state.m_nu); -//--- Accept step,report it and -//--- test stopping conditions on iterations count and function decrease. -//--- NOTE: we expect that State.DeltaX contains direction of step, -//--- State.F contains function value at new point. -//--- NOTE2: we should update XBase ONLY. In the beginning of the next -//--- iteration we expect that State.FIBase is NOT updated and -//--- contains old value of a function vector. - for(int i_=0;i_<=n-1;i_++) - state.m_xbase[i_]=state.m_xbase[i_]+state.m_deltax[i_]; -//--- check - if(!state.m_xrep) - return(Func_lbl_55(state,n,m,iflag,i,k,bflag,v,s,t)); - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=13; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinLMIteration. Is a product to get rid of| -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinLM::Func_lbl_55(CMinLMState &state,int &n,int &m,int &iflag, - int &i,int &k,bool &bflag,double &v, - double &s,double &t) - { - state.m_repiterationscount=state.m_repiterationscount+1; -//--- check - if(state.m_repiterationscount>=state.m_maxits&&state.m_maxits>0) - state.m_repterminationtype=5; -//--- check - if(state.m_modelage==0) - { - //--- check - if(MathAbs(state.m_f-state.m_fbase)<=state.m_epsf*MathMax(1,MathMax(MathAbs(state.m_f),MathAbs(state.m_fbase)))) - state.m_repterminationtype=1; - } -//--- check - if(state.m_repterminationtype<=0) - { - state.m_modelage=state.m_modelage+1; - //--- function call, return result - return(Func_lbl_20(state,n,m,iflag,i,k,bflag,v,s,t)); - } -//--- check - if(!state.m_xrep) - return(false); -//--- Report: XBase contains new point,F contains function value at new point - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=14; -//--- Saving state - Func_lbl_rcomm(state,n,m,iflag,i,k,bflag,v,s,t); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CMinComp | -//+------------------------------------------------------------------+ -class CMinASAState - { -public: - //--- variables - int m_n; - double m_epsg; - double m_epsf; - double m_epsx; - int m_maxits; - bool m_xrep; - double m_stpmax; - int m_cgtype; - int m_k; - int m_nfev; - int m_mcstage; - int m_curalgo; - int m_acount; - double m_mu; - double m_finit; - double m_dginit; - double m_fold; - double m_stp; - double m_laststep; - double m_f; - bool m_needfg; - bool m_xupdated; - RCommState m_rstate; - int m_repiterationscount; - int m_repnfev; - int m_repterminationtype; - int m_debugrestartscount; - CLinMinState m_lstate; - double m_betahs; - double m_betady; - //--- arrays - double m_bndl[]; - double m_bndu[]; - double m_ak[]; - double m_xk[]; - double m_dk[]; - double m_an[]; - double m_xn[]; - double m_dn[]; - double m_d[]; - double m_work[]; - double m_yk[]; - double m_gc[]; - double m_x[]; - double m_g[]; - //--- constructor, destructor - CMinASAState(void); - ~CMinASAState(void); - //--- copy - void Copy(CMinASAState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinASAState::CMinASAState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinASAState::~CMinASAState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinASAState::Copy(CMinASAState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_epsg=obj.m_epsg; - m_epsf=obj.m_epsf; - m_epsx=obj.m_epsx; - m_maxits=obj.m_maxits; - m_xrep=obj.m_xrep; - m_stpmax=obj.m_stpmax; - m_cgtype=obj.m_cgtype; - m_k=obj.m_k; - m_nfev=obj.m_nfev; - m_mcstage=obj.m_mcstage; - m_curalgo=obj.m_curalgo; - m_acount=obj.m_acount; - m_mu=obj.m_mu; - m_finit=obj.m_finit; - m_dginit=obj.m_dginit; - m_fold=obj.m_fold; - m_stp=obj.m_stp; - m_laststep=obj.m_laststep; - m_f=obj.m_f; - m_needfg=obj.m_needfg; - m_xupdated=obj.m_xupdated; - m_repiterationscount=obj.m_repiterationscount; - m_repnfev=obj.m_repnfev; - m_repterminationtype=obj.m_repterminationtype; - m_debugrestartscount=obj.m_debugrestartscount; - m_betahs=obj.m_betahs; - m_betady=obj.m_betady; - m_rstate.Copy(obj.m_rstate); - m_lstate.Copy(obj.m_lstate); -//--- copy arrays - ArrayCopy(m_bndl,obj.m_bndl); - ArrayCopy(m_bndu,obj.m_bndu); - ArrayCopy(m_ak,obj.m_ak); - ArrayCopy(m_xk,obj.m_xk); - ArrayCopy(m_dk,obj.m_dk); - ArrayCopy(m_an,obj.m_an); - ArrayCopy(m_xn,obj.m_xn); - ArrayCopy(m_dn,obj.m_dn); - ArrayCopy(m_d,obj.m_d); - ArrayCopy(m_work,obj.m_work); - ArrayCopy(m_yk,obj.m_yk); - ArrayCopy(m_gc,obj.m_gc); - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_g,obj.m_g); - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CMinASAState | -//+------------------------------------------------------------------+ -class CMinASAStateShell - { -private: - CMinASAState m_innerobj; -public: - //--- constructors, destructor - CMinASAStateShell(void); - CMinASAStateShell(CMinASAState &obj); - ~CMinASAStateShell(void); - //--- methods - bool GetNeedFG(void); - void SetNeedFG(const bool b); - bool GetXUpdated(void); - void SetXUpdated(const bool b); - double GetF(void); - void SetF(const double d); - CMinASAState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinASAStateShell::CMinASAStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinASAStateShell::CMinASAStateShell(CMinASAState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinASAStateShell::~CMinASAStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfg | -//+------------------------------------------------------------------+ -bool CMinASAStateShell::GetNeedFG(void) - { -//--- return result - return(m_innerobj.m_needfg); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfg | -//+------------------------------------------------------------------+ -void CMinASAStateShell::SetNeedFG(const bool b) - { -//--- change value - m_innerobj.m_needfg=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable xupdated | -//+------------------------------------------------------------------+ -bool CMinASAStateShell::GetXUpdated(void) - { -//--- return result - return(m_innerobj.m_xupdated); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable xupdated | -//+------------------------------------------------------------------+ -void CMinASAStateShell::SetXUpdated(const bool b) - { -//--- change value - m_innerobj.m_xupdated=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable f | -//+------------------------------------------------------------------+ -double CMinASAStateShell::GetF(void) - { -//--- return result - return(m_innerobj.m_f); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable f | -//+------------------------------------------------------------------+ -void CMinASAStateShell::SetF(const double d) - { -//--- change value - m_innerobj.m_f=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinASAState *CMinASAStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CMinComp | -//+------------------------------------------------------------------+ -class CMinASAReport - { -public: - //--- variables - int m_iterationscount; - int m_nfev; - int m_terminationtype; - int m_activeconstraints; - //--- constructor, destructor - CMinASAReport(void); - ~CMinASAReport(void); - //--- copy - void Copy(CMinASAReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinASAReport::CMinASAReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinASAReport::~CMinASAReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CMinASAReport::Copy(CMinASAReport &obj) - { -//--- copy variables - m_iterationscount=obj.m_iterationscount; - m_nfev=obj.m_nfev; - m_terminationtype=obj.m_terminationtype; - m_activeconstraints=obj.m_activeconstraints; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CMinASAReport | -//+------------------------------------------------------------------+ -class CMinASAReportShell - { -private: - CMinASAReport m_innerobj; -public: - //--- constructors, destructor - CMinASAReportShell(void); - CMinASAReportShell(CMinASAReport &obj); - ~CMinASAReportShell(void); - //--- methods - int GetIterationsCount(void); - void SetIterationsCount(const int i); - int GetNFev(void); - void SetNFev(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - int GetActiveConstraints(void); - void SetActiveConstraints(const int i); - CMinASAReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinASAReportShell::CMinASAReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CMinASAReportShell::CMinASAReportShell(CMinASAReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinASAReportShell::~CMinASAReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable iterationscount | -//+------------------------------------------------------------------+ -int CMinASAReportShell::GetIterationsCount(void) - { -//--- return result - return(m_innerobj.m_iterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable iterationscount | -//+------------------------------------------------------------------+ -void CMinASAReportShell::SetIterationsCount(const int i) - { -//--- change value - m_innerobj.m_iterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfev | -//+------------------------------------------------------------------+ -int CMinASAReportShell::GetNFev(void) - { -//--- return result - return(m_innerobj.m_nfev); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfev | -//+------------------------------------------------------------------+ -void CMinASAReportShell::SetNFev(const int i) - { -//--- change value - m_innerobj.m_nfev=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CMinASAReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CMinASAReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable activeconstraints | -//+------------------------------------------------------------------+ -int CMinASAReportShell::GetActiveConstraints(void) - { -//--- return result - return(m_innerobj.m_activeconstraints); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable activeconstraints | -//+------------------------------------------------------------------+ -void CMinASAReportShell::SetActiveConstraints(const int i) - { -//--- change value - m_innerobj.m_activeconstraints=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CMinASAReport *CMinASAReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Backward compatibility functions | -//+------------------------------------------------------------------+ -class CMinComp - { -private: - //--- private methods - static double ASABoundedAntigradNorm(CMinASAState &state); - static double ASAGINorm(CMinASAState &state); - static double ASAD1Norm(CMinASAState &state); - static bool ASAUIsEmpty(CMinASAState &state); - static void ClearRequestFields(CMinASAState &state); - //--- auxiliary functions for MinASAIteration - static void Func_lbl_rcomm(CMinASAState &state,int n,int i,int mcinfo,int diffcnt,bool b,bool stepfound,double betak,double v,double vv); - static bool Func_lbl_15(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_17(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_19(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_21(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_24(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_26(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_27(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_29(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_31(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_35(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_39(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_43(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_49(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_51(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_52(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_53(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_55(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_59(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_63(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); - static bool Func_lbl_65(CMinASAState &state,int &n,int &i,int &mcinfo,int &diffcnt,bool &b,bool &stepfound,double &betak,double &v,double &vv); -public: - //--- class constants - static const int m_n1; - static const int m_n2; - static const double m_stpmin; - static const double m_gtol; - static const double m_gpaftol; - static const double m_gpadecay; - static const double m_asarho; - //--- constructor, destructor - CMinComp(void); - ~CMinComp(void); - //--- public methods - static void MinLBFGSSetDefaultPreconditioner(CMinLBFGSState &state); - static void MinLBFGSSetCholeskyPreconditioner(CMinLBFGSState &state,CMatrixDouble &p,const bool isupper); - static void MinBLEICSetBarrierWidth(CMinBLEICState &state,const double mu); - static void MinBLEICSetBarrierDecay(CMinBLEICState &state,const double mudecay); - static void MinASACreate(const int n,double &x[],double &bndl[],double &bndu[],CMinASAState &state); - static void MinASASetCond(CMinASAState &state,const double epsg,const double epsf,double epsx,const int maxits); - static void MinASASetXRep(CMinASAState &state,const bool needxrep); - static void MinASASetAlgorithm(CMinASAState &state,int algotype); - static void MinASASetStpMax(CMinASAState &state,const double stpmax); - static void MinASAResults(CMinASAState &state,double &x[],CMinASAReport &rep); - static void MinASAResultsBuf(CMinASAState &state,double &x[],CMinASAReport &rep); - static void MinASARestartFrom(CMinASAState &state,double &x[],double &bndl[],double &bndu[]); - static bool MinASAIteration(CMinASAState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constants | -//+------------------------------------------------------------------+ -const int CMinComp::m_n1=2; -const int CMinComp::m_n2=2; -const double CMinComp::m_stpmin=1.0E-300; -const double CMinComp::m_gtol=0.3; -const double CMinComp::m_gpaftol=0.0001; -const double CMinComp::m_gpadecay=0.5; -const double CMinComp::m_asarho=0.5; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMinComp::CMinComp(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMinComp::~CMinComp(void) - { - - } -//+------------------------------------------------------------------+ -//| Obsolete function, use MinLBFGSSetPrecDefault() instead. | -//+------------------------------------------------------------------+ -static void CMinComp::MinLBFGSSetDefaultPreconditioner(CMinLBFGSState &state) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecDefault(state); - } -//+------------------------------------------------------------------+ -//| Obsolete function, use MinLBFGSSetCholeskyPreconditioner() | -//| instead. | -//+------------------------------------------------------------------+ -static void CMinComp::MinLBFGSSetCholeskyPreconditioner(CMinLBFGSState &state, - CMatrixDouble &p, - const bool isupper) - { -//--- function call - CMinLBFGS::MinLBFGSSetPrecCholesky(state,p,isupper); - } -//+------------------------------------------------------------------+ -//| This is obsolete function which was used by previous version of | -//| the BLEIC optimizer. It does nothing in the current version of | -//| BLEIC. | -//+------------------------------------------------------------------+ -static void CMinComp::MinBLEICSetBarrierWidth(CMinBLEICState &state, - const double mu) - { - - } -//+------------------------------------------------------------------+ -//| This is obsolete function which was used by previous version of | -//| the BLEIC optimizer. It does nothing in the current version of | -//| BLEIC. | -//+------------------------------------------------------------------+ -static void CMinComp::MinBLEICSetBarrierDecay(CMinBLEICState &state, - const double mudecay) - { - - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASACreate(const int n,double &x[],double &bndl[], - double &bndu[],CMinASAState &state) - { -//--- create a variable - int i=0; -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N too small!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=n,__FUNCTION__+": Length(BndL)=n,__FUNCTION__+": Length(BndU)=0.0,__FUNCTION__+": negative EpsG!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(CMath::IsFinite(epsx),__FUNCTION__+": EpsX is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsx>=0.0,__FUNCTION__+": negative EpsX!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- check - if(((epsg==0.0 && epsf==0.0) && epsx==0.0) && maxits==0) - epsx=1.0E-6; -//--- change values - state.m_epsg=epsg; - state.m_epsf=epsf; - state.m_epsx=epsx; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASASetXRep(CMinASAState &state,const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASASetAlgorithm(CMinASAState &state,int algotype) - { -//--- check - if(!CAp::Assert(algotype>=-1 && algotype<=1,__FUNCTION__+": incorrect AlgoType!")) - return; -//--- check - if(algotype==-1) - algotype=1; -//--- change value - state.m_cgtype=algotype; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASASetStpMax(CMinASAState &state,const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASAResults(CMinASAState &state,double &x[],CMinASAReport &rep) - { -//--- reset memory - ArrayResizeAL(x,0); -//--- function call - MinASAResultsBuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| Obsolete optimization algorithm. | -//| Was replaced by MinBLEIC subpackage. | -//+------------------------------------------------------------------+ -static void CMinComp::MinASAResultsBuf(CMinASAState &state,double &x[], - CMinASAReport &rep) - { -//--- create variables - int i=0; - int i_=0; -//--- check - if(CAp::Len(x)=state.m_n,__FUNCTION__+": Length(X)=state.m_n,__FUNCTION__+": Length(BndL)=state.m_n,__FUNCTION__+": Length(BndU)0)and(x[i]=bndu[i])) | -//| v[i]=-g[i] otherwise | -//| This function may be used to check a stopping criterion. | -//+------------------------------------------------------------------+ -static double CMinComp::ASABoundedAntigradNorm(CMinASAState &state) - { -//--- create variables - double result=0; - int i=0; - double v=0; -//--- initialization - result=0; - for(i=0;i<=state.m_n-1;i++) - { - v=-state.m_g[i]; - //--- check - if(state.m_x[i]==state.m_bndl[i] && -state.m_g[i]<0.0) - v=0; - //--- check - if(state.m_x[i]==state.m_bndu[i] && -state.m_g[i]>0.0) - v=0; - result=result+CMath::Sqr(v); - } -//--- return result - return(MathSqrt(result)); - } -//+------------------------------------------------------------------+ -//| Returns norm of GI(x). | -//| GI(x) is a gradient vector whose components associated with | -//| active constraints are zeroed. It differs from bounded | -//| anti-gradient because components of GI(x) are zeroed | -//| independently of sign(g[i]), and anti-gradient's components are | -//| zeroed with respect to both constraint and sign. | -//+------------------------------------------------------------------+ -static double CMinComp::ASAGINorm(CMinASAState &state) - { -//--- create variables - double result=0; - int i=0; -//--- initialization - result=0; - for(i=0;i<=state.m_n-1;i++) - { - //--- check - if(state.m_x[i]!=state.m_bndl[i] && state.m_x[i]!=state.m_bndu[i]) - result=result+CMath::Sqr(state.m_g[i]); - } -//--- return result - return(MathSqrt(result)); - } -//+------------------------------------------------------------------+ -//| Returns norm(D1(State.X)) | -//| For a meaning of D1 see 'NEW ACTIVE SET ALGORITHM FOR BOX | -//| CONSTRAINED OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.| -//+------------------------------------------------------------------+ -static double CMinComp::ASAD1Norm(CMinASAState &state) - { -//--- create variables - double result=0; - int i=0; -//--- initialization - result=0; - for(i=0;i<=state.m_n-1;i++) - result=result+CMath::Sqr(CApServ::BoundVal(state.m_x[i]-state.m_g[i],state.m_bndl[i],state.m_bndu[i])-state.m_x[i]); -//--- return result - return(MathSqrt(result)); - } -//+------------------------------------------------------------------+ -//| Returns True, if U set is empty. | -//| * State.X is used as point, | -//| * State.G - as gradient, | -//| * D is calculated within function (because State.D may have | -//| different meaning depending on current optimization algorithm) | -//| For a meaning of U see 'NEW ACTIVE SET ALGORITHM FOR BOX | -//| CONSTRAINED OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.| -//+------------------------------------------------------------------+ -static bool CMinComp::ASAUIsEmpty(CMinASAState &state) - { -//--- create variables - int i=0; - double d=0; - double d2=0; - double d32=0; -//--- initialization - d=ASAD1Norm(state); - d2=MathSqrt(d); - d32=d*d2; - for(i=0;i<=state.m_n-1;i++) - { - //--- check - if(MathAbs(state.m_g[i])>=d2 && MathMin(state.m_x[i]-state.m_bndl[i],state.m_bndu[i]-state.m_x[i])>=d32) - return(false); - } -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Clears request fileds (to be sure that we don't forgot to clear | -//| something) | -//+------------------------------------------------------------------+ -static void CMinComp::ClearRequestFields(CMinASAState &state) - { -//--- change values - state.m_needfg=false; - state.m_xupdated=false; - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -static bool CMinComp::MinASAIteration(CMinASAState &state) - { -//--- create variables - int n=0; - int i=0; - double betak=0; - double v=0; - double vv=0; - int mcinfo=0; - bool b; - bool stepfound; - int diffcnt=0; - int i_=0; -//--- This code initializes locals by: -//--- * random values determined during code -//--- generation - on first subroutine call -//--- * values from previous call - on subsequent calls - if(state.m_rstate.stage>=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - i=state.m_rstate.ia[1]; - mcinfo=state.m_rstate.ia[2]; - diffcnt=state.m_rstate.ia[3]; - b=state.m_rstate.ba[0]; - stepfound=state.m_rstate.ba[1]; - betak=state.m_rstate.ra[0]; - v=state.m_rstate.ra[1]; - vv=state.m_rstate.ra[2]; - } - else - { - //--- initialization - n=-983; - i=-989; - mcinfo=-834; - diffcnt=900; - b=true; - stepfound=false; - betak=214; - v=-338; - vv=-686; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change value - state.m_needfg=false; - //--- check - if(!state.m_xrep) - return(Func_lbl_15(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - //--- progress report - ClearRequestFields(state); - state.m_xupdated=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_15(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change values - state.m_needfg=false; - state.m_repnfev=state.m_repnfev+1; - stepfound=state.m_f<=state.m_finit+m_gpaftol*state.m_dginit; - //--- function call, return result - return(Func_lbl_24(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change values - state.m_needfg=false; - state.m_repnfev=state.m_repnfev+1; - //--- check - if(state.m_stp<=m_stpmin) - { - for(i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; - //--- function call, return result - return(Func_lbl_26(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } - //--- check - if(state.m_f<=state.m_finit+state.m_stp*m_gpaftol*state.m_dginit) - { - //--- copy - for(i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; - //--- function call, return result - return(Func_lbl_26(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } - //--- change value - state.m_stp=state.m_stp*m_gpadecay; - //--- function call, return result - return(Func_lbl_27(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==4) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_29(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==5) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==6) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==7) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==8) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==9) - { - //--- change value - state.m_needfg=false; - //--- postprocess data: zero components of G corresponding to - //--- the active constraints - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_x[i]==state.m_bndl[i] || state.m_x[i]==state.m_bndu[i]) - state.m_gc[i]=0; - else - state.m_gc[i]=state.m_g[i]; - } - CLinMin::MCSrch(n,state.m_xn,state.m_f,state.m_gc,state.m_d,state.m_stp,state.m_stpmax,m_gtol,mcinfo,state.m_nfev,state.m_work,state.m_lstate,state.m_mcstage); - //--- function call, return result - return(Func_lbl_51(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==10) - { - //--- change value - state.m_xupdated=false; - //--- function call, return result - return(Func_lbl_53(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- check - if(state.m_rstate.stage==11) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==12) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==13) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- check - if(state.m_rstate.stage==14) - { - //--- change value - state.m_xupdated=false; - //--- return result - return(false); - } -//--- Routine body -//--- Prepare - n=state.m_n; - state.m_repterminationtype=0; - state.m_repiterationscount=0; - state.m_repnfev=0; - state.m_debugrestartscount=0; - state.m_cgtype=1; -//--- copy - for(i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_x[i_]; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_xk[i]==state.m_bndl[i] || state.m_xk[i]==state.m_bndu[i]) - state.m_ak[i]=0; - else - state.m_ak[i]=1; - } -//--- change values - state.m_mu=0.1; - state.m_curalgo=0; -//--- Calculate F/G,initialize algorithm - ClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=0; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static void CMinComp::Func_lbl_rcomm(CMinASAState &state,int n,int i, - int mcinfo,int diffcnt,bool b, - bool stepfound,double betak, - double v,double vv) - { -//--- save - state.m_rstate.ia[0]=n; - state.m_rstate.ia[1]=i; - state.m_rstate.ia[2]=mcinfo; - state.m_rstate.ia[3]=diffcnt; - state.m_rstate.ba[0]=b; - state.m_rstate.ba[1]=stepfound; - state.m_rstate.ra[0]=betak; - state.m_rstate.ra[1]=v; - state.m_rstate.ra[2]=vv; - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_15(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(ASABoundedAntigradNorm(state)<=state.m_epsg) - { - state.m_repterminationtype=4; - //--- return result - return(false); - } - state.m_repnfev=state.m_repnfev+1; -//--- Main cycle -//--- At the beginning of new iteration: -//--- * CurAlgo stores current algorithm selector -//--- * State.XK,State.F and State.G store current X/F/G -//--- * State.AK stores current set of active constraints - return(Func_lbl_17(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_17(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- GPA algorithm - if(state.m_curalgo!=0) - return(Func_lbl_19(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- change values - state.m_k=0; - state.m_acount=0; -//--- function call, return result - return(Func_lbl_21(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_19(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- CG algorithm - if(state.m_curalgo!=1) - return(Func_lbl_17(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- first,check that there are non-active constraints. -//--- move to GPA algorithm,if all constraints are active - b=true; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_ak[i]!=0.0) - { - b=false; - break; - } - } -//--- check - if(b) - { - state.m_curalgo=0; - //--- function call, return result - return(Func_lbl_17(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- CG iterations - state.m_fold=state.m_f; - for(int i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_x[i_]; - for(i=0;i<=n-1;i++) - { - //--- change values - state.m_dk[i]=-(state.m_g[i]*state.m_ak[i]); - state.m_gc[i]=state.m_g[i]*state.m_ak[i]; - } -//--- function call, return result - return(Func_lbl_49(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_21(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Determine Dk=proj(xk - gk)-xk - for(i=0;i<=n-1;i++) - state.m_d[i]=CApServ::BoundVal(state.m_xk[i]-state.m_g[i],state.m_bndl[i],state.m_bndu[i])-state.m_xk[i]; -//--- Armijo line search. -//--- * exact search with alpha=1 is tried first, -//--- 'exact' means that we evaluate f() EXACTLY at -//--- bound(x-g,bndl,bndu),without intermediate floating -//--- point operations. -//--- * alpha<1 are tried if explicit search wasn't successful -//--- Result is placed into XN. -//--- Two types of search are needed because we can't -//--- just use second type with alpha=1 because in finite -//--- precision arithmetics (x1-x0)+x0 may differ from x1. -//--- So while x1 is correctly bounded (it lie EXACTLY on -//--- boundary,if it is active),(x1-x0)+x0 may be -//--- not bounded. - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_d[i_]*state.m_g[i_]; -//--- change values - state.m_dginit=v; - state.m_finit=state.m_f; -//--- check - if(!(ASAD1Norm(state)<=state.m_stpmax || state.m_stpmax==0.0)) - { - stepfound=false; - //--- function call, return result - return(Func_lbl_24(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- Try alpha=1 step first - for(i=0;i<=n-1;i++) - state.m_x[i]=CApServ::BoundVal(state.m_xk[i]-state.m_g[i],state.m_bndl[i],state.m_bndu[i]); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=2; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_24(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(!stepfound) - { - //--- alpha=1 is too large,try smaller values - state.m_stp=1; - //--- function call - CLinMin::LinMinNormalized(state.m_d,state.m_stp,n); - //--- change values - state.m_dginit=state.m_dginit/state.m_stp; - state.m_stp=m_gpadecay*state.m_stp; - //--- check - if(state.m_stpmax>0.0) - state.m_stp=MathMin(state.m_stp,state.m_stpmax); - //--- function call, return result - return(Func_lbl_27(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- we are at the boundary(ies) - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_x[i_]; - state.m_stp=1; -//--- function call, return result - return(Func_lbl_26(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_26(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { - state.m_repiterationscount=state.m_repiterationscount+1; -//--- check - if(!state.m_xrep) - return(Func_lbl_29(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- progress report - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=4; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_27(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { - v=state.m_stp; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xk[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+v*state.m_d[i_]; - ClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=3; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_29(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Calculate new set of active constraints. -//--- Reset counter if active set was changed. -//--- Prepare for the new iteration - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_xn[i]==state.m_bndl[i] || state.m_xn[i]==state.m_bndu[i]) - state.m_an[i]=0; - else - state.m_an[i]=1; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_ak[i]!=state.m_an[i]) - { - state.m_acount=-1; - break; - } - } - state.m_acount=state.m_acount+1; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_xn[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_ak[i_]=state.m_an[i_]; -//--- Stopping conditions - if(!(state.m_repiterationscount>=state.m_maxits&&state.m_maxits>0)) - return(Func_lbl_31(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- Too many iterations - state.m_repterminationtype=5; -//--- check - if(!state.m_xrep) - return(false); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=5; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_31(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(ASABoundedAntigradNorm(state)>state.m_epsg) - return(Func_lbl_35(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- Gradient is small enough - state.m_repterminationtype=4; -//--- check - if(!state.m_xrep) - return(false); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=6; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_35(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- change value - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_d[i_]*state.m_d[i_]; -//--- check - if(MathSqrt(v)*state.m_stp>state.m_epsx) - return(Func_lbl_39(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- Step size is too small,no further improvement is -//--- possible - state.m_repterminationtype=2; -//--- check - if(!state.m_xrep) - return(false); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=7; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_39(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(state.m_finit-state.m_f>state.m_epsf*MathMax(MathAbs(state.m_finit),MathMax(MathAbs(state.m_f),1.0))) - return(Func_lbl_43(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- F(k+1)-F(k) is small enough - state.m_repterminationtype=1; -//--- check - if(!state.m_xrep) - return(false); - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=8; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_43(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Decide - should we switch algorithm or not - if(ASAUIsEmpty(state)) - { - //--- check - if(ASAGINorm(state)>=state.m_mu*ASAD1Norm(state)) - { - state.m_curalgo=1; - //--- function call, return result - return(Func_lbl_19(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } - else - state.m_mu=state.m_mu*m_asarho; - } - else - { - //--- check - if(state.m_acount==m_n1) - { - //--- check - if(ASAGINorm(state)>=state.m_mu*ASAD1Norm(state)) - { - state.m_curalgo=1; - //--- function call, return result - return(Func_lbl_19(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } - } - } -//--- Next iteration - state.m_k=state.m_k+1; -//--- function call, return result - return(Func_lbl_21(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_49(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Store G[k] for later calculation of Y[k] - for(i=0;i<=n-1;i++) - state.m_yk[i]=-state.m_gc[i]; -//--- Make a CG step in direction given by DK[]: -//--- * calculate step. Step projection into feasible set -//--- is used. It has several benefits: a) step may be -//--- found with usual line search,b) multiple constraints -//--- may be activated with one step,c) activated constraints -//--- are detected in a natural way - just compare x[i] with -//--- bounds -//--- * update active set,set B to True,if there -//--- were changes in the set. - for(int i_=0;i_<=n-1;i_++) - state.m_d[i_]=state.m_dk[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_xn[i_]=state.m_xk[i_]; -//--- change values - state.m_mcstage=0; - state.m_stp=1; -//--- function call - CLinMin::LinMinNormalized(state.m_d,state.m_stp,n); -//--- check - if(state.m_laststep!=0.0) - state.m_stp=state.m_laststep; -//--- function call - CLinMin::MCSrch(n,state.m_xn,state.m_f,state.m_gc,state.m_d,state.m_stp,state.m_stpmax,m_gtol,mcinfo,state.m_nfev,state.m_work,state.m_lstate,state.m_mcstage); -//--- function call, return result - return(Func_lbl_51(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_51(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(state.m_mcstage==0) - return(Func_lbl_52(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- preprocess data: bound State.XN so it belongs to the -//--- feasible set and store it in the State.X - for(i=0;i<=n-1;i++) - state.m_x[i]=CApServ::BoundVal(state.m_xn[i],state.m_bndl[i],state.m_bndu[i]); -//--- RComm - ClearRequestFields(state); -//--- change values - state.m_needfg=true; - state.m_rstate.stage=9; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_52(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { - diffcnt=0; - for(i=0;i<=n-1;i++) - { - //--- XN contains unprojected result,project it, - //--- save copy to X (will be used for progress reporting) - state.m_xn[i]=CApServ::BoundVal(state.m_xn[i],state.m_bndl[i],state.m_bndu[i]); - //--- update active set - if(state.m_xn[i]==state.m_bndl[i] || state.m_xn[i]==state.m_bndu[i]) - state.m_an[i]=0; - else - state.m_an[i]=1; - //--- check - if(state.m_an[i]!=state.m_ak[i]) - diffcnt=diffcnt+1; - state.m_ak[i]=state.m_an[i]; - } - for(int i_=0;i_<=n-1;i_++) - state.m_xk[i_]=state.m_xn[i_]; -//--- change values - state.m_repnfev=state.m_repnfev+state.m_nfev; - state.m_repiterationscount=state.m_repiterationscount+1; -//--- check - if(!state.m_xrep) - return(Func_lbl_53(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- progress report - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=10; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_53(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Update info about step length - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_d[i_]*state.m_d[i_]; - state.m_laststep=MathSqrt(v)*state.m_stp; -//--- Check stopping conditions. - if(ASABoundedAntigradNorm(state)>state.m_epsg) - return(Func_lbl_55(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- Gradient is small enough - state.m_repterminationtype=4; -//--- check - if(!state.m_xrep) - return(false); - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=11; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_55(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(!(state.m_repiterationscount>=state.m_maxits && state.m_maxits>0)) - return(Func_lbl_59(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- Too many iterations - state.m_repterminationtype=5; -//--- check - if(!state.m_xrep) - return(false); - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=12; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_59(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(!(ASAGINorm(state)>=state.m_mu*ASAD1Norm(state) && diffcnt==0)) - return(Func_lbl_63(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- These conditions (EpsF/EpsX) are explicitly or implicitly -//--- related to the current step size and influenced -//--- by changes in the active constraints. -//--- For these reasons they are checked only when we don't -//--- want to 'unstick' at the end of the iteration and there -//--- were no changes in the active set. -//--- NOTE: consition |G|>=Mu*|D1| must be exactly opposite -//--- to the condition used to switch back to GPA. At least -//--- one inequality must be strict,otherwise infinite cycle -//--- may occur when |G|=Mu*|D1| (we DON'T test stopping -//--- conditions and we DON'T switch to GPA,so we cycle -//--- indefinitely). - if(state.m_fold-state.m_f>state.m_epsf*MathMax(MathAbs(state.m_fold),MathMax(MathAbs(state.m_f),1.0))) - return(Func_lbl_65(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- F(k+1)-F(k) is small enough - state.m_repterminationtype=1; - if(!state.m_xrep) - return(false); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=13; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_63(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- Check conditions for switching - if(ASAGINorm(state)0) - { - //--- check - if(ASAUIsEmpty(state) || diffcnt>=m_n2) - state.m_curalgo=1; - else - state.m_curalgo=0; - //--- function call, return result - return(Func_lbl_17(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//--- Calculate D(k+1) -//--- Line search may result in: -//--- * maximum feasible step being taken (already processed) -//--- * point satisfying Wolfe conditions -//--- * some kind of error (CG is restarted by assigning 0.0 to Beta) - if(mcinfo==1) - { - //--- Standard Wolfe conditions are satisfied: - //--- * calculate Y[K] and BetaK - for(int i_=0;i_<=n-1;i_++) - state.m_yk[i_]=state.m_yk[i_]+state.m_gc[i_]; - //--- change value - vv=0.0; - for(int i_=0;i_<=n-1;i_++) - vv+=state.m_yk[i_]*state.m_dk[i_]; - //--- change value - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_gc[i_]*state.m_gc[i_]; - state.m_betady=v/vv; - //--- change value - v=0.0; - for(int i_=0;i_<=n-1;i_++) - v+=state.m_gc[i_]*state.m_yk[i_]; - state.m_betahs=v/vv; - //--- check - if(state.m_cgtype==0) - betak=state.m_betady; - //--- check - if(state.m_cgtype==1) - betak=MathMax(0,MathMin(state.m_betady,state.m_betahs)); - } - else - { - //--- Something is wrong (may be function is too wild or too flat). - //--- We'll set BetaK=0,which will restart CG algorithm. - //--- We can stop later (during normal checks) if stopping conditions are met. - betak=0; - state.m_debugrestartscount=state.m_debugrestartscount+1; - } -//--- change values - for(int i_=0;i_<=n-1;i_++) - state.m_dn[i_]=-state.m_gc[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_dn[i_]=state.m_dn[i_]+betak*state.m_dk[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_dk[i_]=state.m_dn[i_]; -//--- update other information - state.m_fold=state.m_f; - state.m_k=state.m_k+1; -//--- function call, return result - return(Func_lbl_49(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for MinASAIteration. Is a product to get rid | -//| of the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static bool CMinComp::Func_lbl_65(CMinASAState &state,int &n,int &i, - int &mcinfo,int &diffcnt,bool &b, - bool &stepfound,double &betak, - double &v,double &vv) - { -//--- check - if(state.m_laststep>state.m_epsx) - return(Func_lbl_63(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv)); -//--- X(k+1)-X(k) is small enough - state.m_repterminationtype=2; -//--- check - if(!state.m_xrep) - return(false); -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_rstate.stage=14; -//--- Saving state - Func_lbl_rcomm(state,n,i,mcinfo,diffcnt,b,stepfound,betak,v,vv); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/solvers.mqh b/Include/Math/Alglib/solvers.mqh deleted file mode 100644 index 5b4d5ed..0000000 --- a/Include/Math/Alglib/solvers.mqh +++ /dev/null @@ -1,3829 +0,0 @@ -//+------------------------------------------------------------------+ -//| solvers.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "matrix.mqh" -#include "ap.mqh" -#include "alglibinternal.mqh" -#include "linalg.mqh" -//+------------------------------------------------------------------+ -//| Auxiliary class for CDenseSolver | -//+------------------------------------------------------------------+ -class CDenseSolverReport - { -public: - double m_r1; - double m_rinf; - - CDenseSolverReport(void); - ~CDenseSolverReport(void); - - void Copy(CDenseSolverReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDenseSolverReport::CDenseSolverReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDenseSolverReport::~CDenseSolverReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CDenseSolverReport::Copy(CDenseSolverReport &obj) - { -//--- copy variables - m_r1=obj.m_r1; - m_rinf=obj.m_rinf; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CDenseSolverReport | -//+------------------------------------------------------------------+ -class CDenseSolverReportShell - { -private: - CDenseSolverReport m_innerobj; -public: - //--- constructors, destructor - CDenseSolverReportShell(void); - CDenseSolverReportShell(CDenseSolverReport &obj); - ~CDenseSolverReportShell(void); - //--- methods - double GetR1(void); - void SetR1(const double d); - double GetRInf(void); - void SetRInf(const double d); - CDenseSolverReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDenseSolverReportShell::CDenseSolverReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CDenseSolverReportShell::CDenseSolverReportShell(CDenseSolverReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDenseSolverReportShell::~CDenseSolverReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable r1 | -//+------------------------------------------------------------------+ -double CDenseSolverReportShell::GetR1(void) - { -//--- return result - return(m_innerobj.m_r1); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable r1 | -//+------------------------------------------------------------------+ -void CDenseSolverReportShell::SetR1(const double d) - { -//--- change value - m_innerobj.m_r1=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable rinf | -//+------------------------------------------------------------------+ -double CDenseSolverReportShell::GetRInf(void) - { -//--- return result - return(m_innerobj.m_rinf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable rinf | -//+------------------------------------------------------------------+ -void CDenseSolverReportShell::SetRInf(const double d) - { -//--- change value - m_innerobj.m_rinf=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CDenseSolverReport *CDenseSolverReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CDenseSolver | -//+------------------------------------------------------------------+ -class CDenseSolverLSReport - { -public: - double m_r2; - CMatrixDouble m_cx; - int m_n; - int m_k; - //--- constructor, destructor - CDenseSolverLSReport(void); - ~CDenseSolverLSReport(void); - //--- copy - void Copy(CDenseSolverLSReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDenseSolverLSReport::CDenseSolverLSReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDenseSolverLSReport::~CDenseSolverLSReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CDenseSolverLSReport::Copy(CDenseSolverLSReport &obj) - { -//--- copy variables - m_r2=obj.m_r2; - m_n=obj.m_n; - m_k=obj.m_k; -//--- copy matrix - m_cx=obj.m_cx; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CDenseSolverLSReport | -//+------------------------------------------------------------------+ -class CDenseSolverLSReportShell - { -private: - CDenseSolverLSReport m_innerobj; -public: - //--- constructors, destructor - CDenseSolverLSReportShell(void); - CDenseSolverLSReportShell(CDenseSolverLSReport &obj); - ~CDenseSolverLSReportShell(void); - //--- methods - double GetR2(void); - void SetR2(const double d); - int GetN(void); - void SetN(const int i); - int GetK(void); - void SetK(const int i); - CDenseSolverLSReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDenseSolverLSReportShell::CDenseSolverLSReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CDenseSolverLSReportShell::CDenseSolverLSReportShell(CDenseSolverLSReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDenseSolverLSReportShell::~CDenseSolverLSReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable r2 | -//+------------------------------------------------------------------+ -double CDenseSolverLSReportShell::GetR2(void) - { -//--- return result - return(m_innerobj.m_r2); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable r2 | -//+------------------------------------------------------------------+ -void CDenseSolverLSReportShell::SetR2(const double d) - { -//--- change value - m_innerobj.m_r2=d; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable n | -//+------------------------------------------------------------------+ -int CDenseSolverLSReportShell::GetN(void) - { -//--- return result - return(m_innerobj.m_n); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable n | -//+------------------------------------------------------------------+ -void CDenseSolverLSReportShell::SetN(const int i) - { -//--- change value - m_innerobj.m_n=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable k | -//+------------------------------------------------------------------+ -int CDenseSolverLSReportShell::GetK(void) - { -//--- return result - return(m_innerobj.m_k); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable k | -//+------------------------------------------------------------------+ -void CDenseSolverLSReportShell::SetK(const int i) - { -//--- change value - m_innerobj.m_k=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CDenseSolverLSReport *CDenseSolverLSReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Dense solver | -//+------------------------------------------------------------------+ -class CDenseSolver - { -private: - //--- private methods - static void RMatrixLUSolveInternal(CMatrixDouble &lua,int &p[],const double scalea,const int n,CMatrixDouble &a,const bool havea,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void SPDMatrixCholeskySolveInternal(CMatrixDouble &cha,const double sqrtscalea,const int n,const bool isupper,CMatrixDouble &a,const bool havea,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void CMatrixLUSolveInternal(CMatrixComplex &lua,int &p[],const double scalea,const int n,CMatrixComplex &a,const bool havea,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void HPDMatrixCholeskySolveInternal(CMatrixComplex &cha,const double sqrtscalea,const int n,const bool isupper,CMatrixComplex &a,const bool havea,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static int CDenseSolverRFSMax(const int n,const double r1,const double rinf); - static int CDenseSolverRFSMaxV2(const int n,const double r2); - static void RBasicLUSolve(CMatrixDouble &lua,int &p[],const double scalea,const int n,double &xb[],double &tmp[]); - static void SPDBasicCholeskySolve(CMatrixDouble &cha,const double sqrtscalea,const int n,const bool isupper,double &xb[],double &tmp[]); - static void CBasicLUSolve(CMatrixComplex &lua,int &p[],const double scalea,const int n,al_complex &xb[],al_complex &tmp[]); - static void HPDBasicCholeskySolve(CMatrixComplex &cha,const double sqrtscalea,const int n,const bool isupper,al_complex &xb[],al_complex &tmp[]); -public: - //--- constructor, destructor - CDenseSolver(void); - ~CDenseSolver(void); - //--- public methods - static void RMatrixSolve(CMatrixDouble &a,const int n,double &b[],int &info,CDenseSolverReport &rep,double &x[]); - static void RMatrixSolveM(CMatrixDouble &a,const int n,CMatrixDouble &b,const int m,const bool rfs,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void RMatrixLUSolve(CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReport &rep,double &x[]); - static void RMatrixLUSolveM(CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReport &rep,double &x[]); - static void RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void CMatrixSolveM(CMatrixComplex &a,const int n,CMatrixComplex &b,const int m,const bool rfs,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void CMatrixSolve(CMatrixComplex &a,const int n,al_complex &b[],int &info,CDenseSolverReport &rep,al_complex &x[]); - static void CMatrixLUSolveM(CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void CMatrixLUSolve(CMatrixComplex &lua,int &p[],const int n,al_complex &b[],int &info,CDenseSolverReport &rep,al_complex &x[]); - static void CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,al_complex &b[],int &info,CDenseSolverReport &rep,al_complex &x[]); - static void SPDMatrixSolveM(CMatrixDouble &a,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void SPDMatrixSolve(CMatrixDouble &a,const int n,const bool isupper,double &b[],int &info,CDenseSolverReport &rep,double &x[]); - static void SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReport &rep,CMatrixDouble &x); - static void SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n,const bool isupper,double &b[],int &info,CDenseSolverReport &rep,double &x[]); - static void HPDMatrixSolveM(CMatrixComplex &a,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void HPDMatrixSolve(CMatrixComplex &a,const int n,const bool isupper,al_complex &b[],int &info,CDenseSolverReport &rep,al_complex &x[]); - static void HPDMatrixCholeskySolveM(CMatrixComplex &cha,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReport &rep,CMatrixComplex &x); - static void HPDMatrixCholeskySolve(CMatrixComplex &cha,const int n,const bool isupper,al_complex &b[],int &info,CDenseSolverReport &rep,al_complex &x[]); - static void RMatrixSolveLS(CMatrixDouble &a,const int nrows,const int ncols,double &b[],double threshold,int &info,CDenseSolverLSReport &rep,double &x[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDenseSolver::CDenseSolver(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDenseSolver::~CDenseSolver(void) - { - - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*x=b, where A is NxN | -//| non-denegerate real matrix, x and b are vectors. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - return code: | -//| * -3 A is singular, or VERY close to singular.| -//| X is filled by zeros in such cases. | -//| * -1 N<=0 was passed | -//| * 1 task is solved (but matrix A may be | -//| ill-conditioned, check R1/RInf parameters| -//| for condition numbers). | -//| Rep - solver report, see below for more info | -//| X - array[0..N-1], it contains: | -//| * solution of A*x=b if A is non-singular | -//| (well-conditioned or ill-conditioned, but not | -//| very close to singular) | -//| * zeros, if A is singular or VERY close to | -//| singular (in this case Info=-3). | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. | -//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixSolve(CMatrixDouble &a,const int n,double &b[], - int &info,CDenseSolverReport &rep, - double &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixDouble bm; - CMatrixDouble xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - RMatrixSolveM(a,n,bm,1,true,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixSolve() but solves task with multiple right | -//| parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * optional iterative refinement | -//| * O(N^3+M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| RFS - iterative refinement switch: | -//| * True - refinement is used. | -//| Less performance, more precision. | -//| * False - refinement is not used. | -//| More performance, less precision. | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixSolveM(CMatrixDouble &a,const int n, - CMatrixDouble &b,const int m, - const bool rfs,int &info, - CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create variables - double scalea=0; - int i=0; - int j=0; - int i_=0; -//--- create matrix - CMatrixDouble da; - CMatrixDouble emptya; -//--- create array - int p[]; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - da.Resize(n,n); -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - scalea=MathMax(scalea,MathAbs(a[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=n-1;i_++) - da[i].Set(i_,a[i][i_]); - } -//--- function call - CTrFac::RMatrixLU(da,n,n,p); -//--- check - if(rfs) - RMatrixLUSolveInternal(da,p,scalea,n,a,true,b,m,info,rep,x); - else - RMatrixLUSolveInternal(da,p,scalea,n,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*X=B, where A is NxN | -//| non-denegerate real matrix given by its LU decomposition, X and | -//| B are NxM real matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use RMatrixSolve or | -//| RMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixLUSolve(CMatrixDouble &lua,int &p[], - const int n,double &b[], - int &info,CDenseSolverReport &rep, - double &x[]) - { -//--- create matrix - CMatrixDouble bm; - CMatrixDouble xm; -//--- create a variable - int i_=0; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - RMatrixLUSolveM(lua,p,n,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixLUSolve() but solves task with multiple right | -//| parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use RMatrixSolve or | -//| RMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixLUSolveM(CMatrixDouble &lua,int &p[], - const int n,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create matrix - CMatrixDouble emptya; -//--- create variables - int i=0; - int j=0; - double scalea=0; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|U[i][j]|) -//--- we assume that LU is in its normal form,i.e. |L[i][j]|<=1 -//--- 2. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=i;j<=n-1;j++) - scalea=MathMax(scalea,MathAbs(lua[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; -//--- function call - RMatrixLUSolveInternal(lua,p,scalea,n,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND | -//| ITS LU DECOMPOSITION ARE KNOWN. You can use it if for some | -//| reasons you have both A and its LU decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua, - int &p[],const int n,double &b[], - int &info,CDenseSolverReport &rep, - double &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixDouble bm; - CMatrixDouble xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - RMatrixMixedSolveM(a,lua,p,n,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| Similar to RMatrixMixedSolve() but solves task with multiple | -//| right parts (where b and x are NxM matrices). | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua, - int &p[],const int n,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create variables - double scalea=0; - int i=0; - int j=0; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - scalea=MathMax(scalea,MathAbs(a[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; -//--- function call - RMatrixLUSolveInternal(lua,p,scalea,n,a,true,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for complex matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3+M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| RFS - iterative refinement switch: | -//| * True - refinement is used. | -//| Less performance, more precision. | -//| * False - refinement is not used. | -//| More performance, less precision. | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixSolveM(CMatrixComplex &a,const int n, - CMatrixComplex &b,const int m, - const bool rfs,int &info, - CDenseSolverReport &rep, - CMatrixComplex &x) - { -//--- create variables - double scalea=0; - int i=0; - int j=0; - int i_=0; -//--- create array - int p[]; -//--- create matrix - CMatrixComplex da; - CMatrixComplex emptya; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - da.Resize(n,n); -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - scalea=MathMax(scalea,CMath::AbsComplex(a[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; - for(i=0;i<=n-1;i++) - { - for(i_=0;i_<=n-1;i_++) - da[i].Set(i_,a[i][i_]); - } -//--- function call - CTrFac::CMatrixLU(da,n,n,p); -//--- check - if(rfs) - CMatrixLUSolveInternal(da,p,scalea,n,a,true,b,m,info,rep,x); - else - CMatrixLUSolveInternal(da,p,scalea,n,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for complex matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixSolve(CMatrixComplex &a,const int n, - al_complex &b[],int &info, - CDenseSolverReport &rep,al_complex &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixComplex bm; - CMatrixComplex xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - CMatrixSolveM(a,n,bm,1,true,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use CMatrixSolve or | -//| CMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, RMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixLUSolveM(CMatrixComplex &lua,int &p[], - const int n,CMatrixComplex &b, - const int m,int &info, - CDenseSolverReport &rep, - CMatrixComplex &x) - { -//--- create variables - int i=0; - int j=0; - double scalea=0; -//--- create matrix - CMatrixComplex emptya; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|U[i][j]|) -//--- we assume that LU is in its normal form,i.e. |L[i][j]|<=1 -//--- 2. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=i;j<=n-1;j++) - scalea=MathMax(scalea,CMath::AbsComplex(lua[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; -//--- function call - CMatrixLUSolveInternal(lua,p,scalea,n,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for complex matrices.| -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| No iterative refinement is provided because exact form of | -//| original matrix is not known to subroutine. Use CMatrixSolve or | -//| CMatrixMixedSolve if you need iterative refinement. | -//| INPUT PARAMETERS | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixLUSolve(CMatrixComplex &lua,int &p[], - const int n,al_complex &b[],int &info, - CDenseSolverReport &rep,al_complex &x[]) - { -//--- create matrix - CMatrixComplex bm; - CMatrixComplex xm; -//--- create a variable - int i_=0; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - CMatrixLUSolveM(lua,p,n,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixMixedSolveM(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(M*N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua, - int &p[],const int n,CMatrixComplex &b, - const int m,int &info,CDenseSolverReport &rep, - CMatrixComplex &x) - { -//--- create variables - double scalea=0; - int i=0; - int j=0; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - scalea=0; - for(i=0;i<=n-1;i++) - { - for(j=0;j<=n-1;j++) - scalea=MathMax(scalea,CMath::AbsComplex(a[i][j])); - } -//--- check - if(scalea==0.0) - scalea=1; -//--- change values - scalea=1/scalea; -//--- function call - CMatrixLUSolveInternal(lua,p,scalea,n,a,true,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixMixedSolve(), but for complex | -//| matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * iterative refinement | -//| * O(N^2) complexity | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU| -//| result | -//| P - array[0..N-1], pivots array, CMatrixLU result | -//| N - size of A | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolveM | -//| Rep - same as in RMatrixSolveM | -//| X - same as in RMatrixSolveM | -//+------------------------------------------------------------------+ -static void CDenseSolver::CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua, - int &p[],const int n,al_complex &b[], - int &info,CDenseSolverReport &rep, - al_complex &x[]) - { -//--- create matrix - CMatrixComplex bm; - CMatrixComplex xm; -//--- create a variable - int i_=0; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - CMatrixMixedSolveM(a,lua,p,n,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for symmetric positive| -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3+M*N^2) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve. | -//| Returns -3 for non-SPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::SPDMatrixSolveM(CMatrixDouble &a,const int n, - const bool isupper,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create variables - double sqrtscalea=0; - int i=0; - int j=0; - int j1=0; - int j2=0; - int i_=0; -//--- create matrix - CMatrixDouble da; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - da.Resize(n,n); -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - sqrtscalea=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(j=j1;j<=j2;j++) - sqrtscalea=MathMax(sqrtscalea,MathAbs(a[i][j])); - } -//--- check - if(sqrtscalea==0.0) - sqrtscalea=1; -//--- change values - sqrtscalea=1/sqrtscalea; - sqrtscalea=MathSqrt(sqrtscalea); - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(i_=j1;i_<=j2;i_++) - da[i].Set(i_,a[i][i_]); - } -//--- check - if(!CTrFac::SPDMatrixCholesky(da,n,isupper)) - { - //--- allocation - x.Resize(n,m); - for(i=0;i<=n-1;i++) - { - for(j=0;j<=m-1;j++) - x[i].Set(j,0); - } - //--- change values - rep.m_r1=0; - rep.m_rinf=0; - info=-3; - //--- exit the function - return; - } - info=1; -//--- function call - SPDMatrixCholeskySolveInternal(da,sqrtscalea,n,isupper,a,true,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for SPD matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Returns -3 for non-SPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::SPDMatrixSolve(CMatrixDouble &a,const int n, - const bool isupper,double &b[], - int &info,CDenseSolverReport &rep, - double &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixDouble bm; - CMatrixDouble xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - SPDMatrixSolveM(a,n,isupper,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for SPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of CHA | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n, - const bool isupper,CMatrixDouble &b, - const int m,int &info, - CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create variables - double sqrtscalea=0; - int i=0; - int j=0; - int j1=0; - int j2=0; -//--- create matrix - CMatrixDouble emptya; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|U[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - sqrtscalea=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(j=j1;j<=j2;j++) - sqrtscalea=MathMax(sqrtscalea,MathAbs(cha[i][j])); - } -//--- check - if(sqrtscalea==0.0) - sqrtscalea=1; -//--- change values - sqrtscalea=1/sqrtscalea; -//--- function call - SPDMatrixCholeskySolveInternal(cha,sqrtscalea,n,isupper,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for SPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of A | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n, - const bool isupper,double &b[], - int &info,CDenseSolverReport &rep, - double &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixDouble bm; - CMatrixDouble xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - SPDMatrixCholeskySolveM(cha,n,isupper,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolveM(), but for Hermitian positive| -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3+M*N^2) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve. | -//| Returns -3 for non-HPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::HPDMatrixSolveM(CMatrixComplex &a,const int n, - const bool isupper,CMatrixComplex &b, - const int m,int &info, - CDenseSolverReport &rep,CMatrixComplex &x) - { -//--- create variables - double sqrtscalea=0; - int i=0; - int j=0; - int j1=0; - int j2=0; - int i_=0; -//--- create matrix - CMatrixComplex da; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - da.Resize(n,n); -//--- 1. scale matrix,max(|A[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - sqrtscalea=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(j=j1;j<=j2;j++) - sqrtscalea=MathMax(sqrtscalea,CMath::AbsComplex(a[i][j])); - } -//--- check - if(sqrtscalea==0.0) - sqrtscalea=1; -//--- change values - sqrtscalea=1/sqrtscalea; - sqrtscalea=MathSqrt(sqrtscalea); - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(i_=j1;i_<=j2;i_++) - da[i].Set(i_,a[i][i_]); - } -//--- check - if(!CTrFac::HPDMatrixCholesky(da,n,isupper)) - { - //--- allocation - x.Resize(n,m); - for(i=0;i<=n-1;i++) - { - for(j=0;j<=m-1;j++) - x[i].Set(j,0); - } - //--- change values - rep.m_r1=0; - rep.m_rinf=0; - info=-3; - //--- exit the function - return; - } - info=1; -//--- function call - HPDMatrixCholeskySolveInternal(da,sqrtscalea,n,isupper,a,true,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixSolve(), but for Hermitian positive | -//| definite matrices. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * condition number estimation | -//| * O(N^3) complexity | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| A - array[0..N-1,0..N-1], system matrix | -//| N - size of A | -//| IsUpper - what half of A is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Returns -3 for non-HPD matrices. | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::HPDMatrixSolve(CMatrixComplex &a,const int n, - const bool isupper,al_complex &b[], - int &info,CDenseSolverReport &rep, - al_complex &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixComplex bm; - CMatrixComplex xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - HPDMatrixSolveM(a,n,isupper,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(M*N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| HPDMatrixCholesky result | -//| N - size of CHA | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1,0..M-1], right part | -//| M - right part size | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::HPDMatrixCholeskySolveM(CMatrixComplex &cha, - const int n,const bool isupper, - CMatrixComplex &b,const int m, - int &info,CDenseSolverReport &rep, - CMatrixComplex &x) - { -//--- create variables - double sqrtscalea=0; - int i=0; - int j=0; - int j1=0; - int j2=0; -//--- create matrix - CMatrixComplex emptya; -//--- initialization - info=0; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- 1. scale matrix,max(|U[i][j]|) -//--- 2. factorize scaled matrix -//--- 3. solve - sqrtscalea=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(isupper) - { - j1=i; - j2=n-1; - } - else - { - j1=0; - j2=i; - } - //--- calculation - for(j=j1;j<=j2;j++) - { - sqrtscalea=MathMax(sqrtscalea,CMath::AbsComplex(cha[i][j])); - } - } -//--- check - if(sqrtscalea==0.0) - { - sqrtscalea=1; - } -//--- change values - sqrtscalea=1/sqrtscalea; -//--- function call - HPDMatrixCholeskySolveInternal(cha,sqrtscalea,n,isupper,emptya,false,b,m,info,rep,x); - } -//+------------------------------------------------------------------+ -//| Dense solver. Same as RMatrixLUSolve(), but for HPD matrices | -//| represented by their Cholesky decomposition. | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * O(N^2) complexity | -//| * condition number estimation | -//| * matrix is represented by its upper or lower triangle | -//| No iterative refinement is provided because such partial | -//| representation of matrix does not allow efficient calculation of | -//| extra-precise matrix-vector products for large matrices. Use | -//| RMatrixSolve or RMatrixMixedSolve if you need iterative | -//| refinement. | -//| INPUT PARAMETERS | -//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, | -//| SPDMatrixCholesky result | -//| N - size of A | -//| IsUpper - what half of CHA is provided | -//| B - array[0..N-1], right part | -//| OUTPUT PARAMETERS | -//| Info - same as in RMatrixSolve | -//| Rep - same as in RMatrixSolve | -//| X - same as in RMatrixSolve | -//+------------------------------------------------------------------+ -static void CDenseSolver::HPDMatrixCholeskySolve(CMatrixComplex &cha, - const int n,const bool isupper, - al_complex &b[],int &info, - CDenseSolverReport &rep, - al_complex &x[]) - { -//--- create a variable - int i_=0; -//--- create matrix - CMatrixComplex bm; - CMatrixComplex xm; -//--- initialization - info=0; -//--- check - if(n<=0) - { - info=-1; - return; - } -//--- allocation - bm.Resize(n,1); -//--- filling - for(i_=0;i_<=n-1;i_++) - bm[i_].Set(0,b[i_]); -//--- function call - HPDMatrixCholeskySolveM(cha,n,isupper,bm,1,info,rep,xm); -//--- allocation - ArrayResizeAL(x,n); -//--- copy - for(i_=0;i_<=n-1;i_++) - x[i_]=xm[i_][0]; - } -//+------------------------------------------------------------------+ -//| Dense solver. | -//| This subroutine finds solution of the linear system A*X=B with | -//| non-square, possibly degenerate A. System is solved in the least | -//| squares sense, and general least squares solution X = X0 + CX*y | -//| which minimizes |A*X-B| is returned. If A is non-degenerate, | -//| solution in the usual sense is returned | -//| Algorithm features: | -//| * automatic detection of degenerate cases | -//| * iterative refinement | -//| * O(N^3) complexity | -//| INPUT PARAMETERS | -//| A - array[0..NRows-1,0..NCols-1], system matrix | -//| NRows - vertical size of A | -//| NCols - horizontal size of A | -//| B - array[0..NCols-1], right part | -//| Threshold- a number in [0,1]. Singular values beyond | -//| Threshold are considered zero. Set it to 0.0, | -//| if you don't understand what it means, so the | -//| solver will choose good value on its own. | -//| OUTPUT PARAMETERS | -//| Info - return code: | -//| * -4 SVD subroutine failed | -//| * -1 if NRows<=0 or NCols<=0 or Threshold<0 | -//| was passed | -//| * 1 if task is solved | -//| Rep - solver report, see below for more info | -//| X - array[0..N-1,0..M-1], it contains: | -//| * solution of A*X=B if A is non-singular | -//| (well-conditioned or ill-conditioned, but not | -//| very close to singular) | -//| * zeros, if A is singular or VERY close to | -//| singular (in this case Info=-3). | -//| SOLVER REPORT | -//| Subroutine sets following fields of the Rep structure: | -//| * R2 reciprocal of condition number: 1/cond(A), 2-norm. | -//| * N = NCols | -//| * K dim(Null(A)) | -//| * CX array[0..N-1,0..K-1], kernel of A. | -//| Columns of CX store such vectors that A*CX[i]=0. | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixSolveLS(CMatrixDouble &a,const int nrows, - const int ncols,double &b[], - double threshold,int &info, - CDenseSolverLSReport &rep, - double &x[]) - { -//--- create matrix - CMatrixDouble u; - CMatrixDouble vt; -//--- create arrays - double sv[]; - double rp[]; - double utb[]; - double sutb[]; - double tmp[]; - double ta[]; - double tx[]; - double buf[]; - double w[]; -//--- create variables - int i=0; - int j=0; - int nsv=0; - int kernelidx=0; - double v=0; - double verr=0; - bool svdfailed; - bool zeroa; - int rfs=0; - int nrfs=0; - bool terminatenexttime; - bool smallerr; - int i_=0; -//--- initialization - info=0; -//--- check - if((nrows<=0 || ncols<=0) || threshold<0.0) - { - info=-1; - return; - } -//--- check - if(threshold==0.0) - threshold=1000*CMath::m_machineepsilon; -//--- Factorize A first - svdfailed=!CSingValueDecompose::RMatrixSVD(a,nrows,ncols,1,2,2,sv,u,vt); -//--- check - if(sv[0]==0.0) - zeroa=true; - else - zeroa=false; -//--- check - if(svdfailed || zeroa) - { - //--- check - if(svdfailed) - info=-4; - else - info=1; - //--- allocation - ArrayResizeAL(x,ncols); - for(i=0;i<=ncols-1;i++) - x[i]=0; - //--- change values - rep.m_n=ncols; - rep.m_k=ncols; - rep.m_cx.Resize(ncols,ncols); - for(i=0;i<=ncols-1;i++) - { - for(j=0;j<=ncols-1;j++) - { - //--- check - if(i==j) - rep.m_cx[i].Set(j,1); - else - rep.m_cx[i].Set(j,0); - } - } - rep.m_r2=0; - //--- exit the function - return; - } - nsv=MathMin(ncols,nrows); -//--- check - if(nsv==ncols) - rep.m_r2=sv[nsv-1]/sv[0]; - else - rep.m_r2=0; -//--- change values - rep.m_n=ncols; - info=1; -//--- Iterative refinement of xc combined with solution: -//--- 1. xc=0 -//--- 2. calculate r=bc-A*xc using extra-precise dot product -//--- 3. solve A*y=r -//--- 4. update x:=x+r -//--- 5. goto 2 -//--- This cycle is executed until one of two things happens: -//--- 1. maximum number of iterations reached -//--- 2. last iteration decreased error to the lower limit - ArrayResizeAL(utb,nsv); - ArrayResizeAL(sutb,nsv); - ArrayResizeAL(x,ncols); - ArrayResizeAL(tmp,ncols); - ArrayResizeAL(ta,ncols+1); - ArrayResizeAL(tx,ncols+1); - ArrayResizeAL(buf,ncols+1); -//--- initialization - for(i=0;i<=ncols-1;i++) - x[i]=0; - kernelidx=nsv; - for(i=0;i<=nsv-1;i++) - { - //--- check - if(sv[i]<=threshold*sv[0]) - { - kernelidx=i; - break; - } - } -//--- change values - rep.m_k=ncols-kernelidx; - nrfs=CDenseSolverRFSMaxV2(ncols,rep.m_r2); - terminatenexttime=false; -//--- allocation - ArrayResizeAL(rp,nrows); - for(rfs=0;rfs<=nrfs;rfs++) - { - //--- check - if(terminatenexttime) - break; - //--- calculate right part - if(rfs==0) - { - for(i_=0;i_<=nrows-1;i_++) - rp[i_]=b[i_]; - } - else - { - smallerr=true; - for(i=0;i<=nrows-1;i++) - { - //--- copy - for(i_=0;i_<=ncols-1;i_++) - ta[i_]=a[i][i_]; - ta[ncols]=-1; - //--- copy - for(i_=0;i_<=ncols-1;i_++) - tx[i_]=x[i_]; - tx[ncols]=b[i]; - //--- function call - CXblas::XDot(ta,tx,ncols+1,buf,v,verr); - rp[i]=-v; - smallerr=smallerr && MathAbs(v)<4*verr; - } - //--- check - if(smallerr) - terminatenexttime=true; - } - //--- solve A*dx=rp - for(i=0;i<=ncols-1;i++) - tmp[i]=0; - for(i=0;i<=nsv-1;i++) - utb[i]=0; - //--- change values - for(i=0;i<=nrows-1;i++) - { - v=rp[i]; - for(i_=0;i_<=nsv-1;i_++) - utb[i_]=utb[i_]+v*u[i][i_]; - } - for(i=0;i<=nsv-1;i++) - { - //--- check - if(i0) - { - //--- allocation - rep.m_cx.Resize(ncols,rep.m_k); - for(i=0;i<=rep.m_k-1;i++) - { - for(i_=0;i_<=ncols-1;i_++) - rep.m_cx[i_].Set(i,vt[kernelidx+i][i_]); - } - } - } -//+------------------------------------------------------------------+ -//| Internal LU solver | -//+------------------------------------------------------------------+ -static void CDenseSolver::RMatrixLUSolveInternal(CMatrixDouble &lua,int &p[], - const double scalea,const int n, - CMatrixDouble &a,const bool havea, - CMatrixDouble &b,const int m, - int &info,CDenseSolverReport &rep, - CMatrixDouble &x) - { -//--- create variables - int i=0; - int j=0; - int k=0; - int rfs=0; - int nrfs=0; - double v=0; - double verr=0; - double mxb=0; - double scaleright=0; - bool smallerr; - bool terminatenexttime; - int i_=0; -//--- create arrays - double xc[]; - double y[]; - double bc[]; - double xa[]; - double xb[]; - double tx[]; -//--- initialization - info=0; -//--- check - if(!CAp::Assert(scalea>0.0)) - return; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(p[i]>n-1 || p[i]0.0)) - return; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - x.Resize(n,m); - ArrayResizeAL(y,n); - ArrayResizeAL(xc,n); - ArrayResizeAL(bc,n); - ArrayResizeAL(tx,n+1); - ArrayResizeAL(xa,n+1); - ArrayResizeAL(xb,n+1); -//--- estimate condition number,test for near singularity - rep.m_r1=CRCond::SPDMatrixCholeskyRCond(cha,n,isupper); - rep.m_rinf=rep.m_r1; -//--- check - if(rep.m_r10.0)) - return; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } - for(i=0;i<=n-1;i++) - { - //--- check - if(p[i]>n-1 || p[i]0.0)) - return; -//--- prepare: check inputs,allocate space... - if(n<=0 || m<=0) - { - info=-1; - return; - } -//--- allocation - x.Resize(n,m); - ArrayResizeAL(y,n); - ArrayResizeAL(xc,n); - ArrayResizeAL(bc,n); - ArrayResizeAL(tx,n+1); - ArrayResizeAL(xa,n+1); - ArrayResizeAL(xb,n+1); -//--- estimate condition number,test for near singularity - rep.m_r1=CRCond::HPDMatrixCholeskyRCond(cha,n,isupper); - rep.m_rinf=rep.m_r1; -//--- check - if(rep.m_r1=0;i--) - { - //--- calculation - for(i_=i+1;i_<=n-1;i_++) - tmp[i_]=lua[i][i_]*scalea; - v=0.0; - //--- change value - for(i_=i+1;i_<=n-1;i_++) - v+=tmp[i_]*xb[i_]; - //--- get result - xb[i]=(xb[i]-v)/(lua[i][i]*scalea); - } - } -//+------------------------------------------------------------------+ -//| Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. | -//| This subroutine assumes that: | -//| * A*ScaleA is well scaled | -//| * A is well-conditioned, so no zero divisions or overflow may | -//| occur | -//+------------------------------------------------------------------+ -static void CDenseSolver::SPDBasicCholeskySolve(CMatrixDouble &cha, - const double sqrtscalea, - const int n,const bool isupper, - double &xb[],double &tmp[]) - { -//--- create variables - int i=0; - double v=0; - int i_=0; -//--- A=L*L' or A=U'*U - if(isupper) - { - //--- Solve U'*y=b first. - for(i=0;i<=n-1;i++) - { - xb[i]=xb[i]/(sqrtscalea*cha[i][i]); - //--- check - if(i=0;i--) - { - //--- check - if(i0) - { - for(i_=0;i_<=i-1;i_++) - tmp[i_]=sqrtscalea*cha[i][i_]; - //--- change value - v=0.0; - for(i_=0;i_<=i-1;i_++) - v+=tmp[i_]*xb[i_]; - //--- shift - xb[i]=xb[i]-v; - } - xb[i]=xb[i]/(sqrtscalea*cha[i][i]); - } - //--- Solve L'*x=y then. - for(i=n-1;i>=0;i--) - { - xb[i]=xb[i]/(sqrtscalea*cha[i][i]); - //--- check - if(i>0) - { - v=xb[i]; - //--- calculation - for(i_=0;i_<=i-1;i_++) - tmp[i_]=sqrtscalea*cha[i][i_]; - for(i_=0;i_<=i-1;i_++) - xb[i_]=xb[i_]-v*tmp[i_]; - } - } - } - } -//+------------------------------------------------------------------+ -//| Basic LU solver for ScaleA*PLU*x = y. | -//| This subroutine assumes that: | -//| * L is well-scaled, and it is U which needs scaling by ScaleA. | -//| * A=PLU is well-conditioned, so no zero divisions or overflow may| -//| occur | -//+------------------------------------------------------------------+ -static void CDenseSolver::CBasicLUSolve(CMatrixComplex &lua,int &p[], - const double scalea,const int n, - al_complex &xb[],al_complex &tmp[]) - { -//--- create variables - int i=0; - al_complex v=0; - int i_=0; -//--- swap - for(i=0;i<=n-1;i++) - { - //--- check - if(p[i]!=i) - { - v=xb[i]; - xb[i]=xb[p[i]]; - xb[p[i]]=v; - } - } - for(i=1;i<=n-1;i++) - { - v=0.0; - //--- calculation - for(i_=0;i_<=i-1;i_++) - v+=lua[i][i_]*xb[i_]; - //--- shift - xb[i]=xb[i]-v; - } -//--- change values - xb[n-1]=xb[n-1]/(lua[n-1][n-1]*scalea); - for(i=n-2;i>=0;i--) - { - for(i_=i+1;i_<=n-1;i_++) - tmp[i_]=lua[i][i_]*scalea; - //--- calculation - v=0.0; - for(i_=i+1;i_<=n-1;i_++) - v+=tmp[i_]*xb[i_]; - //--- get result - xb[i]=(xb[i]-v)/(lua[i][i]*scalea); - } - } -//+------------------------------------------------------------------+ -//| Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. | -//| This subroutine assumes that: | -//| * A*ScaleA is well scaled | -//| * A is well-conditioned, so no zero divisions or overflow may | -//| occur | -//+------------------------------------------------------------------+ -static void CDenseSolver::HPDBasicCholeskySolve(CMatrixComplex &cha, - const double sqrtscalea, - const int n,const bool isupper, - al_complex &xb[],al_complex &tmp[]) - { -//--- create variables - int i=0; - al_complex v=0; - int i_=0; -//--- A=L*L' or A=U'*U - if(isupper) - { - //--- Solve U'*y=b first. - for(i=0;i<=n-1;i++) - { - xb[i]=xb[i]/(CMath::Conj(cha[i][i])*sqrtscalea); - //--- check - if(i=0;i--) - { - //--- check - if(i0) - { - for(i_=0;i_<=i-1;i_++) - tmp[i_]=cha[i][i_]*sqrtscalea; - //--- change value - v=0.0; - for(i_=0;i_<=i-1;i_++) - v+=tmp[i_]*xb[i_]; - //--- shift - xb[i]=xb[i]-v; - } - xb[i]=xb[i]/(cha[i][i]*sqrtscalea); - } - //--- Solve L'*x=y then. - for(i=n-1;i>=0;i--) - { - xb[i]=xb[i]/(CMath::Conj(cha[i][i])*sqrtscalea); - //--- check - if(i>0) - { - v=xb[i]; - //--- calculation - for(i_=0;i_<=i-1;i_++) - tmp[i_]=CMath::Conj(cha[i][i_])*sqrtscalea; - for(i_=0;i_<=i-1;i_++) - xb[i_]=xb[i_]-v*tmp[i_]; - } - } - } - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CNlEq | -//+------------------------------------------------------------------+ -class CNlEqState - { -public: - //--- variables - int m_n; - int m_m; - double m_epsf; - int m_maxits; - bool m_xrep; - double m_stpmax; - double m_f; - bool m_needf; - bool m_needfij; - bool m_xupdated; - RCommState m_rstate; - int m_repiterationscount; - int m_repnfunc; - int m_repnjac; - int m_repterminationtype; - double m_fbase; - double m_fprev; - //--- arrays - double m_x[]; - double m_fi[]; - double m_xbase[]; - double m_candstep[]; - double m_rightpart[]; - double m_cgbuf[]; - //--- matrix - CMatrixDouble m_j; - //--- constructor, destructor - CNlEqState(void); - ~CNlEqState(void); - //--- copy - void Copy(CNlEqState &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNlEqState::CNlEqState(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNlEqState::~CNlEqState(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CNlEqState::Copy(CNlEqState &obj) - { -//--- copy variables - m_n=obj.m_n; - m_m=obj.m_m; - m_epsf=obj.m_epsf; - m_maxits=obj.m_maxits; - m_xrep=obj.m_xrep; - m_stpmax=obj.m_stpmax; - m_f=obj.m_f; - m_needf=obj.m_needf; - m_needfij=obj.m_needfij; - m_xupdated=obj.m_xupdated; - m_repiterationscount=obj.m_repiterationscount; - m_repnfunc=obj.m_repnfunc; - m_repnjac=obj.m_repnjac; - m_repterminationtype=obj.m_repterminationtype; - m_fbase=obj.m_fbase; - m_fprev=obj.m_fprev; - m_rstate.Copy(obj.m_rstate); -//--- copy arrays - ArrayCopy(m_x,obj.m_x); - ArrayCopy(m_fi,obj.m_fi); - ArrayCopy(m_xbase,obj.m_xbase); - ArrayCopy(m_candstep,obj.m_candstep); - ArrayCopy(m_rightpart,obj.m_rightpart); - ArrayCopy(m_cgbuf,obj.m_cgbuf); -//--- copy matrix - m_j=obj.m_j; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CNlEqState | -//+------------------------------------------------------------------+ -class CNlEqStateShell - { -private: - CNlEqState m_innerobj; -public: - //--- constructors, destructor - CNlEqStateShell(void); - CNlEqStateShell(CNlEqState &obj); - ~CNlEqStateShell(void); - //--- methods - bool GetNeedF(void); - void SetNeedF(const bool b); - bool GetNeedFIJ(void); - void SetNeedFIJ(const bool b); - bool GetXUpdated(void); - void SetXUpdated(const bool b); - double GetF(void); - void SetF(const double d); - CNlEqState *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNlEqStateShell::CNlEqStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CNlEqStateShell::CNlEqStateShell(CNlEqState &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNlEqStateShell::~CNlEqStateShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needf | -//+------------------------------------------------------------------+ -bool CNlEqStateShell::GetNeedF(void) - { -//--- return result - return(m_innerobj.m_needf); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needf | -//+------------------------------------------------------------------+ -void CNlEqStateShell::SetNeedF(const bool b) - { -//--- change value - m_innerobj.m_needf=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable needfij | -//+------------------------------------------------------------------+ -bool CNlEqStateShell::GetNeedFIJ(void) - { -//--- return result - return(m_innerobj.m_needfij); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable needfij | -//+------------------------------------------------------------------+ -void CNlEqStateShell::SetNeedFIJ(const bool b) - { -//--- change value - m_innerobj.m_needfij=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable xupdated | -//+------------------------------------------------------------------+ -bool CNlEqStateShell::GetXUpdated(void) - { -//--- return result - return(m_innerobj.m_xupdated); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable xupdated | -//+------------------------------------------------------------------+ -void CNlEqStateShell::SetXUpdated(const bool b) - { -//--- change value - m_innerobj.m_xupdated=b; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable f | -//+------------------------------------------------------------------+ -double CNlEqStateShell::GetF(void) - { -//--- return result - return(m_innerobj.m_f); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable f | -//+------------------------------------------------------------------+ -void CNlEqStateShell::SetF(const double d) - { -//--- change value - m_innerobj.m_f=d; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CNlEqState *CNlEqStateShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Auxiliary class for CNlEq | -//+------------------------------------------------------------------+ -class CNlEqReport - { -public: - //--- variables - int m_iterationscount; - int m_nfunc; - int m_njac; - int m_terminationtype; - //--- constructor, destructor - CNlEqReport(void); - ~CNlEqReport(void); - //--- copy - void Copy(CNlEqReport &obj); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNlEqReport::CNlEqReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNlEqReport::~CNlEqReport(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy | -//+------------------------------------------------------------------+ -void CNlEqReport::Copy(CNlEqReport &obj) - { -//--- copy variables - m_iterationscount=obj.m_iterationscount; - m_nfunc=obj.m_nfunc; - m_njac=obj.m_njac; - m_terminationtype=obj.m_terminationtype; - } -//+------------------------------------------------------------------+ -//| This class is a shell for class CNlEqReport | -//+------------------------------------------------------------------+ -class CNlEqReportShell - { -private: - CNlEqReport m_innerobj; -public: - //--- constructors, destructor - CNlEqReportShell(void); - CNlEqReportShell(CNlEqReport &obj); - ~CNlEqReportShell(void); - //--- methods - int GetIterationsCount(void); - void SetIterationsCount(const int i); - int GetNFunc(void); - void SetNFunc(const int i); - int GetNJac(void); - void SetNJac(const int i); - int GetTerminationType(void); - void SetTerminationType(const int i); - CNlEqReport *GetInnerObj(void); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNlEqReportShell::CNlEqReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Copy constructor | -//+------------------------------------------------------------------+ -CNlEqReportShell::CNlEqReportShell(CNlEqReport &obj) - { -//--- copy - m_innerobj.Copy(obj); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNlEqReportShell::~CNlEqReportShell(void) - { - - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable iterationscount | -//+------------------------------------------------------------------+ -int CNlEqReportShell::GetIterationsCount(void) - { -//--- return result - return(m_innerobj.m_iterationscount); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable iterationscount | -//+------------------------------------------------------------------+ -void CNlEqReportShell::SetIterationsCount(const int i) - { -//--- change value - m_innerobj.m_iterationscount=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable nfunc | -//+------------------------------------------------------------------+ -int CNlEqReportShell::GetNFunc(void) - { -//--- return result - return(m_innerobj.m_nfunc); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable nfunc | -//+------------------------------------------------------------------+ -void CNlEqReportShell::SetNFunc(const int i) - { -//--- change value - m_innerobj.m_nfunc=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable njac | -//+------------------------------------------------------------------+ -int CNlEqReportShell::GetNJac(void) - { -//--- return result - return(m_innerobj.m_njac); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable njac | -//+------------------------------------------------------------------+ -void CNlEqReportShell::SetNJac(const int i) - { -//--- change value - m_innerobj.m_njac=i; - } -//+------------------------------------------------------------------+ -//| Returns the value of the variable terminationtype | -//+------------------------------------------------------------------+ -int CNlEqReportShell::GetTerminationType(void) - { -//--- return result - return(m_innerobj.m_terminationtype); - } -//+------------------------------------------------------------------+ -//| Changing the value of the variable terminationtype | -//+------------------------------------------------------------------+ -void CNlEqReportShell::SetTerminationType(const int i) - { -//--- change value - m_innerobj.m_terminationtype=i; - } -//+------------------------------------------------------------------+ -//| Return object of class | -//+------------------------------------------------------------------+ -CNlEqReport *CNlEqReportShell::GetInnerObj(void) - { -//--- return result - return(GetPointer(m_innerobj)); - } -//+------------------------------------------------------------------+ -//| Solving systems of nonlinear equations | -//+------------------------------------------------------------------+ -class CNlEq - { -private: - //--- private methods - static void ClearRequestFields(CNlEqState &state); - static bool IncreaseLambda(double &lambdav,double &nu,const double lambdaup); - static void DecreaseLambda(double &lambdav,double &nu,const double lambdadown); - //--- auxiliary functions forNlEqiteration - static void Func_lbl_rcomm(CNlEqState &state,const int n,const int m,const int i,const bool b,const double lambdaup,const double lambdadown,const double lambdav,const double rho,const double mu,const double stepnorm); - static void Func_lbl_7(CNlEqState &state,const int n); - static bool Func_lbl_5(CNlEqState &state,double &lambdaup,double &lambdadown,double &lambdav,double &rho); - static bool Func_lbl_11(CNlEqState &state,const double stepnorm); - static int Func_lbl_10(CNlEqState &state,const int n,const int m,const int i,const bool b,const double lambdaup,const double lambdadown,const double lambdav,const double rho,const double mu,const double stepnorm); - static int Func_lbl_9(CNlEqState &state,int &n,int &m,int &i,bool &b,const double lambdaup,const double lambdadown,double &lambdav,const double rho,const double mu,double &stepnorm); -public: - //--- constant - static const int m_armijomaxfev; - //--- constructor, destructor - CNlEq(void); - ~CNlEq(void); - //--- public methods - static void NlEqCreateLM(const int n,const int m,double &x[],CNlEqState &state); - static void NlEqSetCond(CNlEqState &state,double epsf,const int maxits); - static void NlEqSetXRep(CNlEqState &state,const bool needxrep); - static void NlEqSetStpMax(CNlEqState &state,const double stpmax); - static void NlEqResults(CNlEqState &state,double &x[],CNlEqReport &rep); - static void NlEqResultsBuf(CNlEqState &state,double &x[],CNlEqReport &rep); - static void NlEqRestartFrom(CNlEqState &state,double &x[]); - static bool NlEqIteration(CNlEqState &state); - }; -//+------------------------------------------------------------------+ -//| Initialize constant | -//+------------------------------------------------------------------+ -const int CNlEq::m_armijomaxfev=20; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNlEq::CNlEq(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNlEq::~CNlEq(void) - { - - } -//+------------------------------------------------------------------+ -//| LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER | -//| DESCRIPTION: | -//| This algorithm solves system of nonlinear equations | -//| F[0](x[0], ..., x[n-1]) = 0 | -//| F[1](x[0], ..., x[n-1]) = 0 | -//| ... | -//| F[M-1](x[0], ..., x[n-1]) = 0 | -//| with M/N do not necessarily coincide. Algorithm converges | -//| quadratically under following conditions: | -//| * the solution set XS is nonempty | -//| * for some xs in XS there exist such neighbourhood N(xs) | -//| that: | -//| * vector function F(x) and its Jacobian J(x) are | -//| continuously differentiable on N | -//| * ||F(x)|| provides local error bound on N, i.e. there | -//| exists such c1, that ||F(x)||>c1*distance(x,XS) | -//| Note that these conditions are much more weaker than usual | -//| non-singularity conditions. For example, algorithm will converge | -//| for any affine function F (whether its Jacobian singular or not).| -//| REQUIREMENTS: | -//| Algorithm will request following information during its | -//| operation: | -//| * function vector F[] and Jacobian matrix at given point X | -//| * value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given| -//| point X | -//| USAGE: | -//| 1. User initializes algorithm state with NLEQCreateLM() call | -//| 2. User tunes solver parameters with NLEQSetCond(), | -//| NLEQSetStpMax() and other functions | -//| 3. User calls NLEQSolve() function which takes algorithm state | -//| and pointers (delegates, etc.) to callback functions which | -//| calculate merit function value and Jacobian. | -//| 4. User calls NLEQResults() to get solution | -//| 5. Optionally, user may call NLEQRestartFrom() to solve another | -//| problem with same parameters (N/M) but another starting point | -//| and/or another function vector. NLEQRestartFrom() allows to | -//| reuse already initialized structure. | -//| INPUT PARAMETERS: | -//| N - space dimension, N>1: | -//| * if provided, only leading N elements of X are | -//| used | -//| * if not provided, determined automatically from | -//| size of X | -//| M - system size | -//| X - starting point | -//| OUTPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NOTES: | -//| 1. you may tune stopping conditions with NLEQSetCond() function | -//| 2. if target function contains exp() or other fast growing | -//| functions, and optimization algorithm makes too large steps | -//| which leads to overflow, use NLEQSetStpMax() function to bound| -//| algorithm's steps. | -//| 3. this algorithm is a slightly modified implementation of the | -//| method described in 'Levenberg-Marquardt method for | -//| constrained nonlinear equations with strong local convergence | -//| properties' by Christian Kanzow Nobuo Yamashita and Masao | -//| Fukushima and further developed in 'On the convergence of a | -//| New Levenberg-Marquardt Method' by Jin-yan Fan and Ya-Xiang | -//| Yuan. | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqCreateLM(const int n,const int m,double &x[], - CNlEqState &state) - { -//--- check - if(!CAp::Assert(n>=1,__FUNCTION__+": N<1!")) - return; -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": M<1!")) - return; -//--- check - if(!CAp::Assert(CAp::Len(x)>=n,__FUNCTION__+": Length(X)=0 | -//| The subroutine finishes its work if on k+1-th | -//| iteration the condition ||F||<=EpsF is satisfied | -//| MaxIts - maximum number of iterations. If MaxIts=0, the | -//| number of iterations is unlimited. | -//| Passing EpsF=0 and MaxIts=0 simultaneously will lead to | -//| automatic stopping criterion selection (small EpsF). | -//| NOTES: | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqSetCond(CNlEqState &state,double epsf,const int maxits) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(epsf),__FUNCTION__+": EpsF is not finite number!")) - return; -//--- check - if(!CAp::Assert(epsf>=0.0,__FUNCTION__+": negative EpsF!")) - return; -//--- check - if(!CAp::Assert(maxits>=0,__FUNCTION__+": negative MaxIts!")) - return; -//--- check - if(epsf==0.0 && maxits==0) - epsf=1.0E-6; -//--- change values - state.m_epsf=epsf; - state.m_maxits=maxits; - } -//+------------------------------------------------------------------+ -//| This function turns on/off reporting. | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| NeedXRep- whether iteration reports are needed or not | -//| If NeedXRep is True, algorithm will call rep() callback function | -//| if it is provided to NLEQSolve(). | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqSetXRep(CNlEqState &state,const bool needxrep) - { -//--- change value - state.m_xrep=needxrep; - } -//+------------------------------------------------------------------+ -//| This function sets maximum step length | -//| INPUT PARAMETERS: | -//| State - structure which stores algorithm state | -//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if | -//| you don't want to limit step length. | -//| Use this subroutine when target function contains exp() or other | -//| fast growing functions, and algorithm makes too large steps which| -//| lead to overflow. This function allows us to reject steps that | -//| are too large (and therefore expose us to the possible overflow) | -//| without actually calculating function value at the x+stp*d. | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqSetStpMax(CNlEqState &state,const double stpmax) - { -//--- check - if(!CAp::Assert(CMath::IsFinite(stpmax),__FUNCTION__+": StpMax is not finite!")) - return; -//--- check - if(!CAp::Assert(stpmax>=0.0,__FUNCTION__+": StpMax<0!")) - return; -//--- change value - state.m_stpmax=stpmax; - } -//+------------------------------------------------------------------+ -//| NLEQ solver results | -//| INPUT PARAMETERS: | -//| State - algorithm state. | -//| OUTPUT PARAMETERS: | -//| X - array[0..N-1], solution | -//| Rep - optimization report: | -//| * Rep.TerminationType completetion code: | -//| * -4 ERROR: algorithm has converged to the| -//| stationary point Xf which is local | -//| minimum of f=F[0]^2+...+F[m-1]^2, | -//| but is not solution of nonlinear | -//| system. | -//| * 1 sqrt(f)<=EpsF. | -//| * 5 MaxIts steps was taken | -//| * 7 stopping conditions are too | -//| stringent, further improvement is | -//| impossible | -//| * Rep.IterationsCount contains iterations count | -//| * NFEV countains number of function calculations | -//| * ActiveConstraints contains number of active | -//| constraints | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqResults(CNlEqState &state,double &x[],CNlEqReport &rep) - { - ArrayResizeAL(x,0); -//--- function call - NlEqResultsBuf(state,x,rep); - } -//+------------------------------------------------------------------+ -//| NLEQ solver results | -//| Buffered implementation of NLEQResults(), which uses | -//| pre-allocated buffer to store X[]. If buffer size is too small, | -//| it resizes buffer. It is intended to be used in the inner cycles | -//| of performance critical algorithms where array reallocation | -//| penalty is too large to be ignored. | -//+------------------------------------------------------------------+ -static void CNlEq::NlEqResultsBuf(CNlEqState &state,double &x[],CNlEqReport &rep) - { -//--- create a variable - int i_=0; -//--- check - if(CAp::Len(x)=state.m_n,__FUNCTION__+": Length(X)lnmax) - return(false); -//--- check - if(lnnu+MathLog(2)>lnmax) - return(false); -//--- change values - lambdav=lambdav*lambdaup*nu; - nu=nu*2; -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Decreases lambda, but leaves it unchanged when there is danger of| -//| underflow. | -//+------------------------------------------------------------------+ -static void CNlEq::DecreaseLambda(double &lambdav,double &nu,const double lambdadown) - { -//--- initialization - nu=1; -//--- check - if(MathLog(lambdav)+MathLog(lambdadown)=0) - { - //--- initialization - n=state.m_rstate.ia[0]; - m=state.m_rstate.ia[1]; - i=state.m_rstate.ia[2]; - b=state.m_rstate.ba[0]; - lambdaup=state.m_rstate.ra[0]; - lambdadown=state.m_rstate.ra[1]; - lambdav=state.m_rstate.ra[2]; - rho=state.m_rstate.ra[3]; - mu=state.m_rstate.ra[4]; - stepnorm=state.m_rstate.ra[5]; - } - else - { - //--- initialization - n=-983; - m=-989; - i=-834; - b=false; - lambdaup=-287; - lambdadown=364; - lambdav=214; - rho=-338; - mu=-686; - stepnorm=912; - } -//--- check - if(state.m_rstate.stage==0) - { - //--- change values - state.m_needf=false; - state.m_repnfunc=state.m_repnfunc+1; - //--- copy - for(i_=0;i_<=n-1;i_++) - state.m_xbase[i_]=state.m_x[i_]; - //--- change values - state.m_fbase=state.m_f; - state.m_fprev=CMath::m_maxrealnumber; - //--- check - if(!state.m_xrep) - { - //--- check - if(!Func_lbl_5(state,lambdaup,lambdadown,lambdav,rho)) - return(false); - //--- function call - Func_lbl_7(state,n); - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(true); - } - //--- progress report - ClearRequestFields(state); - state.m_xupdated=true; - state.m_rstate.stage=1; - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==1) - { - //--- change value - state.m_xupdated=false; - //--- check - if(!Func_lbl_5(state,lambdaup,lambdadown,lambdav,rho)) - return(false); - //--- function call - Func_lbl_7(state,n); - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==2) - { - //--- change values - state.m_needfij=false; - state.m_repnfunc=state.m_repnfunc+1; - state.m_repnjac=state.m_repnjac+1; - //--- function call - CAblas::RMatrixMVect(n,m,state.m_j,0,0,1,state.m_fi,0,state.m_rightpart,0); - for(i_=0;i_<=n-1;i_++) - state.m_rightpart[i_]=-1*state.m_rightpart[i_]; - //--- Inner cycle: find good lambda - temp=Func_lbl_9(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- check - if(temp==-1) - return(false); - //--- check - if(temp==1) - return(true); - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(true); - } -//--- check - if(state.m_rstate.stage==3) - { - //--- change values - state.m_needf=false; - state.m_repnfunc=state.m_repnfunc+1; - //--- check - if(state.m_f=state.m_maxits && state.m_maxits>0) - state.m_repterminationtype=5; -//--- check - if(state.m_repterminationtype!=0) - return(false); -//--- return result - return(true); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for NlEqiteration. Is a product to get rid of | -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static int CNlEq::Func_lbl_10(CNlEqState &state,const int n,const int m, - const int i,const bool b,const double lambdaup, - const double lambdadown,const double lambdav, - const double rho,const double mu, - const double stepnorm) - { -//--- Accept step: -//--- * new position -//--- * new function value - state.m_fbase=state.m_f; - for(int i_=0;i_<=n-1;i_++) - state.m_xbase[i_]=state.m_xbase[i_]+stepnorm*state.m_candstep[i_]; - state.m_repiterationscount=state.m_repiterationscount+1; -//--- Report new iteration - if(!state.m_xrep) - { - //--- check - if(!Func_lbl_11(state,stepnorm)) - return(-1); - //--- Now,iteration is finally over - Func_lbl_7(state,n); - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(1); - } -//--- function call - ClearRequestFields(state); -//--- change values - state.m_xupdated=true; - state.m_f=state.m_fbase; -//--- copy - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_rstate.stage=4; -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Auxiliary function for NlEqiteration. Is a product to get rid of | -//| the operator unconditional jump goto. | -//+------------------------------------------------------------------+ -static int CNlEq::Func_lbl_9(CNlEqState &state,int &n,int &m,int &i,bool &b, - const double lambdaup,const double lambdadown, - double &lambdav,const double rho,const double mu, - double &stepnorm) - { -//--- Solve (J^T*J + (Lambda+Mu)*I)*y=J^T*F -//--- to get step d=-y where: -//--- * Mu=||F|| - is damping parameter for nonlinear system -//--- * Lambda - is additional Levenberg-Marquardt parameter -//--- for better convergence when far away from minimum - for(i=0;i<=n-1;i++) - state.m_candstep[i]=0; -//--- function call - CFbls::FblsSolveCGx(state.m_j,m,n,lambdav,state.m_rightpart,state.m_candstep,state.m_cgbuf); -//--- Normalize step (it must be no more than StpMax) - stepnorm=0; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_candstep[i]!=0.0) - { - stepnorm=1; - break; - } - } - CLinMin::LinMinNormalized(state.m_candstep,stepnorm,n); -//--- check - if(state.m_stpmax!=0.0) - stepnorm=MathMin(stepnorm,state.m_stpmax); -//--- Test new step - is it good enough? -//--- * if not,Lambda is increased and we try again. -//--- * if step is good,we decrease Lambda and move on. -//--- We can break this cycle on two occasions: -//--- * step is so small that x+step==x (in floating point arithmetics) -//--- * lambda is so large - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_x[i_]+stepnorm*state.m_candstep[i_]; - b=true; - for(i=0;i<=n-1;i++) - { - //--- check - if(state.m_x[i]!=state.m_xbase[i]) - { - b=false; - break; - } - } -//--- check - if(b) - { - //--- Step is too small,force zero step and break - stepnorm=0; - for(int i_=0;i_<=n-1;i_++) - state.m_x[i_]=state.m_xbase[i_]; - state.m_f=state.m_fbase; - //--- function call - int temp=Func_lbl_10(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- check - if(temp!=0) - return(temp); - //--- Saving state - Func_lbl_rcomm(state,n,m,i,b,lambdaup,lambdadown,lambdav,rho,mu,stepnorm); - //--- return result - return(1); - } -//--- function call - ClearRequestFields(state); -//--- change values - state.m_needf=true; - state.m_rstate.stage=3; -//--- return result - return(0); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/specialfunctions.mqh b/Include/Math/Alglib/specialfunctions.mqh deleted file mode 100644 index 53e400a..0000000 --- a/Include/Math/Alglib/specialfunctions.mqh +++ /dev/null @@ -1,6599 +0,0 @@ -//+------------------------------------------------------------------+ -//| specialfunctions.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "ap.mqh" -#include "alglibinternal.mqh" -//+------------------------------------------------------------------+ -//| Gamma function | -//+------------------------------------------------------------------+ -class CGammaFunc - { -private: - static double GammaStirlFunc(double x); - -public: - CGammaFunc(void); - ~CGammaFunc(void); - static double GammaFunc(double x); - static double LnGamma(double x,double &sgngam); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CGammaFunc::CGammaFunc(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CGammaFunc::~CGammaFunc(void) - { - - } -//+------------------------------------------------------------------+ -//| Stirling function | -//+------------------------------------------------------------------+ -static double CGammaFunc::GammaStirlFunc(double x) - { -//--- create variables - double y; - double w; - double v; - double stir; -//--- initialization - w=1/x; - stir=7.87311395793093628397E-4; - stir=-2.29549961613378126380E-4+w*stir; - stir=-2.68132617805781232825E-3+w*stir; - stir=3.47222221605458667310E-3+w*stir; - stir=8.33333333333482257126E-2+w*stir; - w=1+w*stir; - y=MathExp(x); -//--- check - if(x>143.01608) - { - v=MathPow(x,0.5*x-0.25); - y=v*(v/y); - } - else - y=MathPow(x,x-0.5)/y; -//--- return result - return(2.50662827463100050242*y*w); - } -//+------------------------------------------------------------------+ -//| Gamma function | -//| Input parameters: | -//| X - argument | -//| Domain: | -//| 0 < X < 171.6 | -//| -170 < X < 0, X is not an integer. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -170,-33 20000 2.3e-15 3.3e-16 | -//| IEEE -33, 33 20000 9.4e-16 2.2e-16 | -//| IEEE 33, 171.6 20000 2.3e-15 3.2e-16 | -//+------------------------------------------------------------------+ -static double CGammaFunc::GammaFunc(double x) - { -//--- create variables - double p; - double pp; - double q=MathAbs(x); - double qq; - double z; - int i; - double sgngam=1; -//--- check - if(q>33.0) - { - //--- check - if(x<0.0) - { - p=(int)MathFloor(q); - i=(int)MathRound(p); - //--- check - if(i%2==0) - sgngam=-1; - z=q-p; - //--- check - if(z>0.5) - { - p++; - z=q-p; - } - //--- calculation z - z=q*MathSin(M_PI*z); - z=MathAbs(z); - z=M_PI/(z*GammaStirlFunc(q)); - } - else - z=GammaStirlFunc(x); - //--- return result - return(sgngam*z); - } -//--- q<=33 - z=1; - while(x>=3) - { - x--; - z*=x; - } -//--- x<0 - while(x<0) - { - //--- check - if(x>-0.000000001) - return(z/((1+0.5772156649015329*x)*x)); - z/=x; - x++; - } -//--- 00.5) - { - p++; - z=p-q; - } - z=q*MathSin(M_PI*z); - //--- return result - return(logpi-MathLog(z)-w); - } -//--- x>=-34 - if(x<13) - { - z=1; - p=0; - u=x; - //--- cycle - while(u>=3) - { - p--; - u=x+p; - z*=u; - } - //--- cycle - while(u<2) - { - z/=u; - p++; - u=x+p; - } - //--- check - if(z<0) - { - sgngam=-1; - z=-z; - } - else - sgngam=1; - //--- check - if(u==2) - return(MathLog(z)); - //--- calculation - p-=2; - x+=p; - b=-1378.25152569120859100; - b=-38801.6315134637840924+x*b; - b=-331612.992738871184744+x*b; - b=-1162370.97492762307383+x*b; - b=-1721737.00820839662146+x*b; - b=-853555.664245765465627+x*b; - c=1; - c=-351.815701436523470549+x*c; - c=-17064.2106651881159223+x*c; - c=-220528.590553854454839+x*c; - c=-1139334.44367982507207+x*c; - c=-2532523.07177582951285+x*c; - c=-2018891.41433532773231+x*c; - p=x*b/c; - //--- return result - return(MathLog(z)+p); - } -//--- x>=13 - q=(x-0.5)*MathLog(x)-x+ls2pi; -//--- check - if(x>100000000) - return(q); -//--- change value - p=1/(x*x); -//--- check - if(x>=1000.0) - q+=((7.9365079365079365079365*0.0001*p-2.7777777777777777777778*0.001)*p+0.0833333333333333333333)/x; - else - { - a=8.11614167470508450300*0.0001; - a=-(5.95061904284301438324*0.0001)+p*a; - a=7.93650340457716943945*0.0001+p*a; - a=-(2.77777777730099687205*0.001)+p*a; - a=8.33333333333331927722*0.01+p*a; - q+=a/x; - } -//--- return result - return(q); - } -//+------------------------------------------------------------------+ -//| Normal distribution | -//+------------------------------------------------------------------+ -class CNormalDistr - { -public: - //--- constructor, destructor - CNormalDistr(void); - ~CNormalDistr(void); - //--- methods - static double ErrorFunction(double x); - static double ErrorFunctionC(double x); - static double NormalDistribution(const double x); - static double InvErF(const double e); - static double InvNormalDistribution(double y0); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNormalDistr::CNormalDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNormalDistr::~CNormalDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Error function | -//| The integral is | -//| x | -//| - | -//| 2 | | 2 | -//| erf(x) = -------- | exp( - t ) dt. | -//| sqrt(pi) | | | -//| - | -//| 0 | -//| For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise | -//| erf(x) = 1 - erfc(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 3.7e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CNormalDistr::ErrorFunction(double x) - { -//--- create variables - double xsq=0; - double s=0; - double p=0; - double q=0; -//--- initialization - s=MathSign(x); -//--- change value - x=MathAbs(x); -//--- check - if(x<0.5) - { - //--- calculation - xsq=x*x; - p=0.007547728033418631287834; - p=0.288805137207594084924010+xsq*p; - p=14.3383842191748205576712+xsq*p; - p=38.0140318123903008244444+xsq*p; - p=3017.82788536507577809226+xsq*p; - p=7404.07142710151470082064+xsq*p; - p=80437.3630960840172832162+xsq*p; - q=0.0; - q=1.00000000000000000000000+xsq*q; - q=38.0190713951939403753468+xsq*q; - q=658.070155459240506326937+xsq*q; - q=6379.60017324428279487120+xsq*q; - q=34216.5257924628539769006+xsq*q; - q=80437.3630960840172826266+xsq*q; - //--- return result - return(s*1.1283791670955125738961589031*x*p/q); - } -//--- check - if(x>=10) - return(s); -//--- return result - return(s*(1-ErrorFunctionC(x))); - } -//+------------------------------------------------------------------+ -//| Complementary error function | -//| 1 - erf(x) = | -//| inf. | -//| - | -//| 2 | | 2 | -//| erfc(x) = -------- | exp( - t ) dt | -//| sqrt(pi) | | | -//| - | -//| x | -//| For small x, erfc(x) = 1 - erf(x); otherwise rational | -//| approximations are computed. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,26.6417 30000 5.7e-14 1.5e-14 | -//+------------------------------------------------------------------+ -static double CNormalDistr::ErrorFunctionC(double x) - { -//--- create variables - double p=0; - double q=0; -//--- check - if(x<0.0) - return(2-ErrorFunctionC(-x)); -//--- check - if(x<0.5) - return(1.0-ErrorFunction(x)); -//--- check - if(x>=10) - return(0); -//--- calculation - p=0.0; - p=0.5641877825507397413087057563+x*p; - p=9.675807882987265400604202961+x*p; - p=77.08161730368428609781633646+x*p; - p=368.5196154710010637133875746+x*p; - p=1143.262070703886173606073338+x*p; - p=2320.439590251635247384768711+x*p; - p=2898.0293292167655611275846+x*p; - p=1826.3348842295112592168999+x*p; - q=1.0; - q=17.14980943627607849376131193+x*q; - q=137.1255960500622202878443578+x*q; - q=661.7361207107653469211984771+x*q; - q=2094.384367789539593790281779+x*q; - q=4429.612803883682726711528526+x*q; - q=6089.5424232724435504633068+x*q; - q=4958.82756472114071495438422+x*q; - q=1826.3348842295112595576438+x*q; -//--- return result - return(MathExp(-CMath::Sqr(x))*p/q); - } -//+------------------------------------------------------------------+ -//| Normal distribution function | -//| Returns the area under the Gaussian probability density | -//| function, integrated from minus infinity to x: | -//| x | -//| - | -//| 1 | | 2 | -//| ndtr(x) = --------- | exp( - t /2 ) dt | -//| sqrt(2pi) | | | -//| - | -//| -inf. | -//| = ( 1 + erf(z) ) / 2 | -//| = erfc(z) / 2 | -//| where z = x/sqrt(2). Computation is via the functions | -//| erf and erfc. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -13,0 30000 3.4e-14 6.7e-15 | -//+------------------------------------------------------------------+ -static double CNormalDistr::NormalDistribution(const double x) - { -//--- return result - return(0.5*(ErrorFunction(x/1.41421356237309504880)+1)); - } -//+------------------------------------------------------------------+ -//| Inverse of the error function | -//+------------------------------------------------------------------+ -static double CNormalDistr::InvErF(const double e) - { -//--- return result - return(InvNormalDistribution(0.5*(e+1))/MathSqrt(2)); - } -//+------------------------------------------------------------------+ -//| Inverse of Normal distribution function | -//| Returns the argument, x, for which the area under the | -//| Gaussian probability density function (integrated from | -//| minus infinity to x) is equal to y. | -//| For small arguments 0 < y < exp(-2), the program computes | -//| z = sqrt( -2.0 * log(y) ); then the approximation is | -//| x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). | -//| There are two rational functions P/Q, one for 0 < y < exp(-32) | -//| and the other for y up to exp(-2). For larger arguments, | -//| w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0.125, 1 20000 7.2e-16 1.3e-16 | -//| IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 | -//+------------------------------------------------------------------+ -static double CNormalDistr::InvNormalDistribution(double y0) - { -//--- check - if(y0<=0) - return(-CMath::m_maxrealnumber); -//--- check - if(y0>=1) - return(CMath::m_maxrealnumber); -//--- create variables - double expm2=0.13533528323661269189; - double s2pi=2.50662827463100050242; - double x; - double y=y0; - double z; - double y2; - double x0; - double x1; - int code=1; - double p0; - double q0; - double p1; - double q1; - double p2; - double q2; -//--- check - if(y>1.0-expm2) - { - y=1.0-y; - code=0; - } -//--- check - if(y>expm2) - { - y-=0.5; - y2=y*y; - p0=-59.9633501014107895267; - p0=98.0010754185999661536+y2*p0; - p0=-56.6762857469070293439+y2*p0; - p0=13.9312609387279679503+y2*p0; - p0=-1.23916583867381258016+y2*p0; - q0=1; - q0=1.95448858338141759834+y2*q0; - q0=4.67627912898881538453+y2*q0; - q0=86.3602421390890590575+y2*q0; - q0=-225.462687854119370527+y2*q0; - q0=200.260212380060660359+y2*q0; - q0=-82.0372256168333339912+y2*q0; - q0=15.9056225126211695515+y2*q0; - q0=-1.18331621121330003142+y2*q0; - x=y+y*y2*p0/q0; - x*=s2pi; - //--- return result - return(x); - } -//--- calculation - x=MathSqrt(-(2.0*MathLog(y))); - x0=x-MathLog(x)/x; - z=1.0/x; -//--- check - if(x<8.0) - { - p1=4.05544892305962419923; - p1=31.5251094599893866154+z*p1; - p1=57.1628192246421288162+z*p1; - p1=44.0805073893200834700+z*p1; - p1=14.6849561928858024014+z*p1; - p1=2.18663306850790267539+z*p1; - p1=-(1.40256079171354495875*0.1)+z*p1; - p1=-(3.50424626827848203418*0.01)+z*p1; - p1=-(8.57456785154685413611*0.0001)+z*p1; - q1=1; - q1=15.7799883256466749731+z*q1; - q1=45.3907635128879210584+z*q1; - q1=41.3172038254672030440+z*q1; - q1=15.0425385692907503408+z*q1; - q1=2.50464946208309415979+z*q1; - q1=-(1.42182922854787788574*0.1)+z*q1; - q1=-(3.80806407691578277194*0.01)+z*q1; - q1=-(9.33259480895457427372*0.0001)+z*q1; - x1=z*p1/q1; - } - else - { - p2=3.23774891776946035970; - p2=6.91522889068984211695+z*p2; - p2=3.93881025292474443415+z*p2; - p2=1.33303460815807542389+z*p2; - p2=2.01485389549179081538*0.1+z*p2; - p2=1.23716634817820021358*0.01+z*p2; - p2=3.01581553508235416007*0.0001+z*p2; - p2=2.65806974686737550832*0.000001+z*p2; - p2=6.23974539184983293730*0.000000001+z*p2; - q2=1; - q2=6.02427039364742014255+z*q2; - q2=3.67983563856160859403+z*q2; - q2=1.37702099489081330271+z*q2; - q2=2.16236993594496635890*0.1+z*q2; - q2=1.34204006088543189037*0.01+z*q2; - q2=3.28014464682127739104*0.0001+z*q2; - q2=2.89247864745380683936*0.000001+z*q2; - q2=6.79019408009981274425*0.000000001+z*q2; - x1=z*p2/q2; - } - x=x0-x1; -//--- check - if(code!=0) - x=-x; -//--- return result - return(x); - } -//+------------------------------------------------------------------+ -//| Incomplete gamma function | -//+------------------------------------------------------------------+ -class CIncGammaF - { -public: - //--- constructor, destructor - CIncGammaF(void); - ~CIncGammaF(void); - //--- methods - static double IncompleteGamma(const double a,const double x); - static double IncompleteGammaC(const double a,const double x); - static double InvIncompleteGammaC(const double a,const double y0); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIncGammaF::CIncGammaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIncGammaF::~CIncGammaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Incomplete gamma integral | -//| The function is defined by | -//| x | -//| - | -//| 1 | | -t a-1 | -//| igam(a,x) = ----- | e t dt. | -//| - | | | -//| | (a) - | -//| 0 | -//| In this implementation both arguments must be positive. | -//| The integral is evaluated by either a power series or | -//| continued fraction expansion, depending on the relative | -//| values of a and x. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 200000 3.6e-14 2.9e-15 | -//| IEEE 0,100 300000 9.9e-14 1.5e-14 | -//+------------------------------------------------------------------+ -static double CIncGammaF::IncompleteGamma(const double a,const double x) - { -//--- check - if(x<=0 || a<=0) - return(0); -//--- check - if(x>1 && x>a) - return(1-IncompleteGammaC(a,x)); -//--- create variables - double igammaepsilon=0.000000000000001; - double ans; - double ax; - double c; - double r; - double tmp=0; -//--- change value - ax=a*MathLog(x)-x-CGammaFunc::LnGamma(a,tmp); -//--- check - if(ax<-709.78271289338399) - return(0); -//--- change values - ax=MathExp(ax); - r=a; - c=1; - ans=1; -//--- cycle - do - { - r++; - c*=x/r; - ans+=c; - } - while(c/ans>igammaepsilon); -//--- return result - return(ans*ax/a); - } -//+------------------------------------------------------------------+ -//| Complemented incomplete gamma integral | -//| The function is defined by | -//| igamc(a,x) = 1 - igam(a,x) | -//| inf. | -//| - | -//| 1 | | -t a-1 | -//| = ----- | e t dt. | -//| - | | | -//| | (a) - | -//| x | -//| In this implementation both arguments must be positive. | -//| The integral is evaluated by either a power series or | -//| continued fraction expansion, depending on the relative | -//| values of a and x. | -//| ACCURACY: | -//| Tested at random a, x. | -//| a x Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15| -//| IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15| -//+------------------------------------------------------------------+ -static double CIncGammaF::IncompleteGammaC(const double a,const double x) - { -//--- check - if(x<=0 || a<=0) - return(1); -//--- check - if(x<1 || xigammabignumber) - { - pkm2=pkm2*igammabignumberinv; - pkm1=pkm1*igammabignumberinv; - qkm2=qkm2*igammabignumberinv; - qkm1=qkm1*igammabignumberinv; - } - } - while(t>igammaepsilon); -//--- return result - return(ans*ax); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented imcomplete gamma integral | -//| Given p, the function finds x such that | -//| igamc( a, x ) = p. | -//| Starting with the approximate value | -//| 3 | -//| x = a t | -//| where | -//| t = 1 - d - ndtri(p) sqrt(d) | -//| and | -//| d = 1/9a, | -//| the routine performs up to 10 Newton iterations to find the | -//| root of igamc(a,x) - p = 0. | -//| ACCURACY: | -//| Tested at random a, p in the intervals indicated. | -//| a p Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15| -//| IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15| -//| IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14| -//+------------------------------------------------------------------+ -static double CIncGammaF::InvIncompleteGammaC(const double a,const double y0) - { -//--- create variables - double igammaepsilon=0; - double iinvgammabignumber=0; - double x0=0; - double x1=0; - double x=0; - double yl=0; - double yh=0; - double y=0; - double d=0; - double lgm=0; - double dithresh=0; - int i=0; - int dir=0; - double tmp=0; -//--- initialization - igammaepsilon=0.000000000000001; - iinvgammabignumber=4503599627370496.0; - x0=iinvgammabignumber; - yl=0; - x1=0; - yh=1; - dithresh=5*igammaepsilon; - d=1/(9*a); - y=1-d-CNormalDistr::InvNormalDistribution(y0)*MathSqrt(d); - x=a*y*y*y; - lgm=CGammaFunc::LnGamma(a,tmp); - i=0; -//--- cycle - while(i<10) - { - //--- check - if(x>x0 || xyh) - { - d=0.0625; - break; - } - //--- check - if(y=y0) - { - x1=x; - yh=y; - //--- check - if(dir<0) - { - dir=0; - d=0.5; - } - else - { - //--- check - if(dir>1) - d=0.5*d+0.5; - else - d=(y0-yl)/(yh-yl); - } - dir=dir+1; - } - else - { - x0=x; - yl=y; - //--- check - if(dir>0) - { - dir=0; - d=0.5; - } - else - { - //--- check - if(dir<-1) - d=0.5*d; - else - d=(y0-yl)/(yh-yl); - } - dir=dir-1; - } - i=i+1; - } -//--- return result - return(x); - } -//+------------------------------------------------------------------+ -//| Airy function | -//+------------------------------------------------------------------+ -class CAiryF - { -public: - //--- constructor, destructor - CAiryF(void); - ~CAiryF(void); - //--- method - static void Airy(const double x,double &ai,double &aip,double &bi,double &bip); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CAiryF::CAiryF(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CAiryF::~CAiryF(void) - { - - } -//+------------------------------------------------------------------+ -//| Airy function | -//| Solution of the differential equation | -//| y"(x) = xy. | -//| The function returns the two independent solutions Ai, Bi | -//| and their first derivatives Ai'(x), Bi'(x). | -//| Evaluation is by power series summation for small x, | -//| by rational minimax approximations for large x. | -//| ACCURACY: | -//| Error criterion is absolute when function <= 1, relative | -//| when function > 1, except * denotes relative error criterion. | -//| For large negative x, the absolute error increases as x^1.5. | -//| For large positive x, the relative error increases as x^1.5. | -//| Arithmetic domain function # trials peak rms | -//| IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 | -//| IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15*| -//| IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 | -//| IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15*| -//| IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 | -//| IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 | -//+------------------------------------------------------------------+ -static void CAiryF::Airy(const double x,double &ai,double &aip,double &bi, - double &bip) - { -//--- create variables - double z=0; - double zz=0; - double t=0; - double f=0; - double g=0; - double uf=0; - double ug=0; - double k=0; - double zeta=0; - double theta=0; - int domflg=0; - double c1=0; - double c2=0; - double sqrt3=0; - double sqpii=0; - double afn=0; - double afd=0; - double agn=0; - double agd=0; - double apfn=0; - double apfd=0; - double apgn=0; - double apgd=0; - double an=0; - double ad=0; - double apn=0; - double apd=0; - double bn16=0; - double bd16=0; - double bppn=0; - double bppd=0; -//--- initialization - ai=0; - aip=0; - bi=0; - bip=0; - sqpii=5.64189583547756286948E-1; - c1=0.35502805388781723926; - c2=0.258819403792806798405; - sqrt3=1.732050807568877293527; - domflg=0; -//--- check - if(x>25.77) - { - //--- initialization - ai=0; - aip=0; - bi=CMath::m_maxrealnumber; - bip=CMath::m_maxrealnumber; - //--- exit the function - return; - } -//--- check - if(x<-2.09) - { - //--- calculation - domflg=15; - t=MathSqrt(-x); - zeta=-(2.0*x*t/3.0); - t=MathSqrt(t); - k=sqpii/t; - z=1.0/zeta; - zz=z*z; - //--- calculation - afn=-1.31696323418331795333E-1; - afn=afn*zz-6.26456544431912369773E-1; - afn=afn*zz-6.93158036036933542233E-1; - afn=afn*zz-2.79779981545119124951E-1; - afn=afn*zz-4.91900132609500318020E-2; - afn=afn*zz-4.06265923594885404393E-3; - afn=afn*zz-1.59276496239262096340E-4; - afn=afn*zz-2.77649108155232920844E-6; - afn=afn*zz-1.67787698489114633780E-8; - //--- calculation - afd=1.00000000000000000000E0; - afd=afd*zz+1.33560420706553243746E1; - afd=afd*zz+3.26825032795224613948E1; - afd=afd*zz+2.67367040941499554804E1; - afd=afd*zz+9.18707402907259625840E0; - afd=afd*zz+1.47529146771666414581E0; - afd=afd*zz+1.15687173795188044134E-1; - afd=afd*zz+4.40291641615211203805E-3; - afd=afd*zz+7.54720348287414296618E-5; - afd=afd*zz+4.51850092970580378464E-7; - uf=1.0+zz*afn/afd; - //--- calculation - agn=1.97339932091685679179E-2; - agn=agn*zz+3.91103029615688277255E-1; - agn=agn*zz+1.06579897599595591108E0; - agn=agn*zz+9.39169229816650230044E-1; - agn=agn*zz+3.51465656105547619242E-1; - agn=agn*zz+6.33888919628925490927E-2; - agn=agn*zz+5.85804113048388458567E-3; - agn=agn*zz+2.82851600836737019778E-4; - agn=agn*zz+6.98793669997260967291E-6; - agn=agn*zz+8.11789239554389293311E-8; - agn=agn*zz+3.41551784765923618484E-10; - //--- calculation - agd=1.00000000000000000000E0; - agd=agd*zz+9.30892908077441974853E0; - agd=agd*zz+1.98352928718312140417E1; - agd=agd*zz+1.55646628932864612953E1; - agd=agd*zz+5.47686069422975497931E0; - agd=agd*zz+9.54293611618961883998E-1; - agd=agd*zz+8.64580826352392193095E-2; - agd=agd*zz+4.12656523824222607191E-3; - agd=agd*zz+1.01259085116509135510E-4; - agd=agd*zz+1.17166733214413521882E-6; - agd=agd*zz+4.91834570062930015649E-9; - //--- calculation - ug=z*agn/agd; - theta=zeta+0.25*M_PI; - f=MathSin(theta); - g=MathCos(theta); - ai=k*(f*uf-g*ug); - bi=k*(g*uf+f*ug); - apfn=1.85365624022535566142E-1; - apfn=apfn*zz+8.86712188052584095637E-1; - apfn=apfn*zz+9.87391981747398547272E-1; - apfn=apfn*zz+4.01241082318003734092E-1; - apfn=apfn*zz+7.10304926289631174579E-2; - apfn=apfn*zz+5.90618657995661810071E-3; - apfn=apfn*zz+2.33051409401776799569E-4; - apfn=apfn*zz+4.08718778289035454598E-6; - apfn=apfn*zz+2.48379932900442457853E-8; - //--- calculation - apfd=1.00000000000000000000E0; - apfd=apfd*zz+1.47345854687502542552E1; - apfd=apfd*zz+3.75423933435489594466E1; - apfd=apfd*zz+3.14657751203046424330E1; - apfd=apfd*zz+1.09969125207298778536E1; - apfd=apfd*zz+1.78885054766999417817E0; - apfd=apfd*zz+1.41733275753662636873E-1; - apfd=apfd*zz+5.44066067017226003627E-3; - apfd=apfd*zz+9.39421290654511171663E-5; - apfd=apfd*zz+5.65978713036027009243E-7; - uf=1.0+zz*apfn/apfd; - //--- calculation - apgn=-3.55615429033082288335E-2; - apgn=apgn*zz-6.37311518129435504426E-1; - apgn=apgn*zz-1.70856738884312371053E0; - apgn=apgn*zz-1.50221872117316635393E0; - apgn=apgn*zz-5.63606665822102676611E-1; - apgn=apgn*zz-1.02101031120216891789E-1; - apgn=apgn*zz-9.48396695961445269093E-3; - apgn=apgn*zz-4.60325307486780994357E-4; - apgn=apgn*zz-1.14300836484517375919E-5; - apgn=apgn*zz-1.33415518685547420648E-7; - apgn=apgn*zz-5.63803833958893494476E-10; - //--- calculation - apgd=1.00000000000000000000E0; - apgd=apgd*zz+9.85865801696130355144E0; - apgd=apgd*zz+2.16401867356585941885E1; - apgd=apgd*zz+1.73130776389749389525E1; - apgd=apgd*zz+6.17872175280828766327E0; - apgd=apgd*zz+1.08848694396321495475E0; - apgd=apgd*zz+9.95005543440888479402E-2; - apgd=apgd*zz+4.78468199683886610842E-3; - apgd=apgd*zz+1.18159633322838625562E-4; - apgd=apgd*zz+1.37480673554219441465E-6; - apgd=apgd*zz+5.79912514929147598821E-9; - ug=z*apgn/apgd; - k=sqpii*t; - aip=-(k*(g*uf+f*ug)); - bip=k*(f*uf-g*ug); - //--- exit the function - return; - } -//--- check - if(x>=(double)(2.09)) - { - domflg=5; - t=MathSqrt(x); - zeta=2.0*x*t/3.0; - g=MathExp(zeta); - t=MathSqrt(t); - k=2.0*t*g; - z=1.0/zeta; - //--- calculation - an=3.46538101525629032477E-1; - an=an*z+1.20075952739645805542E1; - an=an*z+7.62796053615234516538E1; - an=an*z+1.68089224934630576269E2; - an=an*z+1.59756391350164413639E2; - an=an*z+7.05360906840444183113E1; - an=an*z+1.40264691163389668864E1; - an=an*z+9.99999999999999995305E-1; - ad=5.67594532638770212846E-1; - ad=ad*z+1.47562562584847203173E1; - ad=ad*z+8.45138970141474626562E1; - ad=ad*z+1.77318088145400459522E2; - ad=ad*z+1.64234692871529701831E2; - ad=ad*z+7.14778400825575695274E1; - ad=ad*z+1.40959135607834029598E1; - ad=ad*z+1.00000000000000000470E0; - //--- calculation - f=an/ad; - ai=sqpii*f/k; - k=-(0.5*sqpii*t/g); - apn=6.13759184814035759225E-1; - apn=apn*z+1.47454670787755323881E1; - apn=apn*z+8.20584123476060982430E1; - apn=apn*z+1.71184781360976385540E2; - apn=apn*z+1.59317847137141783523E2; - apn=apn*z+6.99778599330103016170E1; - apn=apn*z+1.39470856980481566958E1; - apn=apn*z+1.00000000000000000550E0; - apd=3.34203677749736953049E-1; - apd=apd*z+1.11810297306158156705E1; - apd=apd*z+7.11727352147859965283E1; - apd=apd*z+1.58778084372838313640E2; - apd=apd*z+1.53206427475809220834E2; - apd=apd*z+6.86752304592780337944E1; - apd=apd*z+1.38498634758259442477E1; - apd=apd*z+9.99999999999999994502E-1; - f=apn/apd; - aip=f*k; - //--- check - if(x>(double)(8.3203353)) - { - //--- calculation - bn16=-2.53240795869364152689E-1; - bn16=bn16*z+5.75285167332467384228E-1; - bn16=bn16*z-3.29907036873225371650E-1; - bn16=bn16*z+6.44404068948199951727E-2; - bn16=bn16*z-3.82519546641336734394E-3; - bd16=1.00000000000000000000E0; - bd16=bd16*z-7.15685095054035237902E0; - bd16=bd16*z+1.06039580715664694291E1; - bd16=bd16*z-5.23246636471251500874E0; - bd16=bd16*z+9.57395864378383833152E-1; - bd16=bd16*z-5.50828147163549611107E-2; - //--- calculation - f=z*bn16/bd16; - k=sqpii*g; - bi=k*(1.0+f)/t; - bppn=4.65461162774651610328E-1; - bppn=bppn*z-1.08992173800493920734E0; - bppn=bppn*z+6.38800117371827987759E-1; - bppn=bppn*z-1.26844349553102907034E-1; - bppn=bppn*z+7.62487844342109852105E-3; - bppd=1.00000000000000000000E0; - bppd=bppd*z-8.70622787633159124240E0; - bppd=bppd*z+1.38993162704553213172E1; - bppd=bppd*z-7.14116144616431159572E0; - bppd=bppd*z+1.34008595960680518666E0; - bppd=bppd*z-7.84273211323341930448E-2; - f=z*bppn/bppd; - bip=k*t*(1.0+f); - //--- exit the function - return; - } - } -//--- change values - f=1.0; - g=x; - t=1.0; - uf=1.0; - ug=x; - k=1.0; - z=x*x*x; -//--- cycle - while(t>CMath::m_machineepsilon) - { - //--- calculation - uf=uf*z; - k=k+1.0; - uf=uf/k; - ug=ug*z; - k=k+1.0; - ug=ug/k; - uf=uf/k; - f=f+uf; - k=k+1.0; - ug=ug/k; - g=g+ug; - t=MathAbs(uf/f); - } -//--- change values - uf=c1*f; - ug=c2*g; -//--- check - if(domflg%2==0) - ai=uf-ug; -//--- check - if(domflg/2%2==0) - bi=sqrt3*(uf+ug); -//--- change values - k=4.0; - uf=x*x/2.0; - ug=z/3.0; - f=uf; - g=1.0+ug; - uf=uf/3.0; - t=1.0; -//--- cycle - while(t>CMath::m_machineepsilon) - { - //--- calculation - uf=uf*z; - ug=ug/k; - k=k+1.0; - ug=ug*z; - uf=uf/k; - f=f+uf; - k=k+1.0; - ug=ug/k; - uf=uf/k; - g=g+ug; - k=k+1.0; - t=MathAbs(ug/g); - } -//--- change values - uf=c1*f; - ug=c2*g; -//--- check - if(domflg/4%2==0) - aip=uf-ug; -//--- check - if(domflg/8%2==0) - bip=sqrt3*(uf+ug); - } -//+------------------------------------------------------------------+ -//| Bessel function | -//+------------------------------------------------------------------+ -class CBessel - { -private: - //--- private methods - static void BesselMFirstCheb(const double c,double &b0,double &b1,double &b2); - static void BesselMNextCheb(const double x,const double c,double &b0,double &b1,double &b2); - static void BesselM1FirstCheb(const double c,double &b0,double &b1,double &b2); - static void BesselM1NextCheb(const double x,const double c,double &b0,double &b1,double &b2); - static void BesselAsympt0(const double x,double &pzero,double &qzero); - static void BesselAsympt1(const double x,double &pzero,double &qzero); -public: - //--- constructor, destructor - CBessel(void); - ~CBessel(void); - //--- public methods - static double BesselJ0(double x); - static double BesselJ1(double x); - static double BesselJN(int n,double x); - static double BesselY0(double x); - static double BesselY1(double x); - static double BesselYN(int n,double x); - static double BesselI0(double x); - static double BesselI1(double x); - static double BesselK0(double x); - static double BesselK1(double x); - static double BesselKN(int nn,double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CBessel::CBessel(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBessel::~CBessel(void) - { - - } -//+------------------------------------------------------------------+ -//| Bessel function of order zero | -//| Returns Bessel function of order zero of the argument. | -//| The domain is divided into the intervals [0, 5] and | -//| (5, infinity). In the first interval the following rational | -//| approximation is used: | -//| 2 2 | -//| (w - r ) (w - r ) P (w) / Q (w) | -//| 1 2 3 8 | -//| 2 | -//| where w = x and the two r's are zeros of the function. | -//| In the second interval, the Hankel asymptotic expansion | -//| is employed with two rational functions of degree 6/6 | -//| and 7/7. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 60000 4.2e-16 1.1e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselJ0(double x) - { -//--- create variables - double xsq=0; - double nn=0; - double pzero=0; - double qzero=0; - double p1=0; - double q1=0; -//--- check - if(x<0.0) - x=-x; -//--- check - if(x>8.0) - { - //--- function call - BesselAsympt0(x,pzero,qzero); - nn=x-M_PI/4; - //--- return result - return(MathSqrt(2/M_PI/x)*(pzero*MathCos(nn)-qzero*MathSin(nn))); - } -//--- calculation - xsq=CMath::Sqr(x); - p1=26857.86856980014981415848441; - p1=-40504123.71833132706360663322+xsq*p1; - p1=25071582855.36881945555156435+xsq*p1; - p1=-8085222034853.793871199468171+xsq*p1; - p1=1434354939140344.111664316553+xsq*p1; - p1=-136762035308817138.6865416609+xsq*p1; - p1=6382059341072356562.289432465+xsq*p1; - p1=-117915762910761053603.8440800+xsq*p1; - p1=493378725179413356181.6813446+xsq*p1; - q1=1.0; - q1=1363.063652328970604442810507+xsq*q1; - q1=1114636.098462985378182402543+xsq*q1; - q1=669998767.2982239671814028660+xsq*q1; - q1=312304311494.1213172572469442+xsq*q1; - q1=112775673967979.8507056031594+xsq*q1; - q1=30246356167094626.98627330784+xsq*q1; - q1=5428918384092285160.200195092+xsq*q1; - q1=493378725179413356211.3278438+xsq*q1; -//--- return result - return(p1/q1); - } -//+------------------------------------------------------------------+ -//| Bessel function of order one | -//| Returns Bessel function of order one of the argument. | -//| The domain is divided into the intervals [0, 8] and | -//| (8, infinity). In the first interval a 24 term Chebyshev | -//| expansion is used. In the second, the asymptotic | -//| trigonometric representation is employed using two | -//| rational functions of degree 5/5. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 2.6e-16 1.1e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselJ1(double x) - { -//--- create variables - double result=0; - double s=0; - double xsq=0; - double nn=0; - double pzero=0; - double qzero=0; - double p1=0; - double q1=0; -//--- calculation - s=MathSign(x); -//--- check - if(x<0.0) - x=-x; -//--- check - if(x>8.0) - { - //--- function call - BesselAsympt1(x,pzero,qzero); - nn=x-3*M_PI/4; - result=MathSqrt(2/M_PI/x)*(pzero*MathCos(nn)-qzero*MathSin(nn)); - //--- check - if(s<0.0) - result=-result; - //--- return result - return(result); - } -//--- calculation - xsq=CMath::Sqr(x); - p1=2701.122710892323414856790990; - p1=-4695753.530642995859767162166+xsq*p1; - p1=3413234182.301700539091292655+xsq*p1; - p1=-1322983480332.126453125473247+xsq*p1; - p1=290879526383477.5409737601689+xsq*p1; - p1=-35888175699101060.50743641413+xsq*p1; - p1=2316433580634002297.931815435+xsq*p1; - p1=-66721065689249162980.20941484+xsq*p1; - p1=581199354001606143928.050809+xsq*p1; - q1=1.0; - q1=1606.931573481487801970916749+xsq*q1; - q1=1501793.594998585505921097578+xsq*q1; - q1=1013863514.358673989967045588+xsq*q1; - q1=524371026216.7649715406728642+xsq*q1; - q1=208166122130760.7351240184229+xsq*q1; - q1=60920613989175217.46105196863+xsq*q1; - q1=11857707121903209998.37113348+xsq*q1; - q1=1162398708003212287858.529400+xsq*q1; -//--- return result - return(s*x*p1/q1); - } -//+------------------------------------------------------------------+ -//| Bessel function of integer order | -//| Returns Bessel function of order n, where n is a | -//| (possibly negative) integer. | -//| The ratio of jn(x) to j0(x) is computed by backward | -//| recurrence. First the ratio jn/jn-1 is found by a | -//| continued fraction expansion. Then the recurrence | -//| relating successive orders is applied until j0 or j1 is | -//| reached. | -//| If n = 0 or 1 the routine for j0 or j1 is called | -//| directly. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic range # trials peak rms | -//| IEEE 0, 30 5000 4.4e-16 7.9e-17 | -//| Not suitable for large n or x. Use jv() (fractional order) | -//| instead. | -//+------------------------------------------------------------------+ -static double CBessel::BesselJN(int n,double x) - { -//--- create variables - double result=0; - double pkm2=0; - double pkm1=0; - double pk=0; - double xk=0; - double r=0; - double ans=0; - int k=0; - int sg=0; -//--- check - if(n<0) - { - n=-n; - //--- check - if(n%2==0) - sg=1; - else - sg=-1; - } - else - sg=1; -//--- check - if(x<0.0) - { - //--- check - if(n%2!=0) - sg=-sg; - x=-x; - } -//--- check - if(n==0) - return(sg*BesselJ0(x)); -//--- check - if(n==1) - return(sg*BesselJ1(x)); -//--- check - if(n==2) - { - //--- check - if(x==0.0) - return(0); - else - return(sg*(2.0*BesselJ1(x)/x-BesselJ0(x))); - } -//--- check - if(xMathAbs(pkm1)) - ans=BesselJ1(x)/pk; - else - ans=BesselJ0(x)/pkm1; -//--- return result - return(sg*ans); - } -//+------------------------------------------------------------------+ -//| Bessel function of the second kind, order zero | -//| Returns Bessel function of the second kind, of order | -//| zero, of the argument. | -//| The domain is divided into the intervals [0, 5] and | -//| (5, infinity). In the first interval a rational approximation | -//| R(x) is employed to compute | -//| y0(x) = R(x) + 2 * log(x) * j0(x) / PI. | -//| Thus a call to j0() is required. | -//| In the second interval, the Hankel asymptotic expansion | -//| is employed with two rational functions of degree 6/6 | -//| and 7/7. | -//| ACCURACY: | -//| Absolute error, when y0(x) < 1; else relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.3e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselY0(double x) - { -//--- create variables - double nn=0; - double xsq=0; - double pzero=0; - double qzero=0; - double p4=0; - double q4=0; -//--- check - if(x>8.0) - { - //--- function call - BesselAsympt0(x,pzero,qzero); - nn=x-M_PI/4; - //--- return result - return(MathSqrt(2/M_PI/x)*(pzero*MathSin(nn)+qzero*MathCos(nn))); - } -//--- calculation - xsq=CMath::Sqr(x); - p4=-41370.35497933148554125235152; - p4=59152134.65686889654273830069+xsq*p4; - p4=-34363712229.79040378171030138+xsq*p4; - p4=10255208596863.94284509167421+xsq*p4; - p4=-1648605817185729.473122082537+xsq*p4; - p4=137562431639934407.8571335453+xsq*p4; - p4=-5247065581112764941.297350814+xsq*p4; - p4=65874732757195549259.99402049+xsq*p4; - p4=-27502866786291095837.01933175+xsq*p4; - q4=1.0; - q4=1282.452772478993804176329391+xsq*q4; - q4=1001702.641288906265666651753+xsq*q4; - q4=579512264.0700729537480087915+xsq*q4; - q4=261306575504.1081249568482092+xsq*q4; - q4=91620380340751.85262489147968+xsq*q4; - q4=23928830434997818.57439356652+xsq*q4; - q4=4192417043410839973.904769661+xsq*q4; - q4=372645883898616588198.9980+xsq*q4; -//--- return result - return(p4/q4+2/M_PI*BesselJ0(x)*MathLog(x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of second kind of order one | -//| Returns Bessel function of the second kind of order one | -//| of the argument. | -//| The domain is divided into the intervals [0, 8] and | -//| (8, infinity). In the first interval a 25 term Chebyshev | -//| expansion is used, and a call to j1() is required. | -//| In the second, the asymptotic trigonometric representation | -//| is employed using two rational functions of degree 5/5. | -//| ACCURACY: | -//| Absolute error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.0e-15 1.3e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselY1(double x) - { -//--- create variables - double nn=0; - double xsq=0; - double pzero=0; - double qzero=0; - double p4=0; - double q4=0; -//--- check - if(x>8.0) - { - //--- function call - BesselAsympt1(x,pzero,qzero); - nn=x-3*M_PI/4; - //--- return result - return(MathSqrt(2/M_PI/x)*(pzero*MathSin(nn)+qzero*MathCos(nn))); - } -//--- calculation - xsq=CMath::Sqr(x); - p4=-2108847.540133123652824139923; - p4=3639488548.124002058278999428+xsq*p4; - p4=-2580681702194.450950541426399+xsq*p4; - p4=956993023992168.3481121552788+xsq*p4; - p4=-196588746272214065.8820322248+xsq*p4; - p4=21931073399177975921.11427556+xsq*p4; - p4=-1212297555414509577913.561535+xsq*p4; - p4=26554738314348543268942.48968+xsq*p4; - p4=-99637534243069222259967.44354+xsq*p4; - q4=1.0; - q4=1612.361029677000859332072312+xsq*q4; - q4=1563282.754899580604737366452+xsq*q4; - q4=1128686837.169442121732366891+xsq*q4; - q4=646534088126.5275571961681500+xsq*q4; - q4=297663212564727.6729292742282+xsq*q4; - q4=108225825940881955.2553850180+xsq*q4; - q4=29549879358971486742.90758119+xsq*q4; - q4=5435310377188854170800.653097+xsq*q4; - q4=508206736694124324531442.4152+xsq*q4; -//--- return result - return(x*p4/q4+2/M_PI*(BesselJ1(x)*MathLog(x)-1/x)); - } -//+------------------------------------------------------------------+ -//| Bessel function of second kind of integer order | -//| Returns Bessel function of order n, where n is a | -//| (possibly negative) integer. | -//| The function is evaluated by forward recurrence on | -//| n, starting with values computed by the routines | -//| y0() and y1(). | -//| If n = 0 or 1 the routine for y0 or y1 is called | -//| directly. | -//| ACCURACY: | -//| Absolute error, except relative | -//| when y > 1: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 3.4e-15 4.3e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselYN(int n,double x) - { -//--- create variables - int i=0; - double a=0; - double b=0; - double tmp=0; - double s=0; -//--- initialization - s=1; -//--- check - if(n<0) - { - n=-n; - //--- check - if(n%2!=0) - s=-1; - } -//--- check - if(n==0) - return(BesselY0(x)); -//--- check - if(n==1) - return(s*BesselY1(x)); -//--- calculation - a=BesselY0(x); - b=BesselY1(x); - for(i=1;i<=n-1;i++) - { - tmp=b; - b=2*i/x*b-a; - a=tmp; - } -//--- return result - return(s*b); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function of order zero | -//| Returns modified Bessel function of order zero of the | -//| argument. | -//| The function is defined as i0(x) = j0( ix ). | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 5.8e-16 1.4e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselI0(double x) - { -//--- create variables - double y=0; - double v=0; - double z=0; - double b0=0; - double b1=0; - double b2=0; -//--- check - if(x<0.0) - x=-x; -//--- check - if(x<=8.0) - { - y=x/2.0-2.0; - //--- function calls - BesselMFirstCheb(-4.41534164647933937950E-18,b0,b1,b2); - BesselMNextCheb(y,3.33079451882223809783E-17,b0,b1,b2); - BesselMNextCheb(y,-2.43127984654795469359E-16,b0,b1,b2); - BesselMNextCheb(y,1.71539128555513303061E-15,b0,b1,b2); - BesselMNextCheb(y,-1.16853328779934516808E-14,b0,b1,b2); - BesselMNextCheb(y,7.67618549860493561688E-14,b0,b1,b2); - BesselMNextCheb(y,-4.85644678311192946090E-13,b0,b1,b2); - BesselMNextCheb(y,2.95505266312963983461E-12,b0,b1,b2); - BesselMNextCheb(y,-1.72682629144155570723E-11,b0,b1,b2); - BesselMNextCheb(y,9.67580903537323691224E-11,b0,b1,b2); - BesselMNextCheb(y,-5.18979560163526290666E-10,b0,b1,b2); - BesselMNextCheb(y,2.65982372468238665035E-9,b0,b1,b2); - BesselMNextCheb(y,-1.30002500998624804212E-8,b0,b1,b2); - BesselMNextCheb(y,6.04699502254191894932E-8,b0,b1,b2); - BesselMNextCheb(y,-2.67079385394061173391E-7,b0,b1,b2); - BesselMNextCheb(y,1.11738753912010371815E-6,b0,b1,b2); - BesselMNextCheb(y,-4.41673835845875056359E-6,b0,b1,b2); - BesselMNextCheb(y,1.64484480707288970893E-5,b0,b1,b2); - BesselMNextCheb(y,-5.75419501008210370398E-5,b0,b1,b2); - BesselMNextCheb(y,1.88502885095841655729E-4,b0,b1,b2); - BesselMNextCheb(y,-5.76375574538582365885E-4,b0,b1,b2); - BesselMNextCheb(y,1.63947561694133579842E-3,b0,b1,b2); - BesselMNextCheb(y,-4.32430999505057594430E-3,b0,b1,b2); - BesselMNextCheb(y,1.05464603945949983183E-2,b0,b1,b2); - BesselMNextCheb(y,-2.37374148058994688156E-2,b0,b1,b2); - BesselMNextCheb(y,4.93052842396707084878E-2,b0,b1,b2); - BesselMNextCheb(y,-9.49010970480476444210E-2,b0,b1,b2); - BesselMNextCheb(y,1.71620901522208775349E-1,b0,b1,b2); - BesselMNextCheb(y,-3.04682672343198398683E-1,b0,b1,b2); - BesselMNextCheb(y,6.76795274409476084995E-1,b0,b1,b2); - //--- calculation - v=0.5*(b0-b2); - //--- return result - return(MathExp(x)*v); - } -//--- change value - z=32.0/x-2.0; -//--- function calls - BesselMFirstCheb(-7.23318048787475395456E-18,b0,b1,b2); - BesselMNextCheb(z,-4.83050448594418207126E-18,b0,b1,b2); - BesselMNextCheb(z,4.46562142029675999901E-17,b0,b1,b2); - BesselMNextCheb(z,3.46122286769746109310E-17,b0,b1,b2); - BesselMNextCheb(z,-2.82762398051658348494E-16,b0,b1,b2); - BesselMNextCheb(z,-3.42548561967721913462E-16,b0,b1,b2); - BesselMNextCheb(z,1.77256013305652638360E-15,b0,b1,b2); - BesselMNextCheb(z,3.81168066935262242075E-15,b0,b1,b2); - BesselMNextCheb(z,-9.55484669882830764870E-15,b0,b1,b2); - BesselMNextCheb(z,-4.15056934728722208663E-14,b0,b1,b2); - BesselMNextCheb(z,1.54008621752140982691E-14,b0,b1,b2); - BesselMNextCheb(z,3.85277838274214270114E-13,b0,b1,b2); - BesselMNextCheb(z,7.18012445138366623367E-13,b0,b1,b2); - BesselMNextCheb(z,-1.79417853150680611778E-12,b0,b1,b2); - BesselMNextCheb(z,-1.32158118404477131188E-11,b0,b1,b2); - BesselMNextCheb(z,-3.14991652796324136454E-11,b0,b1,b2); - BesselMNextCheb(z,1.18891471078464383424E-11,b0,b1,b2); - BesselMNextCheb(z,4.94060238822496958910E-10,b0,b1,b2); - BesselMNextCheb(z,3.39623202570838634515E-9,b0,b1,b2); - BesselMNextCheb(z,2.26666899049817806459E-8,b0,b1,b2); - BesselMNextCheb(z,2.04891858946906374183E-7,b0,b1,b2); - BesselMNextCheb(z,2.89137052083475648297E-6,b0,b1,b2); - BesselMNextCheb(z,6.88975834691682398426E-5,b0,b1,b2); - BesselMNextCheb(z,3.36911647825569408990E-3,b0,b1,b2); - BesselMNextCheb(z,8.04490411014108831608E-1,b0,b1,b2); -//--- calculation - v=0.5*(b0-b2); -//--- return result - return(MathExp(x)*v/MathSqrt(x)); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function of order one | -//| Returns modified Bessel function of order one of the | -//| argument. | -//| The function is defined as i1(x) = -i j1( ix ). | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.9e-15 2.1e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselI1(double x) - { -//--- create variables - double y=0; - double z=0; - double v=0; - double b0=0; - double b1=0; - double b2=0; -//--- initialization - z=MathAbs(x); -//--- check - if(z<=8.0) - { - //--- initialization - y=z/2.0-2.0; - //--- function call - BesselM1FirstCheb(2.77791411276104639959E-18,b0,b1,b2); - BesselM1NextCheb(y,-2.11142121435816608115E-17,b0,b1,b2); - BesselM1NextCheb(y,1.55363195773620046921E-16,b0,b1,b2); - BesselM1NextCheb(y,-1.10559694773538630805E-15,b0,b1,b2); - BesselM1NextCheb(y,7.60068429473540693410E-15,b0,b1,b2); - BesselM1NextCheb(y,-5.04218550472791168711E-14,b0,b1,b2); - BesselM1NextCheb(y,3.22379336594557470981E-13,b0,b1,b2); - BesselM1NextCheb(y,-1.98397439776494371520E-12,b0,b1,b2); - BesselM1NextCheb(y,1.17361862988909016308E-11,b0,b1,b2); - BesselM1NextCheb(y,-6.66348972350202774223E-11,b0,b1,b2); - BesselM1NextCheb(y,3.62559028155211703701E-10,b0,b1,b2); - BesselM1NextCheb(y,-1.88724975172282928790E-9,b0,b1,b2); - BesselM1NextCheb(y,9.38153738649577178388E-9,b0,b1,b2); - BesselM1NextCheb(y,-4.44505912879632808065E-8,b0,b1,b2); - BesselM1NextCheb(y,2.00329475355213526229E-7,b0,b1,b2); - BesselM1NextCheb(y,-8.56872026469545474066E-7,b0,b1,b2); - BesselM1NextCheb(y,3.47025130813767847674E-6,b0,b1,b2); - BesselM1NextCheb(y,-1.32731636560394358279E-5,b0,b1,b2); - BesselM1NextCheb(y,4.78156510755005422638E-5,b0,b1,b2); - BesselM1NextCheb(y,-1.61760815825896745588E-4,b0,b1,b2); - BesselM1NextCheb(y,5.12285956168575772895E-4,b0,b1,b2); - BesselM1NextCheb(y,-1.51357245063125314899E-3,b0,b1,b2); - BesselM1NextCheb(y,4.15642294431288815669E-3,b0,b1,b2); - BesselM1NextCheb(y,-1.05640848946261981558E-2,b0,b1,b2); - BesselM1NextCheb(y,2.47264490306265168283E-2,b0,b1,b2); - BesselM1NextCheb(y,-5.29459812080949914269E-2,b0,b1,b2); - BesselM1NextCheb(y,1.02643658689847095384E-1,b0,b1,b2); - BesselM1NextCheb(y,-1.76416518357834055153E-1,b0,b1,b2); - BesselM1NextCheb(y,2.52587186443633654823E-1,b0,b1,b2); - //--- calculation - v=0.5*(b0-b2); - z=v*z*MathExp(z); - } - else - { - //--- initialization - y=32.0/z-2.0; - //--- function calls - BesselM1FirstCheb(7.51729631084210481353E-18,b0,b1,b2); - BesselM1NextCheb(y,4.41434832307170791151E-18,b0,b1,b2); - BesselM1NextCheb(y,-4.65030536848935832153E-17,b0,b1,b2); - BesselM1NextCheb(y,-3.20952592199342395980E-17,b0,b1,b2); - BesselM1NextCheb(y,2.96262899764595013876E-16,b0,b1,b2); - BesselM1NextCheb(y,3.30820231092092828324E-16,b0,b1,b2); - BesselM1NextCheb(y,-1.88035477551078244854E-15,b0,b1,b2); - BesselM1NextCheb(y,-3.81440307243700780478E-15,b0,b1,b2); - BesselM1NextCheb(y,1.04202769841288027642E-14,b0,b1,b2); - BesselM1NextCheb(y,4.27244001671195135429E-14,b0,b1,b2); - BesselM1NextCheb(y,-2.10154184277266431302E-14,b0,b1,b2); - BesselM1NextCheb(y,-4.08355111109219731823E-13,b0,b1,b2); - BesselM1NextCheb(y,-7.19855177624590851209E-13,b0,b1,b2); - BesselM1NextCheb(y,2.03562854414708950722E-12,b0,b1,b2); - BesselM1NextCheb(y,1.41258074366137813316E-11,b0,b1,b2); - BesselM1NextCheb(y,3.25260358301548823856E-11,b0,b1,b2); - BesselM1NextCheb(y,-1.89749581235054123450E-11,b0,b1,b2); - BesselM1NextCheb(y,-5.58974346219658380687E-10,b0,b1,b2); - BesselM1NextCheb(y,-3.83538038596423702205E-9,b0,b1,b2); - BesselM1NextCheb(y,-2.63146884688951950684E-8,b0,b1,b2); - BesselM1NextCheb(y,-2.51223623787020892529E-7,b0,b1,b2); - BesselM1NextCheb(y,-3.88256480887769039346E-6,b0,b1,b2); - BesselM1NextCheb(y,-1.10588938762623716291E-4,b0,b1,b2); - BesselM1NextCheb(y,-9.76109749136146840777E-3,b0,b1,b2); - BesselM1NextCheb(y,7.78576235018280120474E-1,b0,b1,b2); - //--- calculation - v=0.5*(b0-b2); - z=v*MathExp(z)/MathSqrt(z); - } -//--- check - if(x<0.0) - z=-z; -//--- return result - return(z); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, order zero | -//| Returns modified Bessel function of the second kind | -//| of order zero of the argument. | -//| The range is partitioned into the two intervals [0,8] and | -//| (8, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Tested at 2000 random points between 0 and 8. Peak absolute | -//| error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.2e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselK0(double x) - { -//--- create variables - double result=0; - double y=0; - double z=0; - double v=0; - double b0=0; - double b1=0; - double b2=0; -//--- check - if(!CAp::Assert(x>0.0,__FUNCTION__+": x<=0")) - return(EMPTY_VALUE); -//--- check - if(x<=2.0) - { - //--- initialization - y=x*x-2.0; - //--- function calls - BesselMFirstCheb(1.37446543561352307156E-16,b0,b1,b2); - BesselMNextCheb(y,4.25981614279661018399E-14,b0,b1,b2); - BesselMNextCheb(y,1.03496952576338420167E-11,b0,b1,b2); - BesselMNextCheb(y,1.90451637722020886025E-9,b0,b1,b2); - BesselMNextCheb(y,2.53479107902614945675E-7,b0,b1,b2); - BesselMNextCheb(y,2.28621210311945178607E-5,b0,b1,b2); - BesselMNextCheb(y,1.26461541144692592338E-3,b0,b1,b2); - BesselMNextCheb(y,3.59799365153615016266E-2,b0,b1,b2); - BesselMNextCheb(y,3.44289899924628486886E-1,b0,b1,b2); - BesselMNextCheb(y,-5.35327393233902768720E-1,b0,b1,b2); - v=0.5*(b0-b2); - v=v-MathLog(0.5*x)*BesselI0(x); - } - else - { - //--- initialization - z=8.0/x-2.0; - //--- function call - BesselMFirstCheb(5.30043377268626276149E-18,b0,b1,b2); - BesselMNextCheb(z,-1.64758043015242134646E-17,b0,b1,b2); - BesselMNextCheb(z,5.21039150503902756861E-17,b0,b1,b2); - BesselMNextCheb(z,-1.67823109680541210385E-16,b0,b1,b2); - BesselMNextCheb(z,5.51205597852431940784E-16,b0,b1,b2); - BesselMNextCheb(z,-1.84859337734377901440E-15,b0,b1,b2); - BesselMNextCheb(z,6.34007647740507060557E-15,b0,b1,b2); - BesselMNextCheb(z,-2.22751332699166985548E-14,b0,b1,b2); - BesselMNextCheb(z,8.03289077536357521100E-14,b0,b1,b2); - BesselMNextCheb(z,-2.98009692317273043925E-13,b0,b1,b2); - BesselMNextCheb(z,1.14034058820847496303E-12,b0,b1,b2); - BesselMNextCheb(z,-4.51459788337394416547E-12,b0,b1,b2); - BesselMNextCheb(z,1.85594911495471785253E-11,b0,b1,b2); - BesselMNextCheb(z,-7.95748924447710747776E-11,b0,b1,b2); - BesselMNextCheb(z,3.57739728140030116597E-10,b0,b1,b2); - BesselMNextCheb(z,-1.69753450938905987466E-9,b0,b1,b2); - BesselMNextCheb(z,8.57403401741422608519E-9,b0,b1,b2); - BesselMNextCheb(z,-4.66048989768794782956E-8,b0,b1,b2); - BesselMNextCheb(z,2.76681363944501510342E-7,b0,b1,b2); - BesselMNextCheb(z,-1.83175552271911948767E-6,b0,b1,b2); - BesselMNextCheb(z,1.39498137188764993662E-5,b0,b1,b2); - BesselMNextCheb(z,-1.28495495816278026384E-4,b0,b1,b2); - BesselMNextCheb(z,1.56988388573005337491E-3,b0,b1,b2); - BesselMNextCheb(z,-3.14481013119645005427E-2,b0,b1,b2); - BesselMNextCheb(z,2.44030308206595545468E0,b0,b1,b2); - //--- calculation - v=0.5*(b0-b2); - v=v*MathExp(-x)/MathSqrt(x); - } -//--- return result - return(v); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, order one | -//| Computes the modified Bessel function of the second kind | -//| of order one of the argument. | -//| The range is partitioned into the two intervals [0,2] and | -//| (2, infinity). Chebyshev polynomial expansions are employed | -//| in each interval. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 30000 1.2e-15 1.6e-16 | -//+------------------------------------------------------------------+ -static double CBessel::BesselK1(double x) - { -//--- create variables - double result=0; - double y=0; - double z=0; - double v=0; - double b0=0; - double b1=0; - double b2=0; -//--- initialization - z=0.5*x; -//--- check - if(!CAp::Assert(z>0.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- check - if(x<=2.0) - { - //--- initialization - y=x*x-2.0; - //--- function calls - BesselM1FirstCheb(-7.02386347938628759343E-18,b0,b1,b2); - BesselM1NextCheb(y,-2.42744985051936593393E-15,b0,b1,b2); - BesselM1NextCheb(y,-6.66690169419932900609E-13,b0,b1,b2); - BesselM1NextCheb(y,-1.41148839263352776110E-10,b0,b1,b2); - BesselM1NextCheb(y,-2.21338763073472585583E-8,b0,b1,b2); - BesselM1NextCheb(y,-2.43340614156596823496E-6,b0,b1,b2); - BesselM1NextCheb(y,-1.73028895751305206302E-4,b0,b1,b2); - BesselM1NextCheb(y,-6.97572385963986435018E-3,b0,b1,b2); - BesselM1NextCheb(y,-1.22611180822657148235E-1,b0,b1,b2); - BesselM1NextCheb(y,-3.53155960776544875667E-1,b0,b1,b2); - BesselM1NextCheb(y,1.52530022733894777053E0,b0,b1,b2); - v=0.5*(b0-b2); - //--- get result - result=MathLog(z)*BesselI1(x)+v/x; - } - else - { - //--- initialization - y=8.0/x-2.0; - //--- function calls - BesselM1FirstCheb(-5.75674448366501715755E-18,b0,b1,b2); - BesselM1NextCheb(y,1.79405087314755922667E-17,b0,b1,b2); - BesselM1NextCheb(y,-5.68946255844285935196E-17,b0,b1,b2); - BesselM1NextCheb(y,1.83809354436663880070E-16,b0,b1,b2); - BesselM1NextCheb(y,-6.05704724837331885336E-16,b0,b1,b2); - BesselM1NextCheb(y,2.03870316562433424052E-15,b0,b1,b2); - BesselM1NextCheb(y,-7.01983709041831346144E-15,b0,b1,b2); - BesselM1NextCheb(y,2.47715442448130437068E-14,b0,b1,b2); - BesselM1NextCheb(y,-8.97670518232499435011E-14,b0,b1,b2); - BesselM1NextCheb(y,3.34841966607842919884E-13,b0,b1,b2); - BesselM1NextCheb(y,-1.28917396095102890680E-12,b0,b1,b2); - BesselM1NextCheb(y,5.13963967348173025100E-12,b0,b1,b2); - BesselM1NextCheb(y,-2.12996783842756842877E-11,b0,b1,b2); - BesselM1NextCheb(y,9.21831518760500529508E-11,b0,b1,b2); - BesselM1NextCheb(y,-4.19035475934189648750E-10,b0,b1,b2); - BesselM1NextCheb(y,2.01504975519703286596E-9,b0,b1,b2); - BesselM1NextCheb(y,-1.03457624656780970260E-8,b0,b1,b2); - BesselM1NextCheb(y,5.74108412545004946722E-8,b0,b1,b2); - BesselM1NextCheb(y,-3.50196060308781257119E-7,b0,b1,b2); - BesselM1NextCheb(y,2.40648494783721712015E-6,b0,b1,b2); - BesselM1NextCheb(y,-1.93619797416608296024E-5,b0,b1,b2); - BesselM1NextCheb(y,1.95215518471351631108E-4,b0,b1,b2); - BesselM1NextCheb(y,-2.85781685962277938680E-3,b0,b1,b2); - BesselM1NextCheb(y,1.03923736576817238437E-1,b0,b1,b2); - BesselM1NextCheb(y,2.72062619048444266945E0,b0,b1,b2); - v=0.5*(b0-b2); - //--- get result - result=MathExp(-x)*v/MathSqrt(x); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Modified Bessel function, second kind, integer order | -//| Returns modified Bessel function of the second kind | -//| of order n of the argument. | -//| The range is partitioned into the two intervals [0,9.55] and | -//| (9.55, infinity). An ascending power series is used in the | -//| low range, and an asymptotic expansion in the high range. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 90000 1.8e-8 3.0e-10 | -//| Error is high only near the crossover point x = 9.55 | -//| between the two expansions used. | -//+------------------------------------------------------------------+ -static double CBessel::BesselKN(int nn,double x) - { -//--- create variables - double k=0; - double kf=0; - double nk1f=0; - double nkf=0; - double zn=0; - double t=0; - double s=0; - double z0=0; - double z=0; - double ans=0; - double fn=0; - double pn=0; - double pk=0; - double zmn=0; - double tlg=0; - double tox=0; - int i=0; - int n=0; - double eul=0; -//--- initialization - eul=5.772156649015328606065e-1; -//--- check - if(nn<0) - n=-nn; - else - n=nn; -//--- check - if(!CAp::Assert(n<=31,__FUNCTION__+": overflow")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(x>0.0,__FUNCTION__+":domain error")) - return(EMPTY_VALUE); -//--- check - if(x<=9.55) - { - //--- initialization - ans=0.0; - z0=0.25*x*x; - fn=1.0; - pn=0.0; - zmn=1.0; - tox=2.0/x; - //--- check - if(n>0) - { - //--- calculation - pn=-eul; - k=1.0; - for(i=1;i<=n-1;i++) - { - pn=pn+1.0/k; - k=k+1.0; - fn=fn*k; - } - zmn=tox; - //--- check - if(n==1) - ans=1.0/x; - else - { - //--- change values - nk1f=fn/n; - kf=1.0; - s=nk1f; - z=-z0; - zn=1.0; - //--- calculation - for(i=1;i<=n-1;i++) - { - nk1f=nk1f/(n-i); - kf=kf*i; - zn=zn*z; - t=nk1f*zn/kf; - s=s+t; - //--- check - if(!CAp::Assert(CMath::m_maxrealnumber-MathAbs(t)>MathAbs(s),__FUNCTION__+": overflow")) - return(EMPTY_VALUE); - //--- check - if(!CAp::Assert(!(tox>1.0 && CMath::m_maxrealnumber/tox1.0 && CMath::m_maxrealnumber/zmn1.0 && CMath::m_maxrealnumber/tCMath::m_machineepsilon); - s=0.5*s/zmn; - //--- check - if(n%2!=0) - { - s=-s; - } - ans=ans+s; - //--- return result - return(ans); - } -//--- check - if(x>MathLog(CMath::m_maxrealnumber)) - return(0); -//--- change values - k=n; - pn=4.0*k*k; - pk=1.0; - z0=8.0*x; - fn=1.0; - t=1.0; - s=t; - nkf=CMath::m_maxrealnumber; - i=0; -//--- cycle - do - { - z=pn-pk*pk; - t=t*z/(fn*z0); - nk1f=MathAbs(t); - //--- check - if(i>=n && nk1f>(double)(nkf)) - break; - //--- change values - nkf=nk1f; - s=s+t; - fn=fn+1.0; - pk=pk+2.0; - i=i+1; - } - while(MathAbs(t/s)>CMath::m_machineepsilon); -//--- return result - return(MathExp(-x)*MathSqrt(M_PI/(2.0*x))*s); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselMFirstCheb(const double c,double &b0,double &b1, - double &b2) - { -//--- change values - b0=c; - b1=0.0; - b2=0.0; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselMNextCheb(const double x,const double c,double &b0, - double &b1,double &b2) - { -//--- change values - b2=b1; - b1=b0; - b0=x*b1-b2+c; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselM1FirstCheb(const double c,double &b0,double &b1, - double &b2) - { -//--- change values - b0=c; - b1=0.0; - b2=0.0; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselM1NextCheb(const double x,const double c,double &b0, - double &b1,double &b2) - { -//--- change values - b2=b1; - b1=b0; - b0=x*b1-b2+c; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselAsympt0(const double x,double &pzero,double &qzero) - { -//--- create variables - double xsq=0; - double p2=0; - double q2=0; - double p3=0; - double q3=0; -//--- initialization - pzero=0; - qzero=0; -//--- calculation - xsq=64.0/(x*x); - p2=0.0; - p2=2485.271928957404011288128951+xsq*p2; - p2=153982.6532623911470917825993+xsq*p2; - p2=2016135.283049983642487182349+xsq*p2; - p2=8413041.456550439208464315611+xsq*p2; - p2=12332384.76817638145232406055+xsq*p2; - p2=5393485.083869438325262122897+xsq*p2; - q2=1.0; - q2=2615.700736920839685159081813+xsq*q2; - q2=156001.7276940030940592769933+xsq*q2; - q2=2025066.801570134013891035236+xsq*q2; - q2=8426449.050629797331554404810+xsq*q2; - q2=12338310.22786324960844856182+xsq*q2; - q2=5393485.083869438325560444960+xsq*q2; - p3=-0.0; - p3=-4.887199395841261531199129300+xsq*p3; - p3=-226.2630641933704113967255053+xsq*p3; - p3=-2365.956170779108192723612816+xsq*p3; - p3=-8239.066313485606568803548860+xsq*p3; - p3=-10381.41698748464093880530341+xsq*p3; - p3=-3984.617357595222463506790588+xsq*p3; - q3=1.0; - q3=408.7714673983499223402830260+xsq*q3; - q3=15704.89191515395519392882766+xsq*q3; - q3=156021.3206679291652539287109+xsq*q3; - q3=533291.3634216897168722255057+xsq*q3; - q3=666745.4239319826986004038103+xsq*q3; - q3=255015.5108860942382983170882+xsq*q3; -//--- get result - pzero=p2/q2; - qzero=8*p3/q3/x; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CBessel::BesselAsympt1(const double x,double &pzero,double &qzero) - { -//--- create variables - double xsq=0; - double p2=0; - double q2=0; - double p3=0; - double q3=0; -//--- initialization - pzero=0; - qzero=0; -//--- calculation - xsq=64.0/(x*x); - p2=-1611.616644324610116477412898; - p2=-109824.0554345934672737413139+xsq*p2; - p2=-1523529.351181137383255105722+xsq*p2; - p2=-6603373.248364939109255245434+xsq*p2; - p2=-9942246.505077641195658377899+xsq*p2; - p2=-4435757.816794127857114720794+xsq*p2; - q2=1.0; - q2=-1455.009440190496182453565068+xsq*q2; - q2=-107263.8599110382011903063867+xsq*q2; - q2=-1511809.506634160881644546358+xsq*q2; - q2=-6585339.479723087072826915069+xsq*q2; - q2=-9934124.389934585658967556309+xsq*q2; - q2=-4435757.816794127856828016962+xsq*q2; - p3=35.26513384663603218592175580; - p3=1706.375429020768002061283546+xsq*p3; - p3=18494.26287322386679652009819+xsq*p3; - p3=66178.83658127083517939992166+xsq*p3; - p3=85145.16067533570196555001171+xsq*p3; - p3=33220.91340985722351859704442+xsq*p3; - q3=1.0; - q3=863.8367769604990967475517183+xsq*q3; - q3=37890.22974577220264142952256+xsq*q3; - q3=400294.4358226697511708610813+xsq*q3; - q3=1419460.669603720892855755253+xsq*q3; - q3=1819458.042243997298924553839+xsq*q3; - q3=708712.8194102874357377502472+xsq*q3; -//--- get result - pzero=p2/q2; - qzero=8*p3/q3/x; - } -//+------------------------------------------------------------------+ -//| Beta function | -//+------------------------------------------------------------------+ -class CBetaF - { -public: - //--- constructor, destructor - CBetaF(void); - ~CBetaF(void); - //--- method - static double Beta(const double a,const double b); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CBetaF::CBetaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBetaF::~CBetaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Beta function | -//| - - | -//| | (a) | (b) | -//| beta( a, b ) = -----------. | -//| - | -//| | (a+b) | -//| For large arguments the logarithm of the function is | -//| evaluated using lgam(), then exponentiated. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 8.1e-14 1.1e-14 | -//+------------------------------------------------------------------+ -static double CBetaF::Beta(const double a,const double b) - { -//--- create variables - double y=0; - double sg=0; - double s=0; -//--- initialization - sg=1; -//--- check - if(!CAp::Assert(a>0.0 || a!=(double)((int)MathFloor(a)),__FUNCTION__+": overflow")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(b>0.0 || b!=(double)((int)MathFloor(b)),__FUNCTION__+": overflow")) - return(EMPTY_VALUE); - y=a+b; -//--- check - if(MathAbs(y)>171.624376956302725) - { - //--- calculation - y=CGammaFunc::LnGamma(y,s); - sg=sg*s; - y=CGammaFunc::LnGamma(b,s)-y; - sg=sg*s; - y=CGammaFunc::LnGamma(a,s)+y; - sg=sg*s; - //--- check - if(!CAp::Assert(y<=(double)(MathLog(CMath::m_maxrealnumber)),__FUNCTION__+": overflow")) - return(EMPTY_VALUE); - //--- return result - return(sg*MathExp(y)); - } -//--- function call - y=CGammaFunc::GammaFunc(y); -//--- check - if(!CAp::Assert(y!=0.0,"Overflow in Beta")) - return(EMPTY_VALUE); -//--- check - if(a>b) - { - //--- calculation - y=CGammaFunc::GammaFunc(a)/y; - y=y*CGammaFunc::GammaFunc(b); - } - else - { - //--- calculation - y=CGammaFunc::GammaFunc(b)/y; - y=y*CGammaFunc::GammaFunc(a); - } -//--- return result - return(y); - } -//+------------------------------------------------------------------+ -//| Incomplete beta function | -//+------------------------------------------------------------------+ -class CIncBetaF - { -private: - //--- private methods - static double IncompleteBetaFracExpans(const double a,const double b,const double x,const double big,const double biginv); - static double IncompleteBetaFracExpans2(const double a,const double b,const double x,const double big,const double biginv); - static double IncompleteBetaPowSeries(const double a,const double b,const double x,const double maxgam); -public: - //--- constructor, destructor - CIncBetaF(void); - ~CIncBetaF(void); - //--- public methods - static double IncompleteBeta(double a,double b,double x); - static double InvIncompleteBeta(const double a,double b,double y); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CIncBetaF::CIncBetaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CIncBetaF::~CIncBetaF(void) - { - - } -//+------------------------------------------------------------------+ -//| Incomplete beta integral | -//| Returns incomplete beta integral of the arguments, evaluated | -//| from zero to x. The function is defined as | -//| x | -//| - - | -//| | (a+b) | | a-1 b-1 | -//| ----------- | t (1-t) dt. | -//| - - | | | -//| | (a) | (b) - | -//| 0 | -//| The domain of definition is 0 <= x <= 1. In this | -//| implementation a and b are restricted to positive values. | -//| The integral from x to 1 may be obtained by the symmetry | -//| relation | -//| 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). | -//| The integral is evaluated by a continued fraction expansion | -//| or, when b*x is small, by a power series. | -//| ACCURACY: | -//| Tested at uniformly distributed random points (a,b,x) with a and | -//| b in "domain" and x between 0 and 1. | -//| Relative error | -//| arithmetic domain # trials peak rms | -//| IEEE 0,5 10000 6.9e-15 4.5e-16 | -//| IEEE 0,85 250000 2.2e-13 1.7e-14 | -//| IEEE 0,1000 30000 5.3e-12 6.3e-13 | -//| IEEE 0,10000 250000 9.3e-11 7.1e-12 | -//| IEEE 0,100000 10000 8.7e-10 4.8e-11 | -//| Outputs smaller than the IEEE gradual underflow threshold | -//| were excluded from these statistics. | -//+------------------------------------------------------------------+ -static double CIncBetaF::IncompleteBeta(double a,double b,double x) - { -//--- check - if(!CAp::Assert(a>0 && b>0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(x>=0 && x<=1,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(x==0) - return(0); -//--- check - if(x==1) - return(1); -//--- create variables - double t; - double xc; - double w; - double y; - int flag=0; - double sg=0; - double big=4.503599627370496e15; - double biginv=2.22044604925031308085e-16; - double maxgam=171.624376956302725; - double minlog=MathLog(CMath::m_minrealnumber); - double maxlog=MathLog(CMath::m_maxrealnumber); - -//--- check - if(b*x<=1.0 && x<=0.95) - return(IncompleteBetaPowSeries(a,b,x,maxgam)); -//--- change value - w=1.0-x; -//--- check - if(x>a/(a+b)) - { - flag=1; - t=a; - a=b; - b=t; - xc=x; - x=w; - } - else - xc=w; -//--- check - if(flag==1 && b*x<=1.0 && x<=0.95) - { - t=IncompleteBetaPowSeries(a,b,x,maxgam); - //--- check - if(t<=CMath::m_machineepsilon) - return(1.0-CMath::m_machineepsilon); - else - return(1.0-t); - } -//--- change value - y=x*(a+b-2.0)-(a-1.0); -//--- check - if(y<0.0) - w=IncompleteBetaFracExpans(a,b,x,big,biginv); - else - w=IncompleteBetaFracExpans2(a,b,x,big,biginv)/xc; -//--- change values - y=a*MathLog(x); - t=b*MathLog(xc); -//--- check - if(a+b=0 && y<=1,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(y==0) - return(0); -//--- check - if(y==1.0) - return(1); -//--- create variables - double aaa=0; - double bbb=0; - double y0=0; - double d=0; - double yyy=0; - double x=0; - double x0=0.0; - double x1=1.0; - double lgm=0; - double yp=0; - double di=0; - double dithresh=0; - double yl=0.0; - double yh=1.0; - double xt=0; - int i=0; - int rflg=0; - int dir=0; - int nflg=0; - double s=0; - int mainlooppos=0; - int ihalve=1; - int ihalvecycle=2; - int newt=3; - int newtcycle=4; - int breaknewtcycle=5; - int breakihalvecycle=6; -//--- main - while(true) - { - //--- start - if(mainlooppos==0) - { - if(a<=1.0 || b<=1.0) - { - dithresh=1.0e-6; - rflg=0; - aaa=a; - bbb=b; - y0=y; - x=aaa/(aaa+bbb); - yyy=IncompleteBeta(aaa,bbb,x); - mainlooppos=ihalve; - continue; - } - else - dithresh=1.0e-4; - //--- change value - yp=-CNormalDistr::InvNormalDistribution(y); - //--- check - if(y>0.5) - { - rflg=1; - aaa=b; - bbb=a; - y0=1.0-y; - yp=-yp; - } - else - { - rflg=0; - aaa=a; - bbb=b; - y0=y; - } - //--- change values - lgm=(yp*yp-3.0)/6.0; - x=2.0/(1.0/(2.0*aaa-1.0)+1.0/(2.0*bbb-1.0)); - d=yp*MathSqrt(x+lgm)/x-(1.0/(2.0*bbb-1.0)-1.0/(2.0*aaa-1.0))*(lgm+5.0/6.0-2.0/(3.0*x)); - d=2.0*d; - //--- check - if(d3) - di=1.0-(1.0-di)*(1.0-di); - else - { - //--- check - if(dir>1) - di=0.5*di+0.5; - else - di=(y0-yyy)/(yh-yl); - } - } - dir++; - //--- check - if(x0>0.75) - { - //--- check - if(rflg==1) - { - rflg=0; - aaa=a; - bbb=b; - y0=y; - } - else - { - rflg=1; - aaa=b; - bbb=a; - y0=1.0-y; - } - //--- change values - x=1.0-x; - yyy=IncompleteBeta(aaa,bbb,x); - x0=0.0; - yl=0.0; - x1=1.0; - yh=1.0; - mainlooppos=ihalve; - continue; - } - } - else - { - x1=x; - //--- check - if(rflg==1 && x10) - { - dir=0; - di=0.5; - } - else - { - //--- check - if(dir<-3) - di*=di; - else - { - //--- check - if(dir<-1) - di*=0.5; - else - di=(yyy-y0)/(yh-yl); - } - } - dir--; - } - i++; - mainlooppos=ihalvecycle; - continue; - } - else - { - mainlooppos=breakihalvecycle; - continue; - } - } - //--- check - if(mainlooppos==breakihalvecycle) - { - //--- check - if(x0>=1.0) - { - x=1.0-CMath::m_machineepsilon; - break; - } - //--- check - if(x<=0.0) - { - x=0.0; - break; - } - mainlooppos=newt; - continue; - } - //--- check - if(mainlooppos==newt) - { - if(nflg!=0) - break; - //--- change values - nflg=1; - lgm=CGammaFunc::LnGamma(aaa+bbb,s)-CGammaFunc::LnGamma(aaa,s)-CGammaFunc::LnGamma(bbb,s); - i=0; - mainlooppos=newtcycle; - continue; - } - //--- check - if(mainlooppos==newtcycle) - { - //--- check - if(i<=7) - { - //--- check - if(i!=0) - yyy=IncompleteBeta(aaa,bbb,x); - //--- check - if(yyyyh) - { - x=x1; - yyy=yh; - } - else - { - //--- check - if(yyyMathLog(CMath::m_maxrealnumber)) - { - mainlooppos=breaknewtcycle; - continue; - } - //--- change values - d=MathExp(d); - d=(yyy-y0)/d; - xt=x-d; - //--- check - if(xt<=x0) - { - yyy=(x-x0)/(x1-x0); - xt=x0+0.5*yyy*(x-x0); - //--- check - if(xt<=0.0) - { - mainlooppos=breaknewtcycle; - continue; - } - } - //--- check - if(xt>=x1) - { - yyy=(x1-x)/(x1-x0); - xt=x1-0.5*yyy*(x1-x); - //--- check - if(xt>=1.0) - { - mainlooppos=breaknewtcycle; - continue; - } - } - x=xt; - //--- check - if(MathAbs(d/x)<128.0*CMath::m_machineepsilon) - break; - //--- change values - i=i+1; - mainlooppos=newtcycle; - continue; - } - else - { - mainlooppos=breaknewtcycle; - continue; - } - } - //--- check - if(mainlooppos==breaknewtcycle) - { - dithresh=256.0*CMath::m_machineepsilon; - mainlooppos=ihalve; - continue; - } - } -//--- get result - if(rflg!=0) - { - if(x<=CMath::m_machineepsilon) - x=1.0-CMath::m_machineepsilon; - else - x=1.0-x; - } -//--- return result - return(x); - } -//+------------------------------------------------------------------+ -//| Continued fraction expansion #1 for incomplete beta integral | -//+------------------------------------------------------------------+ -static double CIncBetaF::IncompleteBetaFracExpans(const double a,const double b, - const double x,const double big, - const double biginv) - { -//--- create variables - double xk=0; - double pk=0; - double pkm1=1.0; - double pkm2=0.0; - double qk=0; - double qkm1=1.0; - double qkm2=1.0; - double k1=a; - double k2=a+b; - double k3=a; - double k4=a+1.0; - double k5=1.0; - double k6=b-1.0; - double k7=k4; - double k8=a+2.0; - double r=1.0; - double t=0; - double ans=1.0; - double thresh=3.0*CMath::m_machineepsilon; - int n=0; -//--- cycle - do - { - xk=-(x*k1*k2/(k3*k4)); - pk=pkm1+pkm2*xk; - qk=qkm1+qkm2*xk; - pkm2=pkm1; - pkm1=pk; - qkm2=qkm1; - qkm1=qk; - xk=x*k5*k6/(k7*k8); - pk=pkm1+pkm2*xk; - qk=qkm1+qkm2*xk; - pkm2=pkm1; - pkm1=pk; - qkm2=qkm1; - qkm1=qk; - //--- check - if(qk!=0) - r=pk/qk; - //--- check - if(r!=0) - { - t=MathAbs((ans-r)/r); - ans=r; - } - else - t=1.0; - //--- check - if(tbig) - { - pkm2*=biginv; - pkm1*=biginv; - qkm2*=biginv; - qkm1*=biginv; - } - //--- check - if(MathAbs(qk)big) - { - pkm2*=biginv; - pkm1*=biginv; - qkm2*=biginv; - qkm1*=biginv; - } - //--- check - if(MathAbs(qk)z) - { - u=(n-b)*x/n; - t=t*u; - v=t/(a+n); - s=s+v; - n=n+1.0; - } -//--- change values - s+=t1; - s+=ai; - u=a*MathLog(x); -//--- check - if(a+b ( ) p (1-p) | -//| -- ( j ) | -//| j=0 | -//| The terms are not summed directly; instead the incomplete | -//| beta integral is employed, according to the formula | -//| y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). | -//| The arguments must be positive, with p ranging from 0 to 1. | -//| ACCURACY: | -//| Tested at random points (a,b,p), with p between 0 and 1. | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 4.3e-15 2.6e-16 | -//+------------------------------------------------------------------+ -static double CBinomialDistr::BinomialDistribution(const int k,const int n, - const double p) - { -//--- check - if(!CAp::Assert(p>=0 && p<=1,__FUNCTION__+": the eroor variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(k>=-1 && k<=n,__FUNCTION__+": the eroor variable")) - return(EMPTY_VALUE); -//--- check - if(k==-1) - return(0); -//--- check - if(k==n) - return(1); -//--- create variables - double dk; - double dn=n-k; -//--- check - if(k==0) - dk=MathPow(1.0-p,dn); - else - { - dk=k+1; - dk=CIncBetaF::IncompleteBeta(dn,dk,1.0-p); - } -//--- return result - return(dk); - } -//+------------------------------------------------------------------+ -//| Complemented binomial distribution | -//| Returns the sum of the terms k+1 through n of the Binomial | -//| probability density: | -//| n | -//| -- ( n ) j n-j | -//| > ( ) p (1-p) | -//| -- ( j ) | -//| j=k+1 | -//| The terms are not summed directly; instead the incomplete | -//| beta integral is employed, according to the formula | -//| y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). | -//| The arguments must be positive, with p ranging from 0 to 1. | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 6.7e-15 8.2e-16 | -//| For p between 0 and .001: | -//| IEEE 0,100 100000 1.5e-13 2.7e-15 | -//+------------------------------------------------------------------+ -static double CBinomialDistr::BinomialComplDistribution(const int k, - const int n, - const double p) - { -//--- check - if(!CAp::Assert(p>=0 && p<=1,__FUNCTION__+": the eroor variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(k>=-1 && k<=n,__FUNCTION__+": the eroor variable")) - return(EMPTY_VALUE); -//--- check - if(k==-1) - return(0); -//--- check - if(k==n) - return(1); -//--- create variables - double dk; - double dn=n-k; -//--- check - if(k==0) - dk=MathPow(1.0-p,dn); - else - { - dk=k+1; - dk=CIncBetaF::IncompleteBeta(dn,dk,1.0-p); - } -//--- return result - return(dk); - } -//+------------------------------------------------------------------+ -//| Inverse binomial distribution | -//| Finds the event probability p such that the sum of the | -//| terms 0 through k of the Binomial probability density | -//| is equal to the given cumulative probability y. | -//| This is accomplished using the inverse beta integral | -//| function and the relation | -//| 1 - p = incbi( n-k, k+1, y ). | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between 0.001 and 1: | -//| IEEE 0,100 100000 2.3e-14 6.4e-16 | -//| IEEE 0,10000 100000 6.6e-12 1.2e-13 | -//| For p between 10^-6 and 0.001: | -//| IEEE 0,100 100000 2.0e-12 1.3e-14 | -//| IEEE 0,10000 100000 1.5e-12 3.2e-14 | -//+------------------------------------------------------------------+ -static double CBinomialDistr::InvBinomialDistribution(const int k,const int n, - const double y) - { -//--- create variables - double dk=0; - double dn=0; - double p=0; -//--- check - if(!CAp::Assert(k>=0 && k0.8) - p=-CNearUnitYUnit::NUExp1m(CNearUnitYUnit::NULog1p(y-1.0)/dn); - else - p=1.0-MathPow(y,1.0/dn); - } - else - { - dk=k+1; - //--- function call - p=CIncBetaF::IncompleteBeta(dn,dk,0.5); - //--- check - if(p>0.5) - p=CIncBetaF::InvIncompleteBeta(dk,dn,1.0-y); - else - p=1.0-CIncBetaF::InvIncompleteBeta(dn,dk,y); - } -//--- return result - return(p); - } -//+------------------------------------------------------------------+ -//| Chebyshev polynomials | -//+------------------------------------------------------------------+ -class CChebyshev - { -public: - //--- constructor, destructor - CChebyshev(void); - ~CChebyshev(void); - //--- methods - static double ChebyshevCalculate(const int r,const int n,const double x); - static double ChebyshevSum(double &c[],const int r,const int n,const double x); - static void ChebyshevCoefficients(const int n,double &c[]); - static void FromChebyshev(double &a[],const int n,double &b[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CChebyshev::CChebyshev(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChebyshev::~CChebyshev(void) - { - - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Chebyshev polynomials of the | -//| first and second kinds. | -//| Parameters: | -//| r - polynomial kind, either 1 or 2. | -//| n - degree, n>=0 | -//| x - argument, -1 <= x <= 1 | -//| Result: | -//| the value of the Chebyshev polynomial at x | -//+------------------------------------------------------------------+ -static double CChebyshev::ChebyshevCalculate(const int r,const int n, - const double x) - { -//--- create variables - double result=0; - int i=0; - double a=0; - double b=0; -//--- Prepare A and B - if(r==1) - { - a=1; - b=x; - } - else - { - a=1; - b=2*x; - } -//--- Special cases: N=0 or N=1 - if(n==0) - return(a); -//--- check - if(n==1) - return(b); -//--- General case: N>=2 - for(i=2;i<=n;i++) - { - result=2*x*b-a; - a=b; - b=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Summation of Chebyshev polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) | -//| or | -//| c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) | -//| depending on the R. | -//| Parameters: | -//| r - polynomial kind, either 1 or 2. | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Chebyshev polynomial at x | -//+------------------------------------------------------------------+ -static double CChebyshev::ChebyshevSum(double &c[],const int r,const int n, - const double x) - { -//--- create variables - double result=0; - double b1=0; - double b2=0; - int i=0; -//--- initialization - b1=0; - b2=0; -//--- calculation - for(i=n;i>=1;i--) - { - result=2*x*b1-b2+c[i]; - b2=b1; - b1=result; - } -//--- check - if(r==1) - result=-b2+x*b1+c[0]; - else - result=-b2+2*x*b1+c[0]; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CChebyshev::ChebyshevCoefficients(const int n,double &c[]) - { -//--- create a variable - int i=0; -//--- allocation - ArrayResizeAL(c,n+1); - for(i=0;i<=n;i++) - c[i]=0; -//--- check - if(n==0 || n==1) - c[n]=1; - else - { - c[n]=MathExp((n-1)*MathLog(2)); - //--- calculation - for(i=0;i<=n/2-1;i++) - c[n-2*(i+1)]=-(c[n-2*i]*(n-2*i)*(n-2*i-1)/4/(i+1)/(n-i-1)); - } - } -//+------------------------------------------------------------------+ -//| Conversion of a series of Chebyshev polynomials to a power | -//| series. | -//| Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as | -//| B[0] + B[1]*X + ... + B[N]*X^N. | -//| Input parameters: | -//| A - Chebyshev series coefficients | -//| N - degree, N>=0 | -//| Output parameters | -//| B - power series coefficients | -//+------------------------------------------------------------------+ -static void CChebyshev::FromChebyshev(double &a[],const int n,double &b[]) - { -//--- create variables - int i=0; - int k=0; - double e=0; - double d=0; -//--- allocation - ArrayResizeAL(b,n+1); -//--- initialization - for(i=0;i<=n;i++) - b[i]=0; -//--- calculation - d=0; - i=0; - do - { - k=i; - //--- cycle - do - { - e=b[k]; - b[k]=0; - //--- check - if(i<=1 && k==i) - b[k]=1; - else - { - //--- check - if(i!=0) - b[k]=2*d; - //--- check - if(k>i+1) - b[k]=b[k]-b[k-2]; - } - //--- change values - d=e; - k=k+1; - } - while(k<=n); - //--- change values - d=b[i]; - e=0; - k=i; - //--- calculation - while(k<=n) - { - e=e+b[k]*a[k]; - k=k+2; - } - //--- change values - b[i]=e; - i=i+1; - } - while(i<=n); - } -//+------------------------------------------------------------------+ -//| Chi-square distribution | -//+------------------------------------------------------------------+ -class CChiSquareDistr - { -public: - //--- constructor, destructor - CChiSquareDistr(void); - ~CChiSquareDistr(void); - //--- methods - static double ChiSquareDistribution(const double v,const double x); - static double ChiSquareComplDistribution(const double v,const double x); - static double InvChiSquareDistribution(const double v,const double y); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CChiSquareDistr::CChiSquareDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChiSquareDistr::~CChiSquareDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Chi-square distribution | -//| Returns the area under the left hand tail (from 0 to x) | -//| of the Chi square probability density function with | -//| v degrees of freedom. | -//| x | -//| - | -//| 1 | | v/2-1 -t/2 | -//| P( x | v ) = ----------- | t e dt | -//| v/2 - | | | -//| 2 | (v/2) - | -//| 0 | -//| where x is the Chi-square variable. | -//| The incomplete gamma integral is used, according to the | -//| formula | -//| y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CChiSquareDistr::ChiSquareDistribution(const double v, - const double x) - { -//--- check - if(!CAp::Assert(x>=0 && v>=1,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- return result - return(CIncGammaF::IncompleteGamma(v/2.0,x/2.0)); - } -//+------------------------------------------------------------------+ -//| Complemented Chi-square distribution | -//| Returns the area under the right hand tail (from x to | -//| infinity) of the Chi square probability density function | -//| with v degrees of freedom: | -//| inf. | -//| - | -//| 1 | | v/2-1 -t/2 | -//| P( x | v ) = ----------- | t e dt | -//| v/2 - | | | -//| 2 | (v/2) - | -//| x | -//| where x is the Chi-square variable. | -//| The incomplete gamma integral is used, according to the | -//| formula | -//| y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CChiSquareDistr::ChiSquareComplDistribution(const double v, - const double x) - { -//--- check - if(!CAp::Assert(x>=0.0 && v>=1.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- return result - return(CIncGammaF::IncompleteGammaC(v/2.0,x/2.0)); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented Chi-square distribution | -//| Finds the Chi-square argument x such that the integral | -//| from x to infinity of the Chi-square density is equal | -//| to the given cumulative probability y. | -//| This is accomplished using the inverse gamma integral | -//| function and the relation | -//| x/2 = igami( df/2, y ); | -//| ACCURACY: | -//| See inverse incomplete gamma function | -//+------------------------------------------------------------------+ -static double CChiSquareDistr::InvChiSquareDistribution(const double v, - const double y) - { -//--- check - if(!CAp::Assert((y>=0.0 && y<=1.0) && v>=1.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- return result - return(2*CIncGammaF::InvIncompleteGammaC(0.5*v,y)); - } -//+------------------------------------------------------------------+ -//| Dawson integral | -//+------------------------------------------------------------------+ -class CDawson - { -public: - //--- constructor, destructor - CDawson(void); - ~CDawson(void); - //--- method - static double DawsonIntegral(double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CDawson::CDawson(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDawson::~CDawson(void) - { - - } -//+------------------------------------------------------------------+ -//| Dawson's Integral | -//| Approximates the integral | -//| x | -//| - | -//| 2 | | 2 | -//| dawsn(x) = exp( -x ) | exp( t ) dt | -//| | | | -//| - | -//| 0 | -//| Three different rational approximations are employed, for | -//| the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,10 10000 6.9e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CDawson::DawsonIntegral(double x) - { -//--- create variables - double result=0; - double x2=0; - double y=0; - int sg=0; - double an=0; - double ad=0; - double bn=0; - double bd=0; - double cn=0; - double cd=0; -//--- initialization - sg=1; -//--- check - if(x<0.0) - { - sg=-1; - x=-x; - } -//--- check - if(x<3.25) - { - //--- calculation - x2=x*x; - an=1.13681498971755972054E-11; - an=an*x2+8.49262267667473811108E-10; - an=an*x2+1.94434204175553054283E-8; - an=an*x2+9.53151741254484363489E-7; - an=an*x2+3.07828309874913200438E-6; - an=an*x2+3.52513368520288738649E-4; - an=an*x2+-8.50149846724410912031E-4; - an=an*x2+4.22618223005546594270E-2; - an=an*x2+-9.17480371773452345351E-2; - an=an*x2+9.99999999999999994612E-1; - ad=2.40372073066762605484E-11; - ad=ad*x2+1.48864681368493396752E-9; - ad=ad*x2+5.21265281010541664570E-8; - ad=ad*x2+1.27258478273186970203E-6; - ad=ad*x2+2.32490249820789513991E-5; - ad=ad*x2+3.25524741826057911661E-4; - ad=ad*x2+3.48805814657162590916E-3; - ad=ad*x2+2.79448531198828973716E-2; - ad=ad*x2+1.58874241960120565368E-1; - ad=ad*x2+5.74918629489320327824E-1; - ad=ad*x2+1.00000000000000000539E0; - y=x*an/ad; - //--- return result - return(sg*y); - } - x2=1.0/(x*x); -//--- check - if(x<6.25) - { - //--- calculation - bn=5.08955156417900903354E-1; - bn=bn*x2-2.44754418142697847934E-1; - bn=bn*x2+9.41512335303534411857E-2; - bn=bn*x2-2.18711255142039025206E-2; - bn=bn*x2+3.66207612329569181322E-3; - bn=bn*x2-4.23209114460388756528E-4; - bn=bn*x2+3.59641304793896631888E-5; - bn=bn*x2-2.14640351719968974225E-6; - bn=bn*x2+9.10010780076391431042E-8; - bn=bn*x2-2.40274520828250956942E-9; - bn=bn*x2+3.59233385440928410398E-11; - bd=1.00000000000000000000E0; - bd=bd*x2-6.31839869873368190192E-1; - bd=bd*x2+2.36706788228248691528E-1; - bd=bd*x2-5.31806367003223277662E-2; - bd=bd*x2+8.48041718586295374409E-3; - bd=bd*x2-9.47996768486665330168E-4; - bd=bd*x2+7.81025592944552338085E-5; - bd=bd*x2-4.55875153252442634831E-6; - bd=bd*x2+1.89100358111421846170E-7; - bd=bd*x2-4.91324691331920606875E-9; - bd=bd*x2+7.18466403235734541950E-11; - y=1.0/x+x2*bn/(bd*x); - //--- return result - return(sg*0.5*y); - } -//--- check - if(x>1.0E9) - return(sg*0.5/x); -//--- calculation - cn=-5.90592860534773254987E-1; - cn=cn*x2+6.29235242724368800674E-1; - cn=cn*x2-1.72858975380388136411E-1; - cn=cn*x2+1.64837047825189632310E-2; - cn=cn*x2-4.86827613020462700845E-4; - cd=1.00000000000000000000E0; - cd=cd*x2-2.69820057197544900361E0; - cd=cd*x2+1.73270799045947845857E0; - cd=cd*x2-3.93708582281939493482E-1; - cd=cd*x2+3.44278924041233391079E-2; - cd=cd*x2-9.73655226040941223894E-4; - y=1.0/x+x2*cn/(cd*x); -//--- return result - return(sg*0.5*y); - } -//+------------------------------------------------------------------+ -//| Elliptic integral | -//+------------------------------------------------------------------+ -class CElliptic - { -public: - //--- constructor, destructor - CElliptic(void); - ~CElliptic(void); - //--- methods - static double EllipticIntegralK(const double m); - static double EllipticIntegralKhighPrecision(const double m1); - static double IncompleteEllipticIntegralK(double phi,const double m); - static double EllipticIntegralE(double m); - static double IncompleteEllipticIntegralE(const double phi,const double m); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CElliptic::CElliptic(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CElliptic::~CElliptic(void) - { - - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the first kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | | -//| | dt | -//| K(m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| using the approximation | -//| P(x) - log x Q(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 2.5e-16 6.8e-17 | -//+------------------------------------------------------------------+ -static double CElliptic::EllipticIntegralK(const double m) - { -//--- return result - return(EllipticIntegralKhighPrecision(1.0-m)); - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the first kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | | -//| | dt | -//| K(m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| where m = 1 - m1, using the approximation | -//| P(x) - log x Q(x). | -//| The argument m1 is used rather than m so that the logarithmic | -//| singularity at m = 1 will be shifted to the origin; this | -//| preserves maximum accuracy. | -//| K(0) = pi/2. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,1 30000 2.5e-16 6.8e-17 | -//+------------------------------------------------------------------+ -static double CElliptic::EllipticIntegralKhighPrecision(const double m1) - { -//--- create variables - double result=0; - double p=0; - double q=0; -//--- check - if(m1<=CMath::m_machineepsilon) - result=1.3862943611198906188E0-0.5*MathLog(m1); - else - { - //--- calculation - p=1.37982864606273237150E-4; - p=p*m1+2.28025724005875567385E-3; - p=p*m1+7.97404013220415179367E-3; - p=p*m1+9.85821379021226008714E-3; - p=p*m1+6.87489687449949877925E-3; - p=p*m1+6.18901033637687613229E-3; - p=p*m1+8.79078273952743772254E-3; - p=p*m1+1.49380448916805252718E-2; - p=p*m1+3.08851465246711995998E-2; - p=p*m1+9.65735902811690126535E-2; - p=p*m1+1.38629436111989062502E0; - q=2.94078955048598507511E-5; - q=q*m1+9.14184723865917226571E-4; - q=q*m1+5.94058303753167793257E-3; - q=q*m1+1.54850516649762399335E-2; - q=q*m1+2.39089602715924892727E-2; - q=q*m1+3.01204715227604046988E-2; - q=q*m1+3.73774314173823228969E-2; - q=q*m1+4.88280347570998239232E-2; - q=q*m1+7.03124996963957469739E-2; - q=q*m1+1.24999999999870820058E-1; - q=q*m1+4.99999999999999999821E-1; - //--- get result - result=p-q*MathLog(m1); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Incomplete elliptic integral of the first kind F(phi|m) | -//| Approximates the integral | -//| phi | -//| - | -//| | | | -//| | dt | -//| F(phi_\m) = | ------------------ | -//| | 2 | -//| | | sqrt( 1 - m sin t ) | -//| - | -//| 0 | -//| of amplitude phi and modulus m, using the arithmetic - | -//| geometric mean algorithm. | -//| ACCURACY: | -//| Tested at random points with m in [0, 1] and phi as indicated. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -10,10 200000 7.4e-16 1.0e-16 | -//+------------------------------------------------------------------+ -static double CElliptic::IncompleteEllipticIntegralK(double phi,const double m) - { -//--- create variables - double a=0; - double b=0; - double c=0; - double e=0; - double temp=0; - double pio2=0; - double t=0; - double k=0; - int d=0; - int md=0; - int s=0; - int npio2=0; -//--- initialization - pio2=1.57079632679489661923; -//--- check - if(m==0.0) - return(phi); -//--- initialization - a=1-m; -//--- check - if(a==0.0) - return(MathLog(MathTan(0.5*(pio2+phi)))); -//--- initialization - npio2=(int)MathFloor(phi/pio2); -//--- check - if(npio2%2!=0) - npio2=npio2+1; -//--- check - if(npio2!=0) - { - k=EllipticIntegralK(1-a); - phi=phi-npio2*pio2; - } - else - k=0; -//--- check - if(phi<0.0) - { - phi=-phi; - s=-1; - } - else - s=0; -//--- calculation - b=MathSqrt(a); - t=MathTan(phi); -//--- check - if(MathAbs(t)>10) - { - e=1.0/(b*t); - //--- check - if(MathAbs(e)<10) - { - e=MathArctan(e); - //--- check - if(npio2==0) - k=EllipticIntegralK(1-a); - //--- function call - temp=k-IncompleteEllipticIntegralK(e,m); - //--- check - if(s<0) - temp=-temp; - //--- return result - return(temp+npio2*k); - } - } -//--- change values - a=1.0; - c=MathSqrt(m); - d=1; - md=0; -//--- cycle - while(MathAbs(c/a)>CMath::m_machineepsilon) - { - //--- calculation - temp=b/a; - phi=phi+MathArctan(t*temp)+md*M_PI; - md=(int)((phi+pio2)/M_PI); - t=t*(1.0+temp)/(1.0-temp*t*t); - c=0.5*(a-b); - temp=MathSqrt(a*b); - a=0.5*(a+b); - b=temp; - d=d+d; - } -//--- change value - temp=(MathArctan(t)+md*M_PI)/(d*a); -//--- check - if(s<0) - temp=-temp; -//--- return result - return(temp+npio2*k); - } -//+------------------------------------------------------------------+ -//| Complete elliptic integral of the second kind | -//| Approximates the integral | -//| pi/2 | -//| - | -//| | | 2 | -//| E(m) = | sqrt( 1 - m sin t ) dt | -//| | | | -//| - | -//| 0 | -//| using the approximation | -//| P(x) - x log x Q(x). | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 1 10000 2.1e-16 7.3e-17 | -//+------------------------------------------------------------------+ -static double CElliptic::EllipticIntegralE(double m) - { -//--- create variables - double p=0; - double q=0; -//--- check - if(!CAp::Assert(m>=0.0 && m<=1.0,__FUNCTION__+": m<0 or m>1")) - return(EMPTY_VALUE); -//--- change value - m=1-m; -//--- check - if(m==0.0) - return(1); -//--- calculation - p=1.53552577301013293365E-4; - p=p*m+2.50888492163602060990E-3; - p=p*m+8.68786816565889628429E-3; - p=p*m+1.07350949056076193403E-2; - p=p*m+7.77395492516787092951E-3; - p=p*m+7.58395289413514708519E-3; - p=p*m+1.15688436810574127319E-2; - p=p*m+2.18317996015557253103E-2; - p=p*m+5.68051945617860553470E-2; - p=p*m+4.43147180560990850618E-1; - p=p*m+1.00000000000000000299E0; - q=3.27954898576485872656E-5; - q=q*m+1.00962792679356715133E-3; - q=q*m+6.50609489976927491433E-3; - q=q*m+1.68862163993311317300E-2; - q=q*m+2.61769742454493659583E-2; - q=q*m+3.34833904888224918614E-2; - q=q*m+4.27180926518931511717E-2; - q=q*m+5.85936634471101055642E-2; - q=q*m+9.37499997197644278445E-2; - q=q*m+2.49999999999888314361E-1; -//--- return result - return(p-q*m*MathLog(m)); - } -//+------------------------------------------------------------------+ -//| Incomplete elliptic integral of the second kind | -//| Approximates the integral | -//| phi | -//| - | -//| | | | -//| | 2 | -//| E(phi_\m) = | sqrt( 1 - m sin t ) dt | -//| | | -//| | | | -//| - | -//| 0 | -//| of amplitude phi and modulus m, using the arithmetic - | -//| geometric mean algorithm. | -//| ACCURACY: | -//| Tested at random arguments with phi in [-10, 10] and m in | -//| [0, 1]. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -10,10 150000 3.3e-15 1.4e-16 | -//+------------------------------------------------------------------+ -static double CElliptic::IncompleteEllipticIntegralE(const double phi, - const double m) - { -//--- create variables - double pio2=0; - double a=0; - double b=0; - double c=0; - double e=0; - double temp=0; - double lphi=0; - double t=0; - double ebig=0; - int d=0; - int md=0; - int npio2=0; - int s=0; -//--- initialization - pio2=1.57079632679489661923; -//--- check - if(m==0.0) - return(phi); -//--- change values - lphi=phi; - npio2=(int)MathFloor(lphi/pio2); -//--- check - if(npio2%2!=0) - npio2=npio2+1; - lphi=lphi-npio2*pio2; -//--- check - if(lphi<0.0) - { - lphi=-lphi; - s=-1; - } - else - s=1; -//--- change values - a=1.0-m; - ebig=EllipticIntegralE(m); -//--- check - if(a==0.0) - { - temp=MathSin(lphi); - //--- check - if(s<0) - temp=-temp; - //--- return result - return(temp+npio2*ebig); - } -//--- calculation - t=MathTan(lphi); - b=MathSqrt(a); -//--- Thanks to Brian Fitzgerald -//--- for pointing out an instability near odd multiples of pi/2 - if(MathAbs(t)>10) - { - //--- Transform the amplitude - e=1.0/(b*t); - //--- ... but avoid multiple recursions. - if(MathAbs(e)<10) - { - e=MathArctan(e); - temp=ebig+m*MathSin(lphi)*MathSin(e)-IncompleteEllipticIntegralE(e,m); - //--- check - if(s<0) - temp=-temp; - //--- return result - return(temp+npio2*ebig); - } - } -//--- change values - c=MathSqrt(m); - a=1.0; - d=1; - e=0.0; - md=0; -//--- cycle - while(MathAbs(c/a)>CMath::m_machineepsilon) - { - //--- calculation - temp=b/a; - lphi=lphi+MathArctan(t*temp)+md*M_PI; - md=(int)((lphi+pio2)/M_PI); - t=t*(1.0+temp)/(1.0-temp*t*t); - c=0.5*(a-b); - temp=MathSqrt(a*b); - a=0.5*(a+b); - b=temp; - d=d+d; - e=e+c*MathSin(lphi); - } -//--- change value - temp=ebig/EllipticIntegralK(m); - temp=temp*((MathArctan(t)+md*M_PI)/(d*a)); - temp=temp+e; -//--- check - if(s<0) - temp=-temp; -//--- return result - return(temp+npio2*ebig); - } -//+------------------------------------------------------------------+ -//| Exponential integral | -//+------------------------------------------------------------------+ -class CExpIntegrals - { -public: - //--- constructor, destructor - CExpIntegrals(void); - ~CExpIntegrals(void); - //--- methods - static double ExponentialIntegralEi(const double x); - static double ExponentialIntegralEn(const double x,const int n); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CExpIntegrals::CExpIntegrals(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CExpIntegrals::~CExpIntegrals(void) - { - - } -//+------------------------------------------------------------------+ -//| Exponential integral Ei(x) | -//| x | -//| - t | -//| | | e | -//| Ei(x) = -|- --- dt . | -//| | | t | -//| - | -//| -inf | -//| Not defined for x <= 0. | -//| See also expn.c. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0,100 50000 8.6e-16 1.3e-16 | -//+------------------------------------------------------------------+ -static double CExpIntegrals::ExponentialIntegralEi(const double x) - { -//--- create variables - double eul=0; - double f=0; - double f1=0; - double f2=0; - double w=0; -//--- initialization - eul=0.5772156649015328606065; -//--- check - if(x<=0.0) - return(0); -//--- check - if(x<2.0) - { - //--- calculation - f1=-5.350447357812542947283; - f1=f1*x+218.5049168816613393830; - f1=f1*x-4176.572384826693777058; - f1=f1*x+55411.76756393557601232; - f1=f1*x-331338.1331178144034309; - f1=f1*x+1592627.163384945414220; - f2=1.000000000000000000000; - f2=f2*x-52.50547959112862969197; - f2=f2*x+1259.616186786790571525; - f2=f2*x-17565.49581973534652631; - f2=f2*x+149306.2117002725991967; - f2=f2*x-729494.9239640527645655; - f2=f2*x+1592627.163384945429726; - f=f1/f2; - //--- return result - return(eul+MathLog(x)+x*f); - } -//--- check - if(x<4.0) - { - //--- calculation - w=1/x; - f1=1.981808503259689673238E-2; - f1=f1*w-1.271645625984917501326; - f1=f1*w-2.088160335681228318920; - f1=f1*w+2.755544509187936721172; - f1=f1*w-4.409507048701600257171E-1; - f1=f1*w+4.665623805935891391017E-2; - f1=f1*w-1.545042679673485262580E-3; - f1=f1*w+7.059980605299617478514E-5; - f2=1.000000000000000000000; - f2=f2*w+1.476498670914921440652; - f2=f2*w+5.629177174822436244827E-1; - f2=f2*w+1.699017897879307263248E-1; - f2=f2*w+2.291647179034212017463E-2; - f2=f2*w+4.450150439728752875043E-3; - f2=f2*w+1.727439612206521482874E-4; - f2=f2*w+3.953167195549672482304E-5; - f=f1/f2; - //--- return result - return(MathExp(x)*w*(1+w*f)); - } -//--- check - if(x<8.0) - { - //--- calculation - w=1/x; - f1=-1.373215375871208729803; - f1=f1*w-7.084559133740838761406E-1; - f1=f1*w+1.580806855547941010501; - f1=f1*w-2.601500427425622944234E-1; - f1=f1*w+2.994674694113713763365E-2; - f1=f1*w-1.038086040188744005513E-3; - f1=f1*w+4.371064420753005429514E-5; - f1=f1*w+2.141783679522602903795E-6; - f2=1.000000000000000000000; - f2=f2*w+8.585231423622028380768E-1; - f2=f2*w+4.483285822873995129957E-1; - f2=f2*w+7.687932158124475434091E-2; - f2=f2*w+2.449868241021887685904E-2; - f2=f2*w+8.832165941927796567926E-4; - f2=f2*w+4.590952299511353531215E-4; - f2=f2*w+-4.729848351866523044863E-6; - f2=f2*w+2.665195537390710170105E-6; - f=f1/f2; - //--- return result - return(MathExp(x)*w*(1+w*f)); - } -//--- check - if(x<16.0) - { - //--- calculation - w=1/x; - f1=-2.106934601691916512584; - f1=f1*w+1.732733869664688041885; - f1=f1*w-2.423619178935841904839E-1; - f1=f1*w+2.322724180937565842585E-2; - f1=f1*w+2.372880440493179832059E-4; - f1=f1*w-8.343219561192552752335E-5; - f1=f1*w+1.363408795605250394881E-5; - f1=f1*w-3.655412321999253963714E-7; - f1=f1*w+1.464941733975961318456E-8; - f1=f1*w+6.176407863710360207074E-10; - f2=1.000000000000000000000; - f2=f2*w-2.298062239901678075778E-1; - f2=f2*w+1.105077041474037862347E-1; - f2=f2*w-1.566542966630792353556E-2; - f2=f2*w+2.761106850817352773874E-3; - f2=f2*w-2.089148012284048449115E-4; - f2=f2*w+1.708528938807675304186E-5; - f2=f2*w-4.459311796356686423199E-7; - f2=f2*w+1.394634930353847498145E-8; - f2=f2*w+6.150865933977338354138E-10; - f=f1/f2; - //--- return result - return(MathExp(x)*w*(1+w*f)); - } -//--- check - if(x<32.0) - { - //--- calculation - w=1/x; - f1=-2.458119367674020323359E-1; - f1=f1*w-1.483382253322077687183E-1; - f1=f1*w+7.248291795735551591813E-2; - f1=f1*w-1.348315687380940523823E-2; - f1=f1*w+1.342775069788636972294E-3; - f1=f1*w-7.942465637159712264564E-5; - f1=f1*w+2.644179518984235952241E-6; - f1=f1*w-4.239473659313765177195E-8; - f2=1.000000000000000000000; - f2=f2*w-1.044225908443871106315E-1; - f2=f2*w-2.676453128101402655055E-1; - f2=f2*w+9.695000254621984627876E-2; - f2=f2*w-1.601745692712991078208E-2; - f2=f2*w+1.496414899205908021882E-3; - f2=f2*w-8.462452563778485013756E-5; - f2=f2*w+2.728938403476726394024E-6; - f2=f2*w-4.239462431819542051337E-8; - f=f1/f2; - //--- return result - return(MathExp(x)*w*(1+w*f)); - } -//--- check - if(x<64) - { - //--- calculation - w=1/x; - f1=1.212561118105456670844E-1; - f1=f1*w-5.823133179043894485122E-1; - f1=f1*w+2.348887314557016779211E-1; - f1=f1*w-3.040034318113248237280E-2; - f1=f1*w+1.510082146865190661777E-3; - f1=f1*w-2.523137095499571377122E-5; - f2=1.000000000000000000000; - f2=f2*w-1.002252150365854016662; - f2=f2*w+2.928709694872224144953E-1; - f2=f2*w-3.337004338674007801307E-2; - f2=f2*w+1.560544881127388842819E-3; - f2=f2*w-2.523137093603234562648E-5; - f=f1/f2; - //--- return result - return(MathExp(x)*w*(1+w*f)); - } -//--- calculation - w=1/x; - f1=-7.657847078286127362028E-1; - f1=f1*w+6.886192415566705051750E-1; - f1=f1*w-2.132598113545206124553E-1; - f1=f1*w+3.346107552384193813594E-2; - f1=f1*w-3.076541477344756050249E-3; - f1=f1*w+1.747119316454907477380E-4; - f1=f1*w-6.103711682274170530369E-6; - f1=f1*w+1.218032765428652199087E-7; - f1=f1*w-1.086076102793290233007E-9; - f2=1.000000000000000000000; - f2=f2*w-1.888802868662308731041; - f2=f2*w+1.066691687211408896850; - f2=f2*w-2.751915982306380647738E-1; - f2=f2*w+3.930852688233823569726E-2; - f2=f2*w-3.414684558602365085394E-3; - f2=f2*w+1.866844370703555398195E-4; - f2=f2*w-6.345146083130515357861E-6; - f2=f2*w+1.239754287483206878024E-7; - f2=f2*w-1.086076102793126632978E-9; - f=f1/f2; -//--- return result - return(MathExp(x)*w*(1+w*f)); - } -//+------------------------------------------------------------------+ -//| Exponential integral En(x) | -//| Evaluates the exponential integral | -//| inf. | -//| - | -//| | | -xt | -//| | e | -//| E (x) = | ---- dt. | -//| n | n | -//| | | t | -//| - | -//| 1 | -//| Both n and x must be nonnegative. | -//| The routine employs either a power series, a continued | -//| fraction, or an asymptotic formula depending on the | -//| relative values of n and x. | -//| ACCURACY: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE 0, 30 10000 1.7e-15 3.6e-16 | -//+------------------------------------------------------------------+ -static double CExpIntegrals::ExponentialIntegralEn(const double x,const int n) - { -//--- create variables - double result=0; - double r=0; - double t=0; - double yk=0; - double xk=0; - double pk=0; - double pkm1=0; - double pkm2=0; - double qk=0; - double qkm1=0; - double qkm2=0; - double psi=0; - double z=0; - int i=0; - int k=0; - double big=0; - double eul=0; -//--- initialization - eul=0.57721566490153286060; - big=1.44115188075855872*MathPow(10,17); -//--- check - if(((n<0 || x<0.0) || x>170) || (x==0.0 && n<2)) - return(-1); -//--- check - if(x==0.0) - return(1.0/(double)(n-1)); -//--- check - if(n==0) - return(MathExp(-x)/x); -//--- check - if(n>5000) - { - //--- calculation - xk=x+n; - yk=1/(xk*xk); - t=n; - result=yk*t*(6*x*x-8*t*x+t*t); - result=yk*(result+t*(t-2.0*x)); - result=yk*(result+t); - result=(result+1)*MathExp(-x)/xk; - //--- return result - return(result); - } -//--- check - if(x<=1.0) - { - //--- calculation - psi=-eul-MathLog(x); - for(i=1;i<=n-1;i++) - psi=psi+1.0/(double)i; - z=-x; - xk=0; - yk=1; - pk=1-n; - //--- check - if(n==1) - result=0.0; - else - result=1.0/pk; - do - { - //--- change values - xk=xk+1; - yk=yk*z/xk; - pk=pk+1; - //--- check - if(pk!=0.0) - result=result+yk/pk; - //--- check - if(result!=0.0) - t=MathAbs(yk/result); - else - t=1; - } - while(t>=CMath::m_machineepsilon); - t=1; - for(i=1;i<=n-1;i++) - t=t*z/i; - //--- return result - return(psi*t-result); - } - else - { - //--- calculation - k=1; - pkm2=1; - qkm2=x; - pkm1=1.0; - qkm1=x+n; - result=pkm1/qkm1; - do - { - k=k+1; - //--- check - if(k%2==1) - { - yk=1; - xk=n+(double)(k-1)/2.0; - } - else - { - yk=x; - xk=(double)k/2.0; - } - //--- change values - pk=pkm1*yk+pkm2*xk; - qk=qkm1*yk+qkm2*xk; - //--- check - if(qk!=0.0) - { - r=pk/qk; - t=MathAbs((result-r)/r); - result=r; - } - else - t=1; - //--- change values - pkm2=pkm1; - pkm1=pk; - qkm2=qkm1; - qkm1=qk; - //--- check - if(MathAbs(pk)>big) - { - //--- change values - pkm2=pkm2/big; - pkm1=pkm1/big; - qkm2=qkm2/big; - qkm1=qkm1/big; - } - } - while(t>=CMath::m_machineepsilon); - result=result*MathExp(-x); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| F distribution | -//+------------------------------------------------------------------+ -class CFDistr - { -public: - //--- constructor, destructor - CFDistr(void); - ~CFDistr(void); - //--- methods - static double FDistribution(const int a,const int b,const double x); - static double FComplDistribution(const int a,const int b,const double x); - static double InvFDistribution(const int a,const int b,const double y); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFDistr::CFDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFDistr::~CFDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| F distribution | -//| Returns the area from zero to x under the F density | -//| function (also known as Snedcor's density or the | -//| variance ratio density). This is the density | -//| of x = (u1/df1)/(u2/df2), where u1 and u2 are random | -//| variables having Chi square distributions with df1 | -//| and df2 degrees of freedom, respectively. | -//| The incomplete beta integral is used, according to the | -//| formula | -//| P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). | -//| The arguments a and b are greater than zero, and x is | -//| nonnegative. | -//| ACCURACY: | -//| Tested at random points (a,b,x). | -//| x a,b Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 | -//| IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 | -//| IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 | -//| IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 | -//+------------------------------------------------------------------+ -static double CFDistr::FDistribution(const int a,const int b,const double x) - { -//--- check - if(!CAp::Assert(a>=1 && b>=1 && x>=0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- create a variable - double w=0; -//--- calculation - w=a*x; - w/=b+w; -//--- return result - return(CIncBetaF::IncompleteBeta(0.5*a,0.5*b,w)); - } -//+------------------------------------------------------------------+ -//| Complemented F distribution | -//| Returns the area from x to infinity under the F density | -//| function (also known as Snedcor's density or the | -//| variance ratio density). | -//| inf. | -//| - | -//| 1 | | a-1 b-1 | -//| 1-P(x) = ------ | t (1-t) dt | -//| B(a,b) | | | -//| - | -//| x | -//| The incomplete beta integral is used, according to the | -//| formula | -//| P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). | -//| ACCURACY: | -//| Tested at random points (a,b,x) in the indicated intervals. | -//| x a,b Relative error: | -//| arithmetic domain domain # trials peak rms | -//| IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 | -//| IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 | -//| IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 | -//| IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 | -//+------------------------------------------------------------------+ -static double CFDistr::FComplDistribution(const int a,const int b,const double x) - { -//--- create a variable - double w=0; -//--- check - if(!CAp::Assert((a>=1 && b>=1) && x>=0.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- calculation - w=b/(b+a*x); -//--- return result - return(CIncBetaF::IncompleteBeta(0.5*b,0.5*a,w)); - } -//+------------------------------------------------------------------+ -//| Inverse of complemented F distribution | -//| Finds the F density argument x such that the integral | -//| from x to infinity of the F density is equal to the | -//| given probability p. | -//| This is accomplished using the inverse beta integral | -//| function and the relations | -//| z = incbi( df2/2, df1/2, p ) | -//| x = df2 (1-z) / (df1 z). | -//| Note: the following relations hold for the inverse of | -//| the uncomplemented F distribution: | -//| z = incbi( df1/2, df2/2, p ) | -//| x = df2 z / (df1 (1-z)). | -//| ACCURACY: | -//| Tested at random points (a,b,p). | -//| a,b Relative error: | -//| arithmetic domain # trials peak rms | -//| For p between .001 and 1: | -//| IEEE 1,100 100000 8.3e-15 4.7e-16 | -//| IEEE 1,10000 100000 2.1e-11 1.4e-13 | -//| For p between 10^-6 and 10^-3: | -//| IEEE 1,100 50000 1.3e-12 8.4e-15 | -//| IEEE 1,10000 50000 3.0e-12 4.8e-14 | -//+------------------------------------------------------------------+ -static double CFDistr::InvFDistribution(const int a,const int b,const double y) - { -//--- create variables - double result=0; - double w=0; -//--- check - if(!CAp::Assert(((a>=1 && b>=1) && y>0.0) && y<=1.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- Compute probability for x=0.5 - w=CIncBetaF::IncompleteBeta(0.5*b,0.5*a,0.5); -//--- If that is greater than y,then the solution w < .5 -//--- Otherwise,solve at 1-y to remove cancellation in (b - b*w) - if(w>y || y<0.001) - { - //--- calculation - w=CIncBetaF::InvIncompleteBeta(0.5*b,0.5*a,y); - result=(b-b*w)/(a*w); - } - else - { - //--- calculation - w=CIncBetaF::InvIncompleteBeta(0.5*a,0.5*b,1.0-y); - result=b*w/(a*(1.0-w)); - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Fresnel integral | -//+------------------------------------------------------------------+ -class CFresnel - { -public: - //--- constructor, destructor - CFresnel(void); - ~CFresnel(void); - //--- method - static void FresnelIntegral(double x,double &c,double &s); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CFresnel::CFresnel(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFresnel::~CFresnel(void) - { - - } -//+------------------------------------------------------------------+ -//| Fresnel integral | -//| Evaluates the Fresnel integrals | -//| x | -//| - | -//| | | | -//| C(x) = | cos(pi/2 t**2) dt, | -//| | | | -//| - | -//| 0 | -//| x | -//| - | -//| | | | -//| S(x) = | sin(pi/2 t**2) dt. | -//| | | | -//| - | -//| 0 | -//| The integrals are evaluated by a power series for x < 1. | -//| For x >= 1 auxiliary functions f(x) and g(x) are employed | -//| such that | -//| C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) | -//| S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) | -//| ACCURACY: | -//| Relative error. | -//| Arithmetic function domain # trials peak rms | -//| IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16| -//| IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16| -//+------------------------------------------------------------------+ -static void CFresnel::FresnelIntegral(double x,double &c,double &s) - { -//--- create variables - double xxa=0; - double f=0; - double g=0; - double cc=0; - double ss=0; - double t=0; - double u=0; - double x2=0; - double sn=0; - double sd=0; - double cn=0; - double cd=0; - double fn=0; - double fd=0; - double gn=0; - double gd=0; - double mpi=0; - double mpio2=0; -//--- initialization - mpi=3.14159265358979323846; - mpio2=1.57079632679489661923; - xxa=x; - x=MathAbs(xxa); - x2=x*x; -//--- check - if(x2<2.5625) - { - //--- calculation - t=x2*x2; - sn=-2.99181919401019853726E3; - sn=sn*t+7.08840045257738576863E5; - sn=sn*t-6.29741486205862506537E7; - sn=sn*t+2.54890880573376359104E9; - sn=sn*t-4.42979518059697779103E10; - sn=sn*t+3.18016297876567817986E11; - sd=1.00000000000000000000E0; - sd=sd*t+2.81376268889994315696E2; - sd=sd*t+4.55847810806532581675E4; - sd=sd*t+5.17343888770096400730E6; - sd=sd*t+4.19320245898111231129E8; - sd=sd*t+2.24411795645340920940E10; - sd=sd*t+6.07366389490084639049E11; - cn=-4.98843114573573548651E-8; - cn=cn*t+9.50428062829859605134E-6; - cn=cn*t-6.45191435683965050962E-4; - cn=cn*t+1.88843319396703850064E-2; - cn=cn*t-2.05525900955013891793E-1; - cn=cn*t+9.99999999999999998822E-1; - cd=3.99982968972495980367E-12; - cd=cd*t+9.15439215774657478799E-10; - cd=cd*t+1.25001862479598821474E-7; - cd=cd*t+1.22262789024179030997E-5; - cd=cd*t+8.68029542941784300606E-4; - cd=cd*t+4.12142090722199792936E-2; - cd=cd*t+1.00000000000000000118E0; - s=MathSign(xxa)*x*x2*sn/sd; - c=MathSign(xxa)*x*cn/cd; - //--- exit the function - return; - } -//--- check - if(x>36974.0) - { - //--- calculation - c=MathSign(xxa)*0.5; - s=MathSign(xxa)*0.5; - //--- exit the function - return; - } -//--- calculation - x2=x*x; - t=mpi*x2; - u=1/(t*t); - t=1/t; - fn=4.21543555043677546506E-1; - fn=fn*u+1.43407919780758885261E-1; - fn=fn*u+1.15220955073585758835E-2; - fn=fn*u+3.45017939782574027900E-4; - fn=fn*u+4.63613749287867322088E-6; - fn=fn*u+3.05568983790257605827E-8; - fn=fn*u+1.02304514164907233465E-10; - fn=fn*u+1.72010743268161828879E-13; - fn=fn*u+1.34283276233062758925E-16; - fn=fn*u+3.76329711269987889006E-20; - fd=1.00000000000000000000E0; - fd=fd*u+7.51586398353378947175E-1; - fd=fd*u+1.16888925859191382142E-1; - fd=fd*u+6.44051526508858611005E-3; - fd=fd*u+1.55934409164153020873E-4; - fd=fd*u+1.84627567348930545870E-6; - fd=fd*u+1.12699224763999035261E-8; - fd=fd*u+3.60140029589371370404E-11; - fd=fd*u+5.88754533621578410010E-14; - fd=fd*u+4.52001434074129701496E-17; - fd=fd*u+1.25443237090011264384E-20; - gn=5.04442073643383265887E-1; - gn=gn*u+1.97102833525523411709E-1; - gn=gn*u+1.87648584092575249293E-2; - gn=gn*u+6.84079380915393090172E-4; - gn=gn*u+1.15138826111884280931E-5; - gn=gn*u+9.82852443688422223854E-8; - gn=gn*u+4.45344415861750144738E-10; - gn=gn*u+1.08268041139020870318E-12; - gn=gn*u+1.37555460633261799868E-15; - gn=gn*u+8.36354435630677421531E-19; - gn=gn*u+1.86958710162783235106E-22; - gd=1.00000000000000000000E0; - gd=gd*u+1.47495759925128324529E0; - gd=gd*u+3.37748989120019970451E-1; - gd=gd*u+2.53603741420338795122E-2; - gd=gd*u+8.14679107184306179049E-4; - gd=gd*u+1.27545075667729118702E-5; - gd=gd*u+1.04314589657571990585E-7; - gd=gd*u+4.60680728146520428211E-10; - gd=gd*u+1.10273215066240270757E-12; - gd=gd*u+1.38796531259578871258E-15; - gd=gd*u+8.39158816283118707363E-19; - gd=gd*u+1.86958710162783236342E-22; -//--- get result - f=1-u*fn/fd; - g=t*gn/gd; - t=mpio2*x2; - cc=MathCos(t); - ss=MathSin(t); - t=mpi*x; - c=0.5+(f*ss-g*cc)/t; - s=0.5-(f*cc+g*ss)/t; - c=c*MathSign(xxa); - s=s*MathSign(xxa); - } -//+------------------------------------------------------------------+ -//| Hermite polynomial | -//+------------------------------------------------------------------+ -class CHermite - { -public: - //--- constructor, destructor - CHermite(void); - ~CHermite(void); - //--- methods - static double HermiteCalculate(const int n,const double x); - static double HermiteSum(double &c[],const int n,const double x); - static void HermiteCoefficients(const int n,double &c[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CHermite::CHermite(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CHermite::~CHermite(void) - { - - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Hermite polynomial. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Hermite polynomial Hn at x | -//+------------------------------------------------------------------+ -static double CHermite::HermiteCalculate(const int n,const double x) - { -//--- create variables - double result=0; - int i=0; - double a=0; - double b=0; -//--- Prepare A and B - a=1; - b=2*x; -//--- Special cases: N=0 or N=1 - if(n==0) - return(a); -//--- check - if(n==1) - return(b); -//--- General case: N>=2 - for(i=2;i<=n;i++) - { - result=2*x*b-2*(i-1)*a; - a=b; - b=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Summation of Hermite polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Hermite polynomial at x | -//+------------------------------------------------------------------+ -static double CHermite::HermiteSum(double &c[],const int n,const double x) - { -//--- create variables - double result=0; - double b1=0; - double b2=0; - int i=0; -//--- initialization - b1=0; - b2=0; -//--- calculation - for(i=n;i>=0;i--) - { - result=2*(x*b1-(i+1)*b2)+c[i]; - b2=b1; - b1=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CHermite::HermiteCoefficients(const int n,double &c[]) - { -//--- create a variable - int i=0; -//--- allocation - ArrayResizeAL(c,n+1); -//--- initialization - for(i=0;i<=n;i++) - c[i]=0; -//--- calculation - c[n]=MathExp(n*MathLog(2)); - for(i=0;i<=n/2-1;i++) - c[n-2*(i+1)]=-(c[n-2*i]*(n-2*i)*(n-2*i-1)/4/(i+1)); - } -//+------------------------------------------------------------------+ -//| Jacobian elliptic functions | -//+------------------------------------------------------------------+ -class CJacobianElliptic - { -public: - //--- constructor, destructor - CJacobianElliptic(void); - ~CJacobianElliptic(void); - //--- method - static void JacobianEllipticFunctions(const double u,const double m,double &sn,double &cn,double &dn,double &ph); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CJacobianElliptic::CJacobianElliptic(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CJacobianElliptic::~CJacobianElliptic(void) - { - - } -//+------------------------------------------------------------------+ -//| Jacobian Elliptic Functions | -//| Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), | -//| and dn(u|m) of parameter m between 0 and 1, and real | -//| argument u. | -//| These functions are periodic, with quarter-period on the | -//| real axis equal to the complete elliptic integral | -//| ellpk(1.0-m). | -//| Relation to incomplete elliptic integral: | -//| If u = ellik(phi,m), then sn(u|m) = sin(phi), | -//| and cn(u|m) = cos(phi). Phi is called the amplitude of u. | -//| Computation is by means of the arithmetic-geometric mean | -//| algorithm, except when m is within 1e-9 of 0 or 1. In the | -//| latter case with m close to 1, the approximation applies | -//| only for phi < pi/2. | -//| ACCURACY: | -//| Tested at random points with u between 0 and 10, m between | -//| 0 and 1. | -//| Absolute error (* = relative error): | -//| arithmetic function # trials peak rms | -//| IEEE phi 10000 9.2e-16* 1.4e-16* | -//| IEEE sn 50000 4.1e-15 4.6e-16 | -//| IEEE cn 40000 3.6e-15 4.4e-16 | -//| IEEE dn 10000 1.3e-12 1.8e-14 | -//| Peak error observed in consistency check using addition | -//| theorem for sn(u+v) was 4e-16 (absolute). Also tested by | -//| the above relation to the incomplete elliptic integral. | -//| Accuracy deteriorates when u is large. | -//+------------------------------------------------------------------+ -static void CJacobianElliptic::JacobianEllipticFunctions(const double u, - const double m, - double &sn,double &cn, - double &dn,double &ph) - { -//--- create variables - double ai=0; - double b=0; - double phi=0; - double t=0; - double twon=0; - int i=0; -//--- create arrays - double a[]; - double c[]; -//--- initialization - sn=0; - cn=0; - dn=0; - ph=0; -//--- check - if(!CAp::Assert(m>=0.0 && m<=1.0,__FUNCTION__+": m<0 or m>1")) - return; -//--- allocation - ArrayResizeAL(a,9); - ArrayResizeAL(c,9); -//--- check - if(m<1.0e-9) - { - //--- calculation - t=MathSin(u); - b=MathCos(u); - ai=0.25*m*(u-t*b); - sn=t-ai*b; - cn=b+ai*t; - ph=u-ai; - dn=1.0-0.5*m*t*t; - //--- exit the function - return; - } -//--- check - if(m>=0.9999999999) - { - //--- calculation - ai=0.25*(1.0-m); - b=MathCosh(u); - t=MathTanh(u); - phi=1.0/b; - twon=b*MathSinh(u); - sn=t+ai*(twon-u)/(b*b); - ph=2.0*MathArctan(MathExp(u))-1.57079632679489661923+ai*(twon-u)/b; - ai=ai*t*phi; - cn=phi-ai*(twon-u); - dn=phi+ai*(twon+u); - //--- exit the function - return; - } -//--- change values - a[0]=1.0; - b=MathSqrt(1.0-m); - c[0]=MathSqrt(m); - twon=1.0; - i=0; -//--- cycle - while(MathAbs(c[i]/a[i])>CMath::m_machineepsilon) - { - //--- check - if(i>7) - { - //--- check - if(!CAp::Assert(false,__FUNCTION__+": overflow")) - return; - //--- break the cycle - break; - } - //--- calculation - ai=a[i]; - i=i+1; - c[i]=0.5*(ai-b); - t=MathSqrt(ai*b); - a[i]=0.5*(ai+b); - b=t; - twon=twon*2.0; - } - phi=twon*a[i]*u; -//--- cycle - do - { - //--- calculation - t=c[i]*MathSin(phi)/a[i]; - b=phi; - phi=(MathArcsin(t)+phi)/2.0; - i=i-1; - } - while(i!=0); -//--- get result - sn=MathSin(phi); - t=MathCos(phi); - cn=t; - dn=t/MathCos(phi-b); - ph=phi; - } -//+------------------------------------------------------------------+ -//| Laguerre polynomial | -//+------------------------------------------------------------------+ -class CLaguerre - { -public: - //--- constructor, destructor - CLaguerre(void); - ~CLaguerre(void); - //--- methods - static double LaguerreCalculate(const int n,const double x); - static double LaguerreSum(double &c[],const int n,const double x); - static void LaguerreCoefficients(const int n,double &c[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLaguerre::CLaguerre(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLaguerre::~CLaguerre(void) - { - - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Laguerre polynomial. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Laguerre polynomial Ln at x | -//+------------------------------------------------------------------+ -static double CLaguerre::LaguerreCalculate(const int n,const double x) - { -//--- create variables - double result=0; - double a=0; - double b=0; - double i=0; -//--- initialization - result=1; - a=1; - b=1-x; -//--- check - if(n==1) - result=b; -//--- initialization - i=2; -//--- cycle - while(i<=n) - { - //--- calculation - result=((2*i-1-x)*b-(i-1)*a)/i; - a=b; - b=result; - i=i+1; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Summation of Laguerre polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + | -//| + c[N]*LN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Laguerre polynomial at x | -//+------------------------------------------------------------------+ -static double CLaguerre::LaguerreSum(double &c[],const int n,const double x) - { -//--- create variables - double result=0; - double b1=0; - double b2=0; - int i=0; -//--- initialization - b1=0; - b2=0; - result=0; -//--- calculation - for(i=n;i>=0;i--) - { - result=(2*i+1-x)*b1/(i+1)-(i+1)*b2/(i+2)+c[i]; - b2=b1; - b1=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CLaguerre::LaguerreCoefficients(const int n,double &c[]) - { -//--- create a variable - int i=0; -//--- allocation - ArrayResizeAL(c,n+1); -//--- initialization - c[0]=1; -//--- calculation - for(i=0;i<=n-1;i++) - c[i+1]=-(c[i]*(n-i)/(i+1)/(i+1)); - } -//+------------------------------------------------------------------+ -//| Legendre polynomial | -//+------------------------------------------------------------------+ -class CLegendre - { -public: - //--- constructor, destructor - CLegendre(void); - ~CLegendre(void); - //--- methods - static double LegendreCalculate(const int n,const double x); - static double LegendreSum(double &c[],const int n,const double x); - static void LegendreCoefficients(const int n,double &c[]); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CLegendre::CLegendre(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLegendre::~CLegendre(void) - { - - } -//+------------------------------------------------------------------+ -//| Calculation of the value of the Legendre polynomial Pn. | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Legendre polynomial Pn at x | -//+------------------------------------------------------------------+ -static double CLegendre::LegendreCalculate(const int n,const double x) - { -//--- create variables - double result=0; - double a=0; - double b=0; - int i=0; -//--- initialization - result=1; - a=1; - b=x; -//--- check - if(n==0) - return(a); -//--- check - if(n==1) - return(b); -//--- calculation - for(i=2;i<=n;i++) - { - result=((2*i-1)*x*b-(i-1)*a)/i; - a=b; - b=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Summation of Legendre polynomials using Clenshaw?s recurrence | -//| formula. | -//| This routine calculates | -//| c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) | -//| Parameters: | -//| n - degree, n>=0 | -//| x - argument | -//| Result: | -//| the value of the Legendre polynomial at x | -//+------------------------------------------------------------------+ -static double CLegendre::LegendreSum(double &c[],const int n,const double x) - { -//--- create variables - double result=0; - double b1=0; - double b2=0; - int i=0; -//--- initialization - b1=0; - b2=0; - result=0; -//--- calculation - for(i=n;i>=0;i--) - { - result=(2*i+1)*x*b1/(i+1)-(i+1)*b2/(i+2)+c[i]; - b2=b1; - b1=result; - } -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N | -//| Input parameters: | -//| N - polynomial degree, n>=0 | -//| Output parameters: | -//| C - coefficients | -//+------------------------------------------------------------------+ -static void CLegendre::LegendreCoefficients(const int n,double &c[]) - { -//--- create a variable - int i=0; -//--- allocation - ArrayResizeAL(c,n+1); -//--- initialization - for(i=0;i<=n;i++) - c[i]=0; - c[n]=1; -//--- calculation - for(i=1;i<=n;i++) - c[n]=c[n]*(n+i)/2/i; - for(i=0;i<=n/2-1;i++) - c[n-2*(i+1)]=-(c[n-2*i]*(n-2*i)*(n-2*i-1)/2/(i+1)/(2*(n-i)-1)); - } -//+------------------------------------------------------------------+ -//| Poisson distribution | -//+------------------------------------------------------------------+ -class CPoissonDistr - { -public: - //--- constructor, destructor - CPoissonDistr(void); - ~CPoissonDistr(void); - //--- methods - static double PoissonDistribution(const int k,const double m); - static double PoissonComplDistribution(const int k,const double m); - static double InvPoissonDistribution(const int k,const double y); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPoissonDistr::CPoissonDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPoissonDistr::~CPoissonDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Poisson distribution | -//| Returns the sum of the first k+1 terms of the Poisson | -//| distribution: | -//| k j | -//| -- -m m | -//| > e -- | -//| -- j! | -//| j=0 | -//| The terms are not summed directly; instead the incomplete | -//| gamma integral is employed, according to the relation | -//| y = pdtr( k, m ) = igamc( k+1, m ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CPoissonDistr::PoissonDistribution(const int k,const double m) - { -//--- check - if(!CAp::Assert(k>=0 && m>0.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- return result - return(CIncGammaF::IncompleteGammaC(k+1,m)); - } -//+------------------------------------------------------------------+ -//| Complemented Poisson distribution | -//| Returns the sum of the terms k+1 to infinity of the Poisson | -//| distribution: | -//| inf. j | -//| -- -m m | -//| > e -- | -//| -- j! | -//| j=k+1 | -//| The terms are not summed directly; instead the incomplete | -//| gamma integral is employed, according to the formula | -//| y = pdtrc( k, m ) = igam( k+1, m ). | -//| The arguments must both be positive. | -//| ACCURACY: | -//| See incomplete gamma function | -//+------------------------------------------------------------------+ -static double CPoissonDistr::PoissonComplDistribution(const int k,const double m) - { -//--- check - if(!CAp::Assert(k>=0 && m>0.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- return result - return(CIncGammaF::IncompleteGamma(k+1,m)); - } -//+------------------------------------------------------------------+ -//| Inverse Poisson distribution | -//| Finds the Poisson variable x such that the integral | -//| from 0 to x of the Poisson density is equal to the | -//| given probability y. | -//| This is accomplished using the inverse gamma integral | -//| function and the relation | -//| m = igami( k+1, y ). | -//| ACCURACY: | -//| See inverse incomplete gamma function | -//+------------------------------------------------------------------+ -static double CPoissonDistr::InvPoissonDistribution(const int k,const double y) - { -//--- check - if(!CAp::Assert((k>=0 && y>=0.0) && y<1.0,__FUNCTION__+": domain error")) - return(EMPTY_VALUE); -//--- return result - return(CIncGammaF::InvIncompleteGammaC(k+1,y)); - } -//+------------------------------------------------------------------+ -//| Psi function | -//+------------------------------------------------------------------+ -class CPsiF - { -public: - //--- constructor, destructor - CPsiF(void); - ~CPsiF(void); - //--- method - static double Psi(double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CPsiF::CPsiF(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPsiF::~CPsiF(void) - { - - } -//+------------------------------------------------------------------+ -//| Psi (digamma) function | -//| d - | -//| psi(x) = -- ln | (x) | -//| dx | -//| is the logarithmic derivative of the gamma function. | -//| For integer x, | -//| n-1 | -//| - | -//| psi(n) = -EUL + > 1/k. | -//| - | -//| k=1 | -//| This formula is used for 0 < n <= 10. If x is negative, it | -//| is transformed to a positive argument by the reflection | -//| formula psi(1-x) = psi(x) + pi cot(pi x). | -//| For general positive x, the argument is made greater than 10 | -//| using the recurrence psi(x+1) = psi(x) + 1/x. | -//| Then the following asymptotic expansion is applied: | -//| inf. B | -//| - 2k | -//| psi(x) = log(x) - 1/2x - > ------- | -//| - 2k | -//| k=1 2k x | -//| where the B2k are Bernoulli numbers. | -//| ACCURACY: | -//| Relative error (except absolute when |psi| < 1): | -//| arithmetic domain # trials peak rms | -//| IEEE 0,30 30000 1.3e-15 1.4e-16 | -//| IEEE -30,0 40000 1.5e-15 2.2e-16 | -//+------------------------------------------------------------------+ -static double CPsiF::Psi(double x) - { -//--- create variables - double result=0; - double p=0; - double q=0; - double nz=0; - double s=0; - double w=0; - double y=0; - double z=0; - double polv=0; - int i=0; - int n=0; - int negative=0; -//--- initialization - negative=0; - nz=0.0; -//--- check - if(x<=0.0) - { - negative=1; - q=x; - p=(int)MathFloor(q); - //--- check - if(p==q) - { - //--- check - if(!CAp::Assert(false,__FUNCTION__+": singularity in Psi(x)")) - return(EMPTY_VALUE); - //--- return result - return(CMath::m_maxrealnumber); - } - nz=q-p; - //--- check - if(nz!=0.5) - { - //--- check - if(nz>0.5) - { - p=p+1.0; - nz=q-p; - } - //--- change value - nz=M_PI/MathTan(M_PI*nz); - } - else - nz=0.0; - x=1.0-x; - } -//--- check - if(x<=10.0 && x==(double)((int)MathFloor(x))) - { - y=0.0; - n=(int)MathFloor(x); - //--- calculation - for(i=1;i<=n-1;i++) - { - w=i; - y=y+1.0/w; - } - y=y-0.57721566490153286061; - } - else - { - //--- change values - s=x; - w=0.0; - //--- cycle - while(s<10.0) - { - w=w+1.0/s; - s=s+1.0; - } - //--- check - if(s<1.0E17) - { - //--- calculation - z=1.0/(s*s); - polv=8.33333333333333333333E-2; - polv=polv*z-2.10927960927960927961E-2; - polv=polv*z+7.57575757575757575758E-3; - polv=polv*z-4.16666666666666666667E-3; - polv=polv*z+3.96825396825396825397E-3; - polv=polv*z-8.33333333333333333333E-3; - polv=polv*z+8.33333333333333333333E-2; - y=z*polv; - } - else - y=0.0; - //--- change value - y=MathLog(s)-0.5/s-y-w; - } -//--- check - if(negative!=0) - y=y-nz; -//--- return result - return(y); - } -//+------------------------------------------------------------------+ -//| Student's t distribution | -//+------------------------------------------------------------------+ -class CStudenttDistr - { -public: - //--- constructor, destructor - CStudenttDistr(void); - ~CStudenttDistr(void); - //--- methods - static double StudenttDistribution(const int k,const double t); - static double InvStudenttDistribution(const int k,double p); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CStudenttDistr::CStudenttDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CStudenttDistr::~CStudenttDistr(void) - { - - } -//+------------------------------------------------------------------+ -//| Student's t distribution | -//| Computes the integral from minus infinity to t of the Student | -//| t distribution with integer k > 0 degrees of freedom: | -//| t | -//| - | -//| | | | -//| - | 2 -(k+1)/2 | -//| | ( (k+1)/2 ) | ( x ) | -//| ---------------------- | ( 1 + --- ) dx | -//| - | ( k ) | -//| sqrt( k pi ) | ( k/2 ) | | -//| | | | -//| - | -//| -inf. | -//| Relation to incomplete beta integral: | -//| 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) | -//| where | -//| z = k/(k + t**2). | -//| For t < -2, this is the method of computation. For higher t, | -//| a direct method is derived from integration by parts. | -//| Since the function is symmetric about t=0, the area under the | -//| right tail of the density is found by calling the function | -//| with -t instead of t. | -//| ACCURACY: | -//| Tested at random 1 <= k <= 25. The "domain" refers to t. | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE -100,-2 50000 5.9e-15 1.4e-15 | -//| IEEE -2,100 500000 2.7e-15 4.9e-17 | -//+------------------------------------------------------------------+ -static double CStudenttDistr::StudenttDistribution(const int k,const double t) - { -//--- check - if(!CAp::Assert(k>0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(t==0) - return(0.5); -//--- create variables - double x=0; - double rk=0; - double z=0; - double f=0; - double tz=0; - double p=0; - double xsqk=0; - int j=0; -//--- check - if(t<-2.0) - { - rk=k; - z=rk/(rk+t*t); - //--- return result - return(0.5*CIncBetaF::IncompleteBeta(0.5*rk,0.5,z)); - } -//--- check - if(t<0) - x=-t; - else - x=t; -//--- change values - rk=k; - z=1.0+x*x/rk; -//--- check - if(k%2!=0) - { - xsqk=x/MathSqrt(rk); - p=MathArctan(xsqk); - //--- check - if(k>1) - { - f=1.0; - tz=1.0; - j=3; - //--- cycle - while(jCMath::m_machineepsilon) - { - //--- calculation - tz*=(j-1)/(z*j); - f+=tz; - j+=2; - } - p+=f*xsqk/z; - } - p*=2.0/M_PI; - } - else - { - f=1.0; - tz=1.0; - j=2; - //--- cycle - while(jCMath::m_machineepsilon) - { - //--- calculation - tz*=(j-1)/(z*j); - f+=tz; - j+=2; - } - p=f*x/MathSqrt(z*rk); - } -//--- check - if(t<0) - p=-p; -//--- return result - return(0.5+0.5*p); - } -//+------------------------------------------------------------------+ -//| Functional inverse of Student's t distribution | -//| Given probability p, finds the argument t such that stdtr(k,t) | -//| is equal to p. | -//| ACCURACY: | -//| Tested at random 1 <= k <= 100. The "domain" refers to p: | -//| Relative error: | -//| arithmetic domain # trials peak rms | -//| IEEE .001,.999 25000 5.7e-15 8.0e-16 | -//| IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 | -//+------------------------------------------------------------------+ -static double CStudenttDistr::InvStudenttDistribution(const int k,double p) - { -//--- create variables - double t=0; - double rk=k; - double z=0; - int rflg=0; - CIncBetaF ibetaf; -//--- check - if(!CAp::Assert(k>0 && p>0 && p<1,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(p>0.25 && p<0.75) - { - //--- check - if(p==0.5) - return(0); - //--- change values - z=1.0-2.0*p; - z=CIncBetaF::InvIncompleteBeta(0.5,0.5*rk,MathAbs(z)); - t=MathSqrt(rk*z/(1.0-z)); - //--- check - if(p<0.5) - t=-t; - //--- return result - return(t); - } -//--- 0=0.5) - { - p=1.0-p; - rflg=1; - } -//--- change value - z=CIncBetaF::InvIncompleteBeta(0.5*rk,0.5,2.0*p); -//--- check - if(CMath::m_maxrealnumber*z 8 auxiliary functions f(x) and g(x) are employed | -//| such that | -//| Ci(x) = f(x) sin(x) - g(x) cos(x) | -//| Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) | -//| ACCURACY: | -//| Test interval = [0,50]. | -//| Absolute error, except relative when > 1: | -//| arithmetic function # trials peak rms | -//| IEEE Si 30000 4.4e-16 7.3e-17 | -//| IEEE Ci 30000 6.9e-16 5.1e-17 | -//+------------------------------------------------------------------+ -static void CTrigIntegrals::SineCosineIntegrals(double x,double &si,double &ci) - { -//--- create variables - double z=0; - double c=0; - double s=0; - double f=0; - double g=0; - int sg=0; - double sn=0; - double sd=0; - double cn=0; - double cd=0; - double fn=0; - double fd=0; - double gn=0; - double gd=0; -//--- initialization - si=0; - ci=0; -//--- check - if(x<0.0) - { - sg=-1; - x=-x; - } - else - sg=0; -//--- check - if(x==0.0) - { - si=0; - ci=-CMath::m_maxrealnumber; - //--- exit the function - return; - } -//--- check - if(x>1.0E9) - { - si=1.570796326794896619-MathCos(x)/x; - ci=MathSin(x)/x; - //--- exit the function - return; - } -//--- check - if(x<=4.0) - { - //--- calculation - z=x*x; - sn=-8.39167827910303881427E-11; - sn=sn*z+4.62591714427012837309E-8; - sn=sn*z-9.75759303843632795789E-6; - sn=sn*z+9.76945438170435310816E-4; - sn=sn*z-4.13470316229406538752E-2; - sn=sn*z+1.00000000000000000302E0; - sd=2.03269266195951942049E-12; - sd=sd*z+1.27997891179943299903E-9; - sd=sd*z+4.41827842801218905784E-7; - sd=sd*z+9.96412122043875552487E-5; - sd=sd*z+1.42085239326149893930E-2; - sd=sd*z+9.99999999999999996984E-1; - s=x*sn/sd; - cn=2.02524002389102268789E-11; - cn=cn*z-1.35249504915790756375E-8; - cn=cn*z+3.59325051419993077021E-6; - cn=cn*z-4.74007206873407909465E-4; - cn=cn*z+2.89159652607555242092E-2; - cn=cn*z-1.00000000000000000080E0; - cd=4.07746040061880559506E-12; - cd=cd*z+3.06780997581887812692E-9; - cd=cd*z+1.23210355685883423679E-6; - cd=cd*z+3.17442024775032769882E-4; - cd=cd*z+5.10028056236446052392E-2; - cd=cd*z+4.00000000000000000080E0; - c=z*cn/cd; - //--- check - if(sg!=0) - s=-s; - //--- calculation - si=s; - ci=0.57721566490153286061+MathLog(x)+c; - //--- exit the function - return; - } -//--- change values - s=MathSin(x); - c=MathCos(x); - z=1.0/(x*x); -//--- check - if(x<8.0) - { - //--- calculation - fn=4.23612862892216586994E0; - fn=fn*z+5.45937717161812843388E0; - fn=fn*z+1.62083287701538329132E0; - fn=fn*z+1.67006611831323023771E-1; - fn=fn*z+6.81020132472518137426E-3; - fn=fn*z+1.08936580650328664411E-4; - fn=fn*z+5.48900223421373614008E-7; - fd=1.00000000000000000000E0; - fd=fd*z+8.16496634205391016773E0; - fd=fd*z+7.30828822505564552187E0; - fd=fd*z+1.86792257950184183883E0; - fd=fd*z+1.78792052963149907262E-1; - fd=fd*z+7.01710668322789753610E-3; - fd=fd*z+1.10034357153915731354E-4; - fd=fd*z+5.48900252756255700982E-7; - f=fn/(x*fd); - gn=8.71001698973114191777E-2; - gn=gn*z+6.11379109952219284151E-1; - gn=gn*z+3.97180296392337498885E-1; - gn=gn*z+7.48527737628469092119E-2; - gn=gn*z+5.38868681462177273157E-3; - gn=gn*z+1.61999794598934024525E-4; - gn=gn*z+1.97963874140963632189E-6; - gn=gn*z+7.82579040744090311069E-9; - gd=1.00000000000000000000E0; - gd=gd*z+1.64402202413355338886E0; - gd=gd*z+6.66296701268987968381E-1; - gd=gd*z+9.88771761277688796203E-2; - gd=gd*z+6.22396345441768420760E-3; - gd=gd*z+1.73221081474177119497E-4; - gd=gd*z+2.02659182086343991969E-6; - gd=gd*z+7.82579218933534490868E-9; - g=z*gn/gd; - } - else - { - //--- calculation - fn=4.55880873470465315206E-1; - fn=fn*z+7.13715274100146711374E-1; - fn=fn*z+1.60300158222319456320E-1; - fn=fn*z+1.16064229408124407915E-2; - fn=fn*z+3.49556442447859055605E-4; - fn=fn*z+4.86215430826454749482E-6; - fn=fn*z+3.20092790091004902806E-8; - fn=fn*z+9.41779576128512936592E-11; - fn=fn*z+9.70507110881952024631E-14; - fd=1.00000000000000000000E0; - fd=fd*z+9.17463611873684053703E-1; - fd=fd*z+1.78685545332074536321E-1; - fd=fd*z+1.22253594771971293032E-2; - fd=fd*z+3.58696481881851580297E-4; - fd=fd*z+4.92435064317881464393E-6; - fd=fd*z+3.21956939101046018377E-8; - fd=fd*z+9.43720590350276732376E-11; - fd=fd*z+9.70507110881952025725E-14; - f=fn/(x*fd); - gn=6.97359953443276214934E-1; - gn=gn*z+3.30410979305632063225E-1; - gn=gn*z+3.84878767649974295920E-2; - gn=gn*z+1.71718239052347903558E-3; - gn=gn*z+3.48941165502279436777E-5; - gn=gn*z+3.47131167084116673800E-7; - gn=gn*z+1.70404452782044526189E-9; - gn=gn*z+3.85945925430276600453E-12; - gn=gn*z+3.14040098946363334640E-15; - gd=1.00000000000000000000E0; - gd=gd*z+1.68548898811011640017E0; - gd=gd*z+4.87852258695304967486E-1; - gd=gd*z+4.67913194259625806320E-2; - gd=gd*z+1.90284426674399523638E-3; - gd=gd*z+3.68475504442561108162E-5; - gd=gd*z+3.57043223443740838771E-7; - gd=gd*z+1.72693748966316146736E-9; - gd=gd*z+3.87830166023954706752E-12; - gd=gd*z+3.14040098946363335242E-15; - g=z*gn/gd; - } - si=1.570796326794896619-f*c-g*s; -//--- check - if(sg!=0) - si=-si; -//--- get result - ci=f*s-g*c; - } -//+------------------------------------------------------------------+ -//| Hyperbolic sine and cosine integrals | -//| Approximates the integrals | -//| x | -//| - | -//| | | cosh t - 1 | -//| Chi(x) = eul + ln x + | ----------- dt, | -//| | | t | -//| - | -//| 0 | -//| x | -//| - | -//| | | sinh t | -//| Shi(x) = | ------ dt | -//| | | t | -//| - | -//| 0 | -//| where eul = 0.57721566490153286061 is Euler's constant. | -//| The integrals are evaluated by power series for x < 8 | -//| and by Chebyshev expansions for x between 8 and 88. | -//| For large x, both functions approach exp(x)/2x. | -//| Arguments greater than 88 in magnitude return MAXNUM. | -//| ACCURACY: | -//| Test interval 0 to 88. | -//| Relative error: | -//| arithmetic function # trials peak rms | -//| IEEE Shi 30000 6.9e-16 1.6e-16 | -//| Absolute error, except relative when |Chi| > 1: | -//| IEEE Chi 30000 8.4e-16 1.4e-16 | -//+------------------------------------------------------------------+ -static void CTrigIntegrals::HyperbolicSineCosineIntegrals(double x, - double &shi, - double &chi) - { -//--- create variables - double k=0; - double z=0; - double c=0; - double s=0; - double a=0; - int sg=0; - double b0=0; - double b1=0; - double b2=0; -//--- initialization - shi=0; - chi=0; -//--- check - if(x<0.0) - { - sg=-1; - x=-x; - } - else - sg=0; -//--- check - if(x==0.0) - { - shi=0; - chi=-CMath::m_maxrealnumber; - //--- exit the function - return; - } -//--- check - if(x<8.0) - { - //--- initialization - z=x*x; - a=1.0; - s=1.0; - c=0.0; - k=2.0; - do - { - //--- calculation - a=a*z/k; - c=c+a/k; - k=k+1.0; - a=a/k; - s=s+a/k; - k=k+1.0; - } - while(MathAbs(a/s)>=CMath::m_machineepsilon); - s=s*x; - } - else - { - //--- check - if(x<18.0) - { - //--- calculation - a=(576.0/x-52.0)/10.0; - k=MathExp(x)/x; - b0=1.83889230173399459482E-17; - b1=0.0; - //--- function calls - ChebIterationShiChi(a,-9.55485532279655569575E-17,b0,b1,b2); - ChebIterationShiChi(a,2.04326105980879882648E-16,b0,b1,b2); - ChebIterationShiChi(a,1.09896949074905343022E-15,b0,b1,b2); - ChebIterationShiChi(a,-1.31313534344092599234E-14,b0,b1,b2); - ChebIterationShiChi(a,5.93976226264314278932E-14,b0,b1,b2); - ChebIterationShiChi(a,-3.47197010497749154755E-14,b0,b1,b2); - ChebIterationShiChi(a,-1.40059764613117131000E-12,b0,b1,b2); - ChebIterationShiChi(a,9.49044626224223543299E-12,b0,b1,b2); - ChebIterationShiChi(a,-1.61596181145435454033E-11,b0,b1,b2); - ChebIterationShiChi(a,-1.77899784436430310321E-10,b0,b1,b2); - ChebIterationShiChi(a,1.35455469767246947469E-9,b0,b1,b2); - ChebIterationShiChi(a,-1.03257121792819495123E-9,b0,b1,b2); - ChebIterationShiChi(a,-3.56699611114982536845E-8,b0,b1,b2); - ChebIterationShiChi(a,1.44818877384267342057E-7,b0,b1,b2); - ChebIterationShiChi(a,7.82018215184051295296E-7,b0,b1,b2); - ChebIterationShiChi(a,-5.39919118403805073710E-6,b0,b1,b2); - ChebIterationShiChi(a,-3.12458202168959833422E-5,b0,b1,b2); - ChebIterationShiChi(a,8.90136741950727517826E-5,b0,b1,b2); - ChebIterationShiChi(a,2.02558474743846862168E-3,b0,b1,b2); - ChebIterationShiChi(a,2.96064440855633256972E-2,b0,b1,b2); - ChebIterationShiChi(a,1.11847751047257036625E0,b0,b1,b2); - //--- calculation - s=k*0.5*(b0-b2); - b0=-8.12435385225864036372E-18; - b1=0.0; - //--- function calls - ChebIterationShiChi(a,2.17586413290339214377E-17,b0,b1,b2); - ChebIterationShiChi(a,5.22624394924072204667E-17,b0,b1,b2); - ChebIterationShiChi(a,-9.48812110591690559363E-16,b0,b1,b2); - ChebIterationShiChi(a,5.35546311647465209166E-15,b0,b1,b2); - ChebIterationShiChi(a,-1.21009970113732918701E-14,b0,b1,b2); - ChebIterationShiChi(a,-6.00865178553447437951E-14,b0,b1,b2); - ChebIterationShiChi(a,7.16339649156028587775E-13,b0,b1,b2); - ChebIterationShiChi(a,-2.93496072607599856104E-12,b0,b1,b2); - ChebIterationShiChi(a,-1.40359438136491256904E-12,b0,b1,b2); - ChebIterationShiChi(a,8.76302288609054966081E-11,b0,b1,b2); - ChebIterationShiChi(a,-4.40092476213282340617E-10,b0,b1,b2); - ChebIterationShiChi(a,-1.87992075640569295479E-10,b0,b1,b2); - ChebIterationShiChi(a,1.31458150989474594064E-8,b0,b1,b2); - ChebIterationShiChi(a,-4.75513930924765465590E-8,b0,b1,b2); - ChebIterationShiChi(a,-2.21775018801848880741E-7,b0,b1,b2); - ChebIterationShiChi(a,1.94635531373272490962E-6,b0,b1,b2); - ChebIterationShiChi(a,4.33505889257316408893E-6,b0,b1,b2); - ChebIterationShiChi(a,-6.13387001076494349496E-5,b0,b1,b2); - ChebIterationShiChi(a,-3.13085477492997465138E-4,b0,b1,b2); - ChebIterationShiChi(a,4.97164789823116062801E-4,b0,b1,b2); - ChebIterationShiChi(a,2.64347496031374526641E-2,b0,b1,b2); - ChebIterationShiChi(a,1.11446150876699213025E0,b0,b1,b2); - c=k*0.5*(b0-b2); - } - else - { - //--- check - if(x<=88.0) - { - //--- calculation - a=(6336.0/x-212.0)/70.0; - k=MathExp(x)/x; - b0=-1.05311574154850938805E-17; - b1=0.0; - //--- function calls - ChebIterationShiChi(a,2.62446095596355225821E-17,b0,b1,b2); - ChebIterationShiChi(a,8.82090135625368160657E-17,b0,b1,b2); - ChebIterationShiChi(a,-3.38459811878103047136E-16,b0,b1,b2); - ChebIterationShiChi(a,-8.30608026366935789136E-16,b0,b1,b2); - ChebIterationShiChi(a,3.93397875437050071776E-15,b0,b1,b2); - ChebIterationShiChi(a,1.01765565969729044505E-14,b0,b1,b2); - ChebIterationShiChi(a,-4.21128170307640802703E-14,b0,b1,b2); - ChebIterationShiChi(a,-1.60818204519802480035E-13,b0,b1,b2); - ChebIterationShiChi(a,3.34714954175994481761E-13,b0,b1,b2); - ChebIterationShiChi(a,2.72600352129153073807E-12,b0,b1,b2); - ChebIterationShiChi(a,1.66894954752839083608E-12,b0,b1,b2); - ChebIterationShiChi(a,-3.49278141024730899554E-11,b0,b1,b2); - ChebIterationShiChi(a,-1.58580661666482709598E-10,b0,b1,b2); - ChebIterationShiChi(a,-1.79289437183355633342E-10,b0,b1,b2); - ChebIterationShiChi(a,1.76281629144264523277E-9,b0,b1,b2); - ChebIterationShiChi(a,1.69050228879421288846E-8,b0,b1,b2); - ChebIterationShiChi(a,1.25391771228487041649E-7,b0,b1,b2); - ChebIterationShiChi(a,1.16229947068677338732E-6,b0,b1,b2); - ChebIterationShiChi(a,1.61038260117376323993E-5,b0,b1,b2); - ChebIterationShiChi(a,3.49810375601053973070E-4,b0,b1,b2); - ChebIterationShiChi(a,1.28478065259647610779E-2,b0,b1,b2); - ChebIterationShiChi(a,1.03665722588798326712E0,b0,b1,b2); - //--- calculation - s=k*0.5*(b0-b2); - b0=8.06913408255155572081E-18; - b1=0.0; - //--- function calls - ChebIterationShiChi(a,-2.08074168180148170312E-17,b0,b1,b2); - ChebIterationShiChi(a,-5.98111329658272336816E-17,b0,b1,b2); - ChebIterationShiChi(a,2.68533951085945765591E-16,b0,b1,b2); - ChebIterationShiChi(a,4.52313941698904694774E-16,b0,b1,b2); - ChebIterationShiChi(a,-3.10734917335299464535E-15,b0,b1,b2); - ChebIterationShiChi(a,-4.42823207332531972288E-15,b0,b1,b2); - ChebIterationShiChi(a,3.49639695410806959872E-14,b0,b1,b2); - ChebIterationShiChi(a,6.63406731718911586609E-14,b0,b1,b2); - ChebIterationShiChi(a,-3.71902448093119218395E-13,b0,b1,b2); - ChebIterationShiChi(a,-1.27135418132338309016E-12,b0,b1,b2); - ChebIterationShiChi(a,2.74851141935315395333E-12,b0,b1,b2); - ChebIterationShiChi(a,2.33781843985453438400E-11,b0,b1,b2); - ChebIterationShiChi(a,2.71436006377612442764E-11,b0,b1,b2); - ChebIterationShiChi(a,-2.56600180000355990529E-10,b0,b1,b2); - ChebIterationShiChi(a,-1.61021375163803438552E-9,b0,b1,b2); - ChebIterationShiChi(a,-4.72543064876271773512E-9,b0,b1,b2); - ChebIterationShiChi(a,-3.00095178028681682282E-9,b0,b1,b2); - ChebIterationShiChi(a,7.79387474390914922337E-8,b0,b1,b2); - ChebIterationShiChi(a,1.06942765566401507066E-6,b0,b1,b2); - ChebIterationShiChi(a,1.59503164802313196374E-5,b0,b1,b2); - ChebIterationShiChi(a,3.49592575153777996871E-4,b0,b1,b2); - ChebIterationShiChi(a,1.28475387530065247392E-2,b0,b1,b2); - ChebIterationShiChi(a,1.03665693917934275131E0,b0,b1,b2); - c=k*0.5*(b0-b2); - } - else - { - //--- check - if(sg!=0) - shi=-CMath::m_maxrealnumber; - else - shi=CMath::m_maxrealnumber; - chi=CMath::m_maxrealnumber; - //--- exit the function - return; - } - } - } -//--- check - if(sg!=0) - s=-s; -//--- get result - shi=s; - chi=0.57721566490153286061+MathLog(x)+c; - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CTrigIntegrals::ChebIterationShiChi(const double x,const double c, - double &b0,double &b1,double &b2) - { -//--- change values - b2=b1; - b1=b0; - b0=x*b1-b2+c; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Alglib/statistics.mqh b/Include/Math/Alglib/statistics.mqh deleted file mode 100644 index b458586..0000000 --- a/Include/Math/Alglib/statistics.mqh +++ /dev/null @@ -1,13972 +0,0 @@ -//+------------------------------------------------------------------+ -//| statistics.mqh | -//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) | -//| Copyright 2012-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of ALGLIB library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Linear algebra (direct algorithms, EVD, SVD) | -//| - Solving systems of linear and non-linear equations | -//| - Interpolation | -//| - Optimization | -//| - FFT (Fast Fourier Transform) | -//| - Numerical integration | -//| - Linear and nonlinear least-squares fitting | -//| - Ordinary differential equations | -//| - Computation of special functions | -//| - Descriptive statistics and hypothesis testing | -//| - Data analysis - classification, regression | -//| - Implementing linear algebra algorithms, interpolation, etc. | -//| in high-precision arithmetic (using MPFR) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include "ap.mqh" -#include "alglibinternal.mqh" -#include "linalg.mqh" -#include "specialfunctions.mqh" -//+------------------------------------------------------------------+ -//| basic statistics methods | -//+------------------------------------------------------------------+ -class CBaseStat - { -public: - CBaseStat(void); - ~CBaseStat(void); - //--- basic parameters - static bool SampleMoments(const double &cx[],const int n,double &mean,double &variance,double &skewness,double &kurtosis); - static bool SampleAdev(const double &cx[],const int n,double &adev); - static bool SampleMedian(const double &cx[],const int n,double &median); - static bool SamplePercentile(const double &cx[],const int n,const double p,double &v); - //--- covariance and correlation - static double Cov2(const double &cx[],const double &cy[],const int n); - static double PearsonCorr2(const double &cx[],const double &cy[],const int n); - static double SpearmanCorr2(const double &cx[],const double &cy[],const int n); - static bool CovM(const CMatrixDouble &cx,const int n,const int m,CMatrixDouble &c); - static bool PearsonCorrM(const CMatrixDouble &cx,const int n,const int m,CMatrixDouble &c); - static bool SpearmanCorrM(const CMatrixDouble &cx,const int n,const int m,CMatrixDouble &c); - static bool CovM2(const CMatrixDouble &cx,const CMatrixDouble &cy,const int n,const int m1,const int m2,CMatrixDouble &c); - static bool PearsonCorrM2(const CMatrixDouble &cx,const CMatrixDouble &cy,const int n,const int m1,const int m2,CMatrixDouble &c); - static bool SpearmanCorrM2(const CMatrixDouble &cx,const CMatrixDouble &cy,const int n,const int m1,const int m2,CMatrixDouble &c); - //--- obsolete functions - static double PearsonCorrelation(const double &x[],const double &y[],const int n); - static double SpearmanRankCorrelation(const double &x[],const double &y[],const int n); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CBaseStat::CBaseStat(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBaseStat::~CBaseStat(void) - { - - } -//+------------------------------------------------------------------+ -//| Calculation of the distribution moments: mean, variance, | -//| skewness, kurtosis. | -//| INPUT PARAMETERS: | -//| X - sample | -//| N - N>=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from | -//| size of X | -//| OUTPUT PARAMETERS | -//| Mean - mean. | -//| Variance- variance. | -//| Skewness- skewness (if variance<>0; zero otherwise). | -//| Kurtosis- kurtosis (if variance<>0; zero otherwise). | -//+------------------------------------------------------------------+ -static bool CBaseStat::SampleMoments(const double &cx[],const int n,double &mean, - double &variance,double &skewness,double &kurtosis) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| ADev- ADev | -//+------------------------------------------------------------------+ -static bool CBaseStat::SampleAdev(const double &cx[],const int n, - double &adev) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| Output parameters: | -//| Median | -//+------------------------------------------------------------------+ -static bool CBaseStat::SampleMedian(const double &cx[],const int n, - double &median) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=3. -//--- Choose X[(N-1)/2] - int i=0; - int ir=n-1; - int j=0; - int l=0; - int midp=0; - int k=(n-1)/2; - double a=0; - double tval=0; -//--- create copy - double x[]; - ArrayResizeAL(x,n); - for(int ii=0;ii=3 - while(true) - { - //--- check - if(ir<=l+1) - { - //--- 1 or 2 elements in partition - if(ir==l+1 && x[ir]x[ir]) - { - //--- swap - tval=x[l]; - x[l]=x[ir]; - x[ir]=tval; - } - //--- check - if(x[l+1]>x[ir]) - { - //--- swap - tval=x[l+1]; - x[l+1]=x[ir]; - x[ir]=tval; - } - //--- check - if(x[l]>x[l+1]) - { - //--- swap - tval=x[l]; - x[l]=x[l+1]; - x[l+1]=tval; - } - //--- change values - i=l+1; - j=ir; - a=x[l+1]; - //--- cycle - while(true) - { - //--- i++ - do - i++; - while(x[i]a); - //--- check - if(j=k) - ir=j-1; - //--- check - if(j<=k) - l=i; - } - } -//--- If N is odd, return result - if(n%2==1) - { - median=x[k]; - return(true); - } - a=x[n-1]; - for(i=k+1;i=0, sample size: | -//| * if given, only leading N elements of X are | -//| processed | -//| * if not given, automatically determined from size | -//| of X | -//| P - percentile (0<=P<=1) | -//| Output parameters: | -//| V - percentile | -//+------------------------------------------------------------------+ -static bool CBaseStat::SamplePercentile(const double &cx[],const int n, - const double p,double &v) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=0 && p<=1,__FUNCTION__+": incorrect p")) - return(false); -//--- check - if(p==0) - { - v=cx[0]; - return(true); - } -//--- check - if(p==1) - { - v=cx[n-1]; - return(true); - } -//--- initialization - int i1=0; - double t=0; - double rbuf[]; - v=0; -//--- create copy - double x[]; - ArrayResizeAL(x,n); - for(int ii=0;ii=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| covariance (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CBaseStat::Cov2(const double &cx[],const double &cy[], - const int n) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=n,__FUNCTION__+": length(y)=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Pearson product-moment correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CBaseStat::PearsonCorr2(const double &cx[],const double &cy[], - const int n) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=n,__FUNCTION__+": length(y)=0, sample size: | -//| * if given, only N leading elements of X/Y are | -//| processed | -//| * if not given, automatically determined from | -//| input sizes | -//| Result: | -//| Spearman's rank correlation coefficient | -//| (zero for N=0 or N=1) | -//+------------------------------------------------------------------+ -static double CBaseStat::SpearmanCorr2(const double &cx[],const double &cy[], - const int n) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(EMPTY_VALUE); -//--- check - if(!CAp::Assert(CAp::Len(cx)>=n,__FUNCTION__+": length(x)=n,__FUNCTION__+": length(y)=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], covariance matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::CovM(const CMatrixDouble &cx,const int n,const int m, - CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m || n==0,__FUNCTION__+": cols(x)=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::PearsonCorrM(const CMatrixDouble &cx,const int n, - const int m,CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m || n==0,__FUNCTION__+": cols(x)=0, number of observations: | -//| * if given, only leading N rows of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M - M>0, number of variables: | -//| * if given, only leading M columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M,M], correlation matrix (zero if N=0 or N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::SpearmanCorrM(const CMatrixDouble &cx,const int n, - const int m,CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m || n==0,__FUNCTION__+": cols(x)=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-covariance matrix (zero if N=0 or| -//| N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::CovM2(const CMatrixDouble &cx,const CMatrixDouble &cy, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m1>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m2>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m1 || n==0,__FUNCTION__+": cols(x)=n,__FUNCTION__+": rows(y)=m2 || n==0,__FUNCTION__+": cols(y)=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::PearsonCorrM2(const CMatrixDouble &cx,const CMatrixDouble &cy, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m1>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m2>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m1 || n==0,__FUNCTION__+": cols(x)=n,__FUNCTION__+": rows(y)=m2 || n==0,__FUNCTION__+": cols(y)=0, number of observations: | -//| * if given, only leading N rows of X/Y are used | -//| * if not given, automatically determined from input | -//| sizes | -//| M1 - M1>0, number of variables in X: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| M2 - M2>0, number of variables in Y: | -//| * if given, only leading M1 columns of X are used | -//| * if not given, automatically determined from input | -//| size | -//| OUTPUT PARAMETERS: | -//| C - array[M1,M2], cross-correlation matrix (zero if N=0 | -//| or N=1) | -//+------------------------------------------------------------------+ -static bool CBaseStat::SpearmanCorrM2(const CMatrixDouble &cx,const CMatrixDouble &cy, - const int n,const int m1,const int m2, - CMatrixDouble &c) - { -//--- check - if(!CAp::Assert(n>=0,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m1>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(m2>=1,__FUNCTION__+": the error variable")) - return(false); -//--- check - if(!CAp::Assert(CAp::Rows(cx)>=n,__FUNCTION__+": rows(x)=m1 || n==0,__FUNCTION__+": cols(x)=n,__FUNCTION__+": rows(y)=m2 || n==0,__FUNCTION__+": cols(y)=3.580e+00) - return(8.304e-03); -//--- check - if(s>=2.322e+00) - return(4.163e-02); -//--- check - if(s>=1.704e+00) - return(6.641e-02); -//--- check - if(s>=1.303e+00) - return(1.164e-01); -//--- check - if(s>=1.003e+00) - return(1.748e-01); -//--- check - if(s>=7.584e-01) - return(2.249e-01); -//--- check - if(s>=5.468e-01) - return(2.581e-01); -//--- check - if(s>=3.555e-01) - return(3.413e-01); -//--- check - if(s>=1.759e-01) - return(3.911e-01); -//--- check - if(s>=1.741e-03) - return(4.747e-01); -//--- check - if(s>=0.000e+00) - return(5.248e-01); -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Tail(S, 6) | -//+------------------------------------------------------------------+ -static double CCorrTests::SpearmanTail6(const double s) - { -//--- check - if(s<1.001e+00) - return(CStudenttDistr::StudenttDistribution(4,-s)); -//--- check - if(s>=5.663e+00) - return(1.366e-03); -//--- check - if(s>=3.834e+00) - return(8.350e-03); -//--- check - if(s>=2.968e+00) - return(1.668e-02); -//--- check - if(s>=2.430e+00) - return(2.921e-02); -//--- check - if(s>=2.045e+00) - return(5.144e-02); -//--- check - if(s>=1.747e+00) - return(6.797e-02); -//--- check - if(s>=1.502e+00) - return(8.752e-02); -//--- check - if(s>=1.295e+00) - return(1.210e-01); -//--- check - if(s>=1.113e+00) - return(1.487e-01); -//--- check - if(s>=1.001e+00) - return(1.780e-01); -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Tail(S, 7) | -//+------------------------------------------------------------------+ -static double CCorrTests::SpearmanTail7(const double s) - { -//--- check - if(s<1.001e+00) - return(CStudenttDistr::StudenttDistribution(5,-s)); -//--- check - if(s>=8.159e+00) - return(2.081e-04); -//--- check - if(s>=5.620e+00) - return(1.393e-03); -//--- check - if(s>=4.445e+00) - return(3.398e-03); -//--- check - if(s>=3.728e+00) - return(6.187e-03); -//--- check - if(s>=3.226e+00) - return(1.200e-02); -//--- check - if(s>=2.844e+00) - return(1.712e-02); -//--- check - if(s>=2.539e+00) - return(2.408e-02); -//--- check - if(s>=2.285e+00) - return(3.320e-02); -//--- check - if(s>=2.068e+00) - return(4.406e-02); -//--- check - if(s>=1.879e+00) - return(5.478e-02); -//--- check - if(s>=1.710e+00) - return(6.946e-02); -//--- check - if(s>=1.559e+00) - return(8.331e-02); -//--- check - if(s>=1.420e+00) - return(1.001e-01); -//--- check - if(s>=1.292e+00) - return(1.180e-01); -//--- check - if(s>=1.173e+00) - return(1.335e-01); -//--- check - if(s>=1.062e+00) - return(1.513e-01); -//--- check - if(s>=1.001e+00) - return(1.770e-01); -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Tail(S, 8) | -//+------------------------------------------------------------------+ -static double CCorrTests::SpearmanTail8(const double s) - { -//--- check - if(s<2.001e+00) - return(CStudenttDistr::StudenttDistribution(6,-s)); -//--- check - if(s>=1.103e+01) - return(2.194e-05); -//--- check - if(s>=7.685e+00) - return(2.008e-04); -//--- check - if(s>=6.143e+00) - return(5.686e-04); -//--- check - if(s>=5.213e+00) - return(1.138e-03); -//--- check - if(s>=4.567e+00) - return(2.310e-03); -//--- check - if(s>=4.081e+00) - return(3.634e-03); -//--- check - if(s>=3.697e+00) - return(5.369e-03); -//--- check - if(s>=3.381e+00) - return(7.708e-03); -//--- check - if(s>=3.114e+00) - return(1.087e-02); -//--- check - if(s>=2.884e+00) - return(1.397e-02); -//--- check - if(s>=2.682e+00) - return(1.838e-02); -//--- check - if(s>=2.502e+00) - return(2.288e-02); -//--- check - if(s>=2.340e+00) - return(2.883e-02); -//--- check - if(s>=2.192e+00) - return(3.469e-02); -//--- check - if(s>=2.057e+00) - return(4.144e-02); -//--- check - if(s>=2.001e+00) - return(4.804e-02); -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Tail(S, 9) | -//+------------------------------------------------------------------+ -static double CCorrTests::SpearmanTail9(const double s) - { -//--- check - if(s<2.001e+00) - return(CStudenttDistr::StudenttDistribution(7,-s)); -//--- check - if(s>=9.989e+00) - return(2.306e-05); -//--- check - if(s>=8.069e+00) - return(8.167e-05); -//--- check - if(s>=6.890e+00) - return(1.744e-04); -//--- check - if(s>=6.077e+00) - return(3.625e-04); -//--- check - if(s>=5.469e+00) - return(6.450e-04); -//--- check - if(s>=4.991e+00) - return(1.001e-03); -//--- check - if(s>=4.600e+00) - return(1.514e-03); -//--- check - if(s>=4.272e+00) - return(2.213e-03); -//--- check - if(s>=3.991e+00) - return(2.990e-03); -//--- check - if(s>=3.746e+00) - return(4.101e-03); -//--- check - if(s>=3.530e+00) - return(5.355e-03); -//--- check - if(s>=3.336e+00) - return(6.887e-03); -//--- check - if(s>=3.161e+00) - return(8.598e-03); -//--- check - if(s>=3.002e+00) - return(1.065e-02); -//--- check - if(s>=2.855e+00) - return(1.268e-02); -//--- check - if(s>=2.720e+00) - return(1.552e-02); -//--- check - if(s>=2.595e+00) - return(1.836e-02); -//--- check - if(s>=2.477e+00) - return(2.158e-02); -//--- check - if(s>=2.368e+00) - return(2.512e-02); -//--- check - if(s>=2.264e+00) - return(2.942e-02); -//--- check - if(s>=2.166e+00) - return(3.325e-02); -//--- check - if(s>=2.073e+00) - return(3.800e-02); -//--- check - if(s>=2.001e+00) - return(4.285e-02); -//--- return result - return(0); - } -//+------------------------------------------------------------------+ -//| Pearson's correlation coefficient significance test | -//| This test checks hypotheses about whether X and Y are samples of| -//| two continuous distributions having zero correlation or whether | -//| their correlation is non-zero. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - X and Y have zero | -//| correlation) | -//| * left-tailed test (null hypothesis - the correlation | -//| coefficient is greater than or equal to 0) | -//| * right-tailed test (null hypothesis - the correlation | -//| coefficient is less than or equal to 0). | -//| Requirements: | -//| * the number of elements in each sample is not less than 5 | -//| * normality of distributions of X and Y. | -//| Input parameters: | -//| R - Pearson's correlation coefficient for X and Y | -//| N - number of elements in samples, N>=5. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CCorrTests::PearsonCorrSignific(const double r,const int n, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- Some special cases - if(r>=1) - { - bothTails=0.0; - leftTail=1.0; - rightTail=0.0; - return; - } -//--- check - if(r<=-1) - { - bothTails=0.0; - leftTail=0.0; - rightTail=1.0; - return; - } -//--- check - if(n<5) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - return; - } -//--- create variables - double t; - double p; -//--- calculation - t=r*MathSqrt((n-2)/(1-CMath::Sqr(r))); - p=CStudenttDistr::StudenttDistribution(n-2,t); - bothTails=2*MathMin(p,1-p); - leftTail=p; - rightTail=1-p; - } -//+------------------------------------------------------------------+ -//| Spearman's rank correlation coefficient significance test | -//| This test checks hypotheses about whether X and Y are samples of | -//| two continuous distributions having zero correlation or whether | -//| their correlation is non-zero. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - X and Y have zero | -//| correlation) | -//| * left-tailed test (null hypothesis - the correlation | -//| coefficient is greater than or equal to 0) | -//| * right-tailed test (null hypothesis - the correlation | -//| coefficient is less than or equal to 0). | -//| Requirements: | -//| * the number of elements in each sample is not less than 5. | -//| The test is non-parametric and doesn't require distributions X | -//| and Y to be normal. | -//| Input parameters: | -//| R - Spearman's rank correlation coefficient for X and Y | -//| N - number of elements in samples, N>=5. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CCorrTests::SpearmanRankCorrSignific(const double r,const int n, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- Special case - if(n<5) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - return; - } -//--- create variables - double t; - double p; -//--- General case - if(r>=1) - t=1.0E10; - else - { - //--- check - if(r<=-1) - t=-1.0E10; - else - t=r*MathSqrt((n-2)/(1-CMath::Sqr(r))); - } -//--- check - if(t<0) - { - p=SpearmanTail(t,n); - bothTails=2*p; - leftTail=p; - rightTail=1-p; - } - else - { - p=SpearmanTail(-t,n); - bothTails=2*p; - leftTail=1-p; - rightTail=p; - } - } -//+------------------------------------------------------------------+ -//| Jarque-Bera test | -//+------------------------------------------------------------------+ -class CJarqueBera - { -private: - static bool JarqueBeraStat(const double &x[],const int n,double &s); - static double JarqueBeraApprox(const int n,const double s); - static void JBCheb(double x,double c,double &tj,double &tj1,double &r); - static double JBTbl5(const double s); - static double JBTbl6(const double s); - static double JBTbl7(const double s); - static double JBTbl8(const double s); - static double JBTbl9(const double s); - static double JBTbl10(const double s); - static double JBTbl11(const double s); - static double JBTbl12(const double s); - static double JBTbl13(const double s); - static double JBTbl14(const double s); - static double JBTbl15(const double s); - static double JBTbl16(const double s); - static double JBTbl17(const double s); - static double JBTbl18(const double s); - static double JBTbl19(const double s); - static double JBTbl20(const double s); - static double JBTbl30(const double s); - static double JBTbl50(const double s); - static double JBTbl65(const double s); - static double JBTbl100(const double s); - static double JBTbl130(const double s); - static double JBTbl200(const double s); - static double JBTbl301(const double s); - static double JBTbl501(const double s); - static double JBTbl701(const double s); - static double JBTbl1401(const double s); -public: - //--- constructor, destructor - CJarqueBera(void); - ~CJarqueBera(void); - //--- method - static bool JarqueBeraTest(const double &x[],const int n,double &p); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CJarqueBera::CJarqueBera(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CJarqueBera::~CJarqueBera(void) - { - - } -//+------------------------------------------------------------------+ -//| Jarque-Bera test | -//| This test checks hypotheses about the fact that a given sample X | -//| is a sample of normal random variable. | -//| Requirements: | -//| * the number of elements in the sample is not less than 5. | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of the sample. N>=5 | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| Accuracy of the approximation used (5<=N<=1951): | -//| p-value relative error (5<=N<=1951) | -//| [1, 0.1] < 1% | -//| [0.1, 0.01] < 2% | -//| [0.01, 0.001] < 6% | -//| [0.001, 0] wasn't measured | -//| For N>1951 accuracy wasn't measured but it shouldn't be sharply | -//| different from table values. | -//+------------------------------------------------------------------+ -static bool CJarqueBera::JarqueBeraTest(const double &x[],const int n, - double &p) - { -//--- create a variable - double s; -//--- N is too small - if(n<5) - { - p=1.0; - return(true); - } -//--- N is large enough - if(!JarqueBeraStat(x,n,s)) - return(false); - p=JarqueBeraApprox(n,s); -//--- successful execution - return(true); - } -//+------------------------------------------------------------------+ -//| Jarque-Bera statistics | -//+------------------------------------------------------------------+ -static bool CJarqueBera::JarqueBeraStat(const double &x[],const int n, - double &s) - { -//--- check - if(!CAp::Assert(n>1,__FUNCTION__+": the error variable")) - return(false); -//--- create variables - int i=0; - double v=0; - double v1=0; - double v2=0; - double stddev=0; - double mean=0; - double variance=0; - double skewness=0; - double kurtosis=0; -//--- Mean - for(i=0;i=5 && n<=20) - { - //--- check - if(n==5) - return(MathExp(JBTbl5(x))); - //--- check - if(n==6) - return(MathExp(JBTbl6(x))); - //--- check - if(n==7) - return(MathExp(JBTbl7(x))); - //--- check - if(n==8) - return(MathExp(JBTbl8(x))); - //--- check - if(n==9) - return(MathExp(JBTbl9(x))); - //--- check - if(n==10) - return(MathExp(JBTbl10(x))); - //--- check - if(n==11) - return(MathExp(JBTbl11(x))); - //--- check - if(n==12) - return(MathExp(JBTbl12(x))); - //--- check - if(n==13) - return(MathExp(JBTbl13(x))); - //--- check - if(n==14) - return(MathExp(JBTbl14(x))); - //--- check - if(n==15) - return(MathExp(JBTbl15(x))); - //--- check - if(n==16) - return(MathExp(JBTbl16(x))); - //--- check - if(n==17) - return(MathExp(JBTbl17(x))); - //--- check - if(n==18) - return(MathExp(JBTbl18(x))); - //--- check - if(n==19) - return(MathExp(JBTbl19(x))); - //--- check - if(n==20) - return(MathExp(JBTbl20(x))); - } -//--- N = 20, 30, 50 are tabulated. -//--- In-between values are interpolated -//--- using interpolating polynomial of the second degree. - if(n>20 && n<=50) - { - t1=-1.0/20.0; - t2=-1.0/30.0; - t3=-1.0/50.0; - t=-1.0/n; - //--- tabulation - f1=JBTbl20(x); - f2=JBTbl30(x); - f3=JBTbl50(x); - //--- interpolating - f12=((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23=((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result=((t-t3)*f12+(t1-t)*f23)/(t1-t3); - //--- check - if(result>0) - result=0; - //--- return result - return(MathExp(result)); - } -//--- N = 50, 65, 100 are tabulated. -//--- In-between values are interpolated -//--- using interpolating polynomial of the second degree. - if(n>50 && n<=100) - { - t1=-1.0/50.0; - t2=-1.0/65.0; - t3=-1.0/100.0; - t=-1.0/n; - //--- tabulation - f1=JBTbl50(x); - f2=JBTbl65(x); - f3=JBTbl100(x); - //--- interpolating - f12=((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23=((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result=((t-t3)*f12+(t1-t)*f23)/(t1-t3); - //--- check - if(result>0) - result=0; - //--- return result - return(MathExp(result)); - } -//--- N = 100, 130, 200 are tabulated. -//--- In-between values are interpolated -//--- using interpolating polynomial of the second degree. - if(n>100 && n<=200) - { - t1=-(1.0/100.0); - t2=-(1.0/130.0); - t3=-(1.0/200.0); - t=-(1.0/n); - //--- tabulation - f1=JBTbl100(x); - f2=JBTbl130(x); - f3=JBTbl200(x); - //--- interpolating - f12=((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23=((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result=((t-t3)*f12+(t1-t)*f23)/(t1-t3); - //--- check - if(result>0) - result=0; - //--- return result - return(MathExp(result)); - } -//--- N = 200, 301, 501 are tabulated. -//--- In-between values are interpolated -//--- using interpolating polynomial of the second degree. - if(n>200 && n<=501) - { - t1=-(1.0/200.0); - t2=-(1.0/301.0); - t3=-(1.0/501.0); - t=-(1.0/n); - //--- tabulation - f1=JBTbl200(x); - f2=JBTbl301(x); - f3=JBTbl501(x); - //--- interpolating - f12=((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23=((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result=((t-t3)*f12+(t1-t)*f23)/(t1-t3); - //--- check - if(result>0) - result=0; - //--- return result - return(MathExp(result)); - } -//--- N = 501, 701, 1401 are tabulated. -//--- In-between values are interpolated -//--- using interpolating polynomial of the second degree. - if(n>501 && n<=1401) - { - t1=-(1.0/501.0); - t2=-(1.0/701.0); - t3=-(1.0/1401.0); - t=-(1.0/n); - //--- tabulation - f1=JBTbl501(x); - f2=JBTbl701(x); - f3=JBTbl1401(x); - //--- interpolating - f12=((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23=((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result=((t-t3)*f12+(t1-t)*f23)/(t1-t3); - //--- check - if(result>0) - result=0; - //--- return result - return(MathExp(result)); - } -//--- get result - result=-(0.5*x)+(JBTbl1401(x)+0.5*x)*MathSqrt((double)1401/(double)n); -//--- check - if(result>0) - result=0; -//--- return result - return(MathExp(result)); - } -//+------------------------------------------------------------------+ -//| Internal subroutine | -//+------------------------------------------------------------------+ -static void CJarqueBera::JBCheb(double x,double c,double &tj,double &tj1, - double &r) - { -//--- create variables - double t; -//--- change values - r+=c*tj; - t=2*x*tj1-tj; - tj=tj1; - tj1=t; - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 5 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl5(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=0.4000) - { - x=2*s/0.400000-1; - tj=1; - tj1=x; - JBCheb(x,-1.097885e-20,tj,tj1,result); - JBCheb(x,-2.854501e-20,tj,tj1,result); - JBCheb(x,-1.756616e-20,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=1.1000) - { - x=2*(s-0.400000)/0.700000-1; - tj=1; - tj1=x; - JBCheb(x,-1.324545e+00,tj,tj1,result); - JBCheb(x,-1.075941e+00,tj,tj1,result); - JBCheb(x,-9.772272e-01,tj,tj1,result); - JBCheb(x,3.175686e-01,tj,tj1,result); - JBCheb(x,-1.576162e-01,tj,tj1,result); - JBCheb(x,1.126861e-01,tj,tj1,result); - JBCheb(x,-3.434425e-02,tj,tj1,result); - JBCheb(x,-2.790359e-01,tj,tj1,result); - JBCheb(x,2.809178e-02,tj,tj1,result); - JBCheb(x,-5.479704e-01,tj,tj1,result); - JBCheb(x,3.717040e-02,tj,tj1,result); - JBCheb(x,-5.294170e-01,tj,tj1,result); - JBCheb(x,2.880632e-02,tj,tj1,result); - JBCheb(x,-3.023344e-01,tj,tj1,result); - JBCheb(x,1.601531e-02,tj,tj1,result); - JBCheb(x,-7.920403e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(5.188419e+02*(s-1.100000e+00))-4.767297e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 6 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl6(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=0.2500) - { - x=2*(s-0.000000)/0.250000-1; - tj=1; - tj1=x; - JBCheb(x,-2.274707e-04,tj,tj1,result); - JBCheb(x,-5.700471e-04,tj,tj1,result); - JBCheb(x,-3.425764e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=1.3000) - { - x=2*(s-0.250000)/1.050000-1; - tj=1; - tj1=x; - JBCheb(x,-1.339000e+00,tj,tj1,result); - JBCheb(x,-2.011104e+00,tj,tj1,result); - JBCheb(x,-8.168177e-01,tj,tj1,result); - JBCheb(x,-1.085666e-01,tj,tj1,result); - JBCheb(x,7.738606e-02,tj,tj1,result); - JBCheb(x,7.022876e-02,tj,tj1,result); - JBCheb(x,3.462402e-02,tj,tj1,result); - JBCheb(x,6.908270e-03,tj,tj1,result); - JBCheb(x,-8.230772e-03,tj,tj1,result); - JBCheb(x,-1.006996e-02,tj,tj1,result); - JBCheb(x,-5.410222e-03,tj,tj1,result); - JBCheb(x,-2.893768e-03,tj,tj1,result); - JBCheb(x,8.114564e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=1.8500) - { - x=2*(s-1.300000)/0.550000-1; - tj=1; - tj1=x; - JBCheb(x,-6.794311e+00,tj,tj1,result); - JBCheb(x,-3.578700e+00,tj,tj1,result); - JBCheb(x,-1.394664e+00,tj,tj1,result); - JBCheb(x,-7.928290e-01,tj,tj1,result); - JBCheb(x,-4.813273e-01,tj,tj1,result); - JBCheb(x,-3.076063e-01,tj,tj1,result); - JBCheb(x,-1.835380e-01,tj,tj1,result); - JBCheb(x,-1.013013e-01,tj,tj1,result); - JBCheb(x,-5.058903e-02,tj,tj1,result); - JBCheb(x,-1.856915e-02,tj,tj1,result); - JBCheb(x,-6.710887e-03,tj,tj1,result); - //--- - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.770029e+02*(s-1.850000e+00))-1.371015e+01; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 7 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl7(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.4000) - { - x=2*(s-0.000000)/1.400000-1; - tj=1; - tj1=x; - JBCheb(x,-1.093681e+00,tj,tj1,result); - JBCheb(x,-1.695911e+00,tj,tj1,result); - JBCheb(x,-7.473192e-01,tj,tj1,result); - JBCheb(x,-1.203236e-01,tj,tj1,result); - JBCheb(x,6.590379e-02,tj,tj1,result); - JBCheb(x,6.291876e-02,tj,tj1,result); - JBCheb(x,3.132007e-02,tj,tj1,result); - JBCheb(x,9.411147e-03,tj,tj1,result); - JBCheb(x,-1.180067e-03,tj,tj1,result); - JBCheb(x,-3.487610e-03,tj,tj1,result); - JBCheb(x,-2.436561e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=3.0000) - { - x=2*(s-1.400000)/1.600000-1; - tj=1; - tj1=x; - JBCheb(x,-5.947854e+00,tj,tj1,result); - JBCheb(x,-2.772675e+00,tj,tj1,result); - JBCheb(x,-4.707912e-01,tj,tj1,result); - JBCheb(x,-1.691171e-01,tj,tj1,result); - JBCheb(x,-4.132795e-02,tj,tj1,result); - JBCheb(x,-1.481310e-02,tj,tj1,result); - JBCheb(x,2.867536e-03,tj,tj1,result); - JBCheb(x,8.772327e-04,tj,tj1,result); - JBCheb(x,5.033387e-03,tj,tj1,result); - JBCheb(x,-1.378277e-03,tj,tj1,result); - JBCheb(x,-2.497964e-03,tj,tj1,result); - JBCheb(x,-3.636814e-03,tj,tj1,result); - JBCheb(x,-9.581640e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=3.2000) - { - x=2*(s-3.000000)/0.200000-1; - tj=1; - tj1=x; - JBCheb(x,-7.511008e+00,tj,tj1,result); - JBCheb(x,-8.140472e-01,tj,tj1,result); - JBCheb(x,1.682053e+00,tj,tj1,result); - JBCheb(x,-2.568561e-02,tj,tj1,result); - JBCheb(x,-1.933930e+00,tj,tj1,result); - JBCheb(x,-8.140472e-01,tj,tj1,result); - JBCheb(x,-3.895025e+00,tj,tj1,result); - JBCheb(x,-8.140472e-01,tj,tj1,result); - JBCheb(x,-1.933930e+00,tj,tj1,result); - JBCheb(x,-2.568561e-02,tj,tj1,result); - JBCheb(x,1.682053e+00,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.824116e+03*(s-3.200000e+00))-1.440330e+01; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 8 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl8(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.3000) - { - x=2*(s-0.000000)/1.300000-1; - tj=1; - tj1=x; - JBCheb(x,-7.199015e-01,tj,tj1,result); - JBCheb(x,-1.095921e+00,tj,tj1,result); - JBCheb(x,-4.736828e-01,tj,tj1,result); - JBCheb(x,-1.047438e-01,tj,tj1,result); - JBCheb(x,-2.484320e-03,tj,tj1,result); - JBCheb(x,7.937923e-03,tj,tj1,result); - JBCheb(x,4.810470e-03,tj,tj1,result); - JBCheb(x,2.139780e-03,tj,tj1,result); - JBCheb(x,6.708443e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=2.0000) - { - x=2*(s-1.300000)/0.700000-1; - tj=1; - tj1=x; - JBCheb(x,-3.378966e+00,tj,tj1,result); - JBCheb(x,-7.802461e-01,tj,tj1,result); - JBCheb(x,1.547593e-01,tj,tj1,result); - JBCheb(x,-6.241042e-02,tj,tj1,result); - JBCheb(x,1.203274e-02,tj,tj1,result); - JBCheb(x,5.201990e-03,tj,tj1,result); - JBCheb(x,-5.125597e-03,tj,tj1,result); - JBCheb(x,1.584426e-03,tj,tj1,result); - JBCheb(x,2.546069e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=5.0000) - { - x=2*(s-2.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.828366e+00,tj,tj1,result); - JBCheb(x,-3.137533e+00,tj,tj1,result); - JBCheb(x,-5.016671e-01,tj,tj1,result); - JBCheb(x,-1.745637e-01,tj,tj1,result); - JBCheb(x,-5.189801e-02,tj,tj1,result); - JBCheb(x,-1.621610e-02,tj,tj1,result); - JBCheb(x,-6.741122e-03,tj,tj1,result); - JBCheb(x,-4.516368e-03,tj,tj1,result); - JBCheb(x,3.552085e-04,tj,tj1,result); - JBCheb(x,2.787029e-03,tj,tj1,result); - JBCheb(x,5.359774e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(5.087028e+00*(s-5.000000e+00))-1.071300e+01; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 9 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl9(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.3000) - { - x=2*(s-0.000000)/1.300000-1; - tj=1; - tj1=x; - JBCheb(x,-6.279320e-01,tj,tj1,result); - JBCheb(x,-9.277151e-01,tj,tj1,result); - JBCheb(x,-3.669339e-01,tj,tj1,result); - JBCheb(x,-7.086149e-02,tj,tj1,result); - JBCheb(x,-1.333816e-03,tj,tj1,result); - JBCheb(x,3.871249e-03,tj,tj1,result); - JBCheb(x,2.007048e-03,tj,tj1,result); - JBCheb(x,7.482245e-04,tj,tj1,result); - JBCheb(x,2.355615e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=2.0000) - { - x=2*(s-1.300000)/0.700000-1; - tj=1; - tj1=x; - JBCheb(x,-2.981430e+00,tj,tj1,result); - JBCheb(x,-7.972248e-01,tj,tj1,result); - JBCheb(x,1.747737e-01,tj,tj1,result); - JBCheb(x,-3.808530e-02,tj,tj1,result); - JBCheb(x,-7.888305e-03,tj,tj1,result); - JBCheb(x,9.001302e-03,tj,tj1,result); - JBCheb(x,-1.378767e-03,tj,tj1,result); - JBCheb(x,-1.108510e-03,tj,tj1,result); - JBCheb(x,5.915372e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=7.0000) - { - x=2*(s-2.000000)/5.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.387463e+00,tj,tj1,result); - JBCheb(x,-2.845231e+00,tj,tj1,result); - JBCheb(x,-1.809956e-01,tj,tj1,result); - JBCheb(x,-7.543461e-02,tj,tj1,result); - JBCheb(x,-4.880397e-03,tj,tj1,result); - JBCheb(x,-1.160074e-02,tj,tj1,result); - JBCheb(x,-7.356527e-03,tj,tj1,result); - JBCheb(x,-4.394428e-03,tj,tj1,result); - JBCheb(x,9.619892e-04,tj,tj1,result); - JBCheb(x,-2.758763e-04,tj,tj1,result); - JBCheb(x,4.790977e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.020952e+00*(s-7.000000e+00))-9.516623e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 10 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl10(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.2000) - { - x=2*(s-0.000000)/1.200000-1; - tj=1; - tj1=x; - JBCheb(x,-4.590993e-01,tj,tj1,result); - JBCheb(x,-6.562730e-01,tj,tj1,result); - JBCheb(x,-2.353934e-01,tj,tj1,result); - JBCheb(x,-4.069933e-02,tj,tj1,result); - JBCheb(x,-1.849151e-03,tj,tj1,result); - JBCheb(x,8.931406e-04,tj,tj1,result); - JBCheb(x,3.636295e-04,tj,tj1,result); - JBCheb(x,1.178340e-05,tj,tj1,result); - JBCheb(x,-8.917749e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=2.0000) - { - x=2*(s-1.200000)/0.800000-1; - tj=1; - tj1=x; - JBCheb(x,-2.537658e+00,tj,tj1,result); - JBCheb(x,-9.962401e-01,tj,tj1,result); - JBCheb(x,1.838715e-01,tj,tj1,result); - JBCheb(x,1.055792e-02,tj,tj1,result); - JBCheb(x,-2.580316e-02,tj,tj1,result); - JBCheb(x,1.781701e-03,tj,tj1,result); - JBCheb(x,3.770362e-03,tj,tj1,result); - JBCheb(x,-4.838983e-04,tj,tj1,result); - JBCheb(x,-6.999052e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=7.0000) - { - x=2*(s-2.000000)/5.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.337524e+00,tj,tj1,result); - JBCheb(x,-1.877029e+00,tj,tj1,result); - JBCheb(x,4.734650e-02,tj,tj1,result); - JBCheb(x,-4.249254e-02,tj,tj1,result); - JBCheb(x,3.320250e-03,tj,tj1,result); - JBCheb(x,-6.432266e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(8.711035e-01*(s-7.000000e+00))-7.212811e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 11 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl11(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.2000) - { - x=2*(s-0.000000)/1.200000-1; - tj=1; - tj1=x; - JBCheb(x,-4.339517e-01,tj,tj1,result); - JBCheb(x,-6.051558e-01,tj,tj1,result); - JBCheb(x,-2.000992e-01,tj,tj1,result); - JBCheb(x,-3.022547e-02,tj,tj1,result); - JBCheb(x,-9.808401e-04,tj,tj1,result); - JBCheb(x,5.592870e-04,tj,tj1,result); - JBCheb(x,3.575081e-04,tj,tj1,result); - JBCheb(x,2.086173e-04,tj,tj1,result); - JBCheb(x,6.089011e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=2.2500) - { - x=2*(s-1.200000)/1.050000-1; - tj=1; - tj1=x; - JBCheb(x,-2.523221e+00,tj,tj1,result); - JBCheb(x,-1.068388e+00,tj,tj1,result); - JBCheb(x,2.179661e-01,tj,tj1,result); - JBCheb(x,-1.555524e-03,tj,tj1,result); - JBCheb(x,-3.238964e-02,tj,tj1,result); - JBCheb(x,7.364320e-03,tj,tj1,result); - JBCheb(x,4.895771e-03,tj,tj1,result); - JBCheb(x,-1.762774e-03,tj,tj1,result); - JBCheb(x,-8.201340e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=8.0000) - { - x=2*(s-2.250000)/5.750000-1; - tj=1; - tj1=x; - JBCheb(x,-5.212179e+00,tj,tj1,result); - JBCheb(x,-1.684579e+00,tj,tj1,result); - JBCheb(x,8.299519e-02,tj,tj1,result); - JBCheb(x,-3.606261e-02,tj,tj1,result); - JBCheb(x,7.310869e-03,tj,tj1,result); - JBCheb(x,-3.320115e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(5.715445e-01*(s-8.000000e+00))-6.845834e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 12 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl12(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.0000) - { - x=2*(s-0.000000)/1.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.736742e-01,tj,tj1,result); - JBCheb(x,-3.657836e-01,tj,tj1,result); - JBCheb(x,-1.047209e-01,tj,tj1,result); - JBCheb(x,-1.319599e-02,tj,tj1,result); - JBCheb(x,-5.545631e-04,tj,tj1,result); - JBCheb(x,9.280445e-05,tj,tj1,result); - JBCheb(x,2.815679e-05,tj,tj1,result); - JBCheb(x,-2.213519e-05,tj,tj1,result); - JBCheb(x,1.256838e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=3.0000) - { - x=2*(s-1.000000)/2.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.573947e+00,tj,tj1,result); - JBCheb(x,-1.515287e+00,tj,tj1,result); - JBCheb(x,3.611880e-01,tj,tj1,result); - JBCheb(x,-3.271311e-02,tj,tj1,result); - JBCheb(x,-6.495815e-02,tj,tj1,result); - JBCheb(x,4.141186e-02,tj,tj1,result); - JBCheb(x,7.180886e-04,tj,tj1,result); - JBCheb(x,-1.388211e-02,tj,tj1,result); - JBCheb(x,4.890761e-03,tj,tj1,result); - JBCheb(x,3.233175e-03,tj,tj1,result); - JBCheb(x,-2.946156e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=12.0000) - { - x=2*(s-3.000000)/9.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.947819e+00,tj,tj1,result); - JBCheb(x,-2.034157e+00,tj,tj1,result); - JBCheb(x,6.878986e-02,tj,tj1,result); - JBCheb(x,-4.078603e-02,tj,tj1,result); - JBCheb(x,6.990977e-03,tj,tj1,result); - JBCheb(x,-2.866215e-03,tj,tj1,result); - JBCheb(x,3.897866e-03,tj,tj1,result); - JBCheb(x,2.512252e-03,tj,tj1,result); - JBCheb(x,2.073743e-03,tj,tj1,result); - JBCheb(x,3.022621e-03,tj,tj1,result); - JBCheb(x,1.501343e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.877243e-01*(s-1.200000e+01))-7.936839e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 13 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl13(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.0000) - { - x=2*(s-0.000000)/1.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.713276e-01,tj,tj1,result); - JBCheb(x,-3.557541e-01,tj,tj1,result); - JBCheb(x,-9.459092e-02,tj,tj1,result); - JBCheb(x,-1.044145e-02,tj,tj1,result); - JBCheb(x,-2.546132e-04,tj,tj1,result); - JBCheb(x,1.002374e-04,tj,tj1,result); - JBCheb(x,2.349456e-05,tj,tj1,result); - JBCheb(x,-7.025669e-05,tj,tj1,result); - JBCheb(x,-1.590242e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=3.0000) - { - x=2*(s-1.000000)/2.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.454383e+00,tj,tj1,result); - JBCheb(x,-1.467539e+00,tj,tj1,result); - JBCheb(x,3.270774e-01,tj,tj1,result); - JBCheb(x,-8.075763e-03,tj,tj1,result); - JBCheb(x,-6.611647e-02,tj,tj1,result); - JBCheb(x,2.990785e-02,tj,tj1,result); - JBCheb(x,8.109212e-03,tj,tj1,result); - JBCheb(x,-1.135031e-02,tj,tj1,result); - JBCheb(x,5.915919e-04,tj,tj1,result); - JBCheb(x,3.522390e-03,tj,tj1,result); - JBCheb(x,-1.144701e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=13.0000) - { - x=2*(s-3.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.736127e+00,tj,tj1,result); - JBCheb(x,-1.920809e+00,tj,tj1,result); - JBCheb(x,1.175858e-01,tj,tj1,result); - JBCheb(x,-4.002049e-02,tj,tj1,result); - JBCheb(x,1.158966e-02,tj,tj1,result); - JBCheb(x,-3.157781e-03,tj,tj1,result); - JBCheb(x,2.762172e-03,tj,tj1,result); - JBCheb(x,5.780347e-04,tj,tj1,result); - JBCheb(x,-1.193310e-03,tj,tj1,result); - JBCheb(x,-2.442421e-05,tj,tj1,result); - JBCheb(x,2.547756e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.799944e-01*(s-1.300000e+01))-7.566269e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 14 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl14(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=1.0000) - { - x=2*(s-0.000000)/1.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.698527e-01,tj,tj1,result); - JBCheb(x,-3.479081e-01,tj,tj1,result); - JBCheb(x,-8.640733e-02,tj,tj1,result); - JBCheb(x,-8.466899e-03,tj,tj1,result); - JBCheb(x,-1.469485e-04,tj,tj1,result); - JBCheb(x,2.150009e-05,tj,tj1,result); - JBCheb(x,1.965975e-05,tj,tj1,result); - JBCheb(x,-4.710210e-05,tj,tj1,result); - JBCheb(x,-1.327808e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=3.0000) - { - x=2*(s-1.000000)/2.000000-1; - tj=1; - tj1=x; - JBCheb(x,-2.350359e+00,tj,tj1,result); - JBCheb(x,-1.421365e+00,tj,tj1,result); - JBCheb(x,2.960468e-01,tj,tj1,result); - JBCheb(x,1.149167e-02,tj,tj1,result); - JBCheb(x,-6.361109e-02,tj,tj1,result); - JBCheb(x,1.976022e-02,tj,tj1,result); - JBCheb(x,1.082700e-02,tj,tj1,result); - JBCheb(x,-8.563328e-03,tj,tj1,result); - JBCheb(x,-1.453123e-03,tj,tj1,result); - JBCheb(x,2.917559e-03,tj,tj1,result); - JBCheb(x,-1.151067e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-3.000000)/12.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.746892e+00,tj,tj1,result); - JBCheb(x,-2.010441e+00,tj,tj1,result); - JBCheb(x,1.566146e-01,tj,tj1,result); - JBCheb(x,-5.129690e-02,tj,tj1,result); - JBCheb(x,1.929724e-02,tj,tj1,result); - JBCheb(x,-2.524227e-03,tj,tj1,result); - JBCheb(x,3.192933e-03,tj,tj1,result); - JBCheb(x,-4.254730e-04,tj,tj1,result); - JBCheb(x,1.620685e-03,tj,tj1,result); - JBCheb(x,7.289618e-04,tj,tj1,result); - JBCheb(x,-2.112350e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.590621e-01*(s-1.500000e+01))-7.632238e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 15 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl15(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=2.0000) - { - x=2*(s-0.000000)/2.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.043660e+00,tj,tj1,result); - JBCheb(x,-1.361653e+00,tj,tj1,result); - JBCheb(x,-3.009497e-01,tj,tj1,result); - JBCheb(x,4.951784e-02,tj,tj1,result); - JBCheb(x,4.377903e-02,tj,tj1,result); - JBCheb(x,1.003253e-02,tj,tj1,result); - JBCheb(x,-1.271309e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=5.0000) - { - x=2*(s-2.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-3.582778e+00,tj,tj1,result); - JBCheb(x,-8.349578e-01,tj,tj1,result); - JBCheb(x,9.476514e-02,tj,tj1,result); - JBCheb(x,-2.717385e-02,tj,tj1,result); - JBCheb(x,1.222591e-02,tj,tj1,result); - JBCheb(x,-6.635124e-03,tj,tj1,result); - JBCheb(x,2.815993e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=17.0000) - { - x=2*(s-5.000000)/12.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.115476e+00,tj,tj1,result); - JBCheb(x,-1.655936e+00,tj,tj1,result); - JBCheb(x,8.404310e-02,tj,tj1,result); - JBCheb(x,-2.663794e-02,tj,tj1,result); - JBCheb(x,8.868618e-03,tj,tj1,result); - JBCheb(x,1.381447e-03,tj,tj1,result); - JBCheb(x,9.444801e-04,tj,tj1,result); - JBCheb(x,-1.581503e-04,tj,tj1,result); - JBCheb(x,-9.468696e-04,tj,tj1,result); - JBCheb(x,1.728509e-03,tj,tj1,result); - JBCheb(x,1.206470e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.927937e-01*(s-1.700000e+01))-7.700983e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 16 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl16(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=2.0000) - { - x=2*(s-0.000000)/2.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.002570e+00,tj,tj1,result); - JBCheb(x,-1.298141e+00,tj,tj1,result); - JBCheb(x,-2.832803e-01,tj,tj1,result); - JBCheb(x,3.877026e-02,tj,tj1,result); - JBCheb(x,3.539436e-02,tj,tj1,result); - JBCheb(x,8.439658e-03,tj,tj1,result); - JBCheb(x,-4.756911e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=5.0000) - { - x=2*(s-2.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-3.486198e+00,tj,tj1,result); - JBCheb(x,-8.242944e-01,tj,tj1,result); - JBCheb(x,1.020002e-01,tj,tj1,result); - JBCheb(x,-3.130531e-02,tj,tj1,result); - JBCheb(x,1.512373e-02,tj,tj1,result); - JBCheb(x,-8.054876e-03,tj,tj1,result); - JBCheb(x,3.556839e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=20.0000) - { - x=2*(s-5.000000)/15.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.241608e+00,tj,tj1,result); - JBCheb(x,-1.832655e+00,tj,tj1,result); - JBCheb(x,1.340545e-01,tj,tj1,result); - JBCheb(x,-3.361143e-02,tj,tj1,result); - JBCheb(x,1.283219e-02,tj,tj1,result); - JBCheb(x,3.484549e-03,tj,tj1,result); - JBCheb(x,1.805968e-03,tj,tj1,result); - JBCheb(x,-2.057243e-03,tj,tj1,result); - JBCheb(x,-1.454439e-03,tj,tj1,result); - JBCheb(x,-2.177513e-03,tj,tj1,result); - JBCheb(x,-1.819209e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.391580e-01*(s-2.000000e+01))-7.963205e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 17 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl17(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=3.0000) - { - x=2*(s-0.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.566973e+00,tj,tj1,result); - JBCheb(x,-1.810330e+00,tj,tj1,result); - JBCheb(x,-4.840039e-02,tj,tj1,result); - JBCheb(x,2.337294e-01,tj,tj1,result); - JBCheb(x,-5.383549e-04,tj,tj1,result); - JBCheb(x,-5.556515e-02,tj,tj1,result); - JBCheb(x,-8.656965e-03,tj,tj1,result); - JBCheb(x,1.404569e-02,tj,tj1,result); - JBCheb(x,6.447867e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=6.0000) - { - x=2*(s-3.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-3.905684e+00,tj,tj1,result); - JBCheb(x,-6.222920e-01,tj,tj1,result); - JBCheb(x,4.146667e-02,tj,tj1,result); - JBCheb(x,-4.809176e-03,tj,tj1,result); - JBCheb(x,1.057028e-03,tj,tj1,result); - JBCheb(x,-1.211838e-04,tj,tj1,result); - JBCheb(x,-4.099683e-04,tj,tj1,result); - JBCheb(x,1.161105e-04,tj,tj1,result); - JBCheb(x,2.225465e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=24.0000) - { - x=2*(s-6.000000)/18.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.594282e+00,tj,tj1,result); - JBCheb(x,-1.917838e+00,tj,tj1,result); - JBCheb(x,1.455980e-01,tj,tj1,result); - JBCheb(x,-2.999589e-02,tj,tj1,result); - JBCheb(x,5.604263e-03,tj,tj1,result); - JBCheb(x,-3.484445e-03,tj,tj1,result); - JBCheb(x,-1.819937e-03,tj,tj1,result); - JBCheb(x,-2.930390e-03,tj,tj1,result); - JBCheb(x,2.771761e-04,tj,tj1,result); - JBCheb(x,-6.232581e-04,tj,tj1,result); - JBCheb(x,-7.029083e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.127771e-01*(s-2.400000e+01))-8.400197e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 18 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl18(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=3.0000) - { - x=2*(s-0.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.526802e+00,tj,tj1,result); - JBCheb(x,-1.762373e+00,tj,tj1,result); - JBCheb(x,-5.598890e-02,tj,tj1,result); - JBCheb(x,2.189437e-01,tj,tj1,result); - JBCheb(x,5.971721e-03,tj,tj1,result); - JBCheb(x,-4.823067e-02,tj,tj1,result); - JBCheb(x,-1.064501e-02,tj,tj1,result); - JBCheb(x,1.014932e-02,tj,tj1,result); - JBCheb(x,5.953513e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=6.0000) - { - x=2*(s-3.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-3.818669e+00,tj,tj1,result); - JBCheb(x,-6.070918e-01,tj,tj1,result); - JBCheb(x,4.277196e-02,tj,tj1,result); - JBCheb(x,-4.879817e-03,tj,tj1,result); - JBCheb(x,6.887357e-04,tj,tj1,result); - JBCheb(x,1.638451e-05,tj,tj1,result); - JBCheb(x,1.502800e-04,tj,tj1,result); - JBCheb(x,-3.165796e-05,tj,tj1,result); - JBCheb(x,5.034960e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=20.0000) - { - x=2*(s-6.000000)/14.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.010656e+00,tj,tj1,result); - JBCheb(x,-1.496296e+00,tj,tj1,result); - JBCheb(x,1.002227e-01,tj,tj1,result); - JBCheb(x,-2.338250e-02,tj,tj1,result); - JBCheb(x,4.137036e-03,tj,tj1,result); - JBCheb(x,-2.586202e-03,tj,tj1,result); - JBCheb(x,-9.736384e-04,tj,tj1,result); - JBCheb(x,1.332251e-03,tj,tj1,result); - JBCheb(x,1.877982e-03,tj,tj1,result); - JBCheb(x,-1.160963e-05,tj,tj1,result); - JBCheb(x,-2.547247e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.684623e-01*(s-2.000000e+01))-7.428883e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 19 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl19(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=3.0000) - { - x=2*(s-0.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.490213e+00,tj,tj1,result); - JBCheb(x,-1.719633e+00,tj,tj1,result); - JBCheb(x,-6.459123e-02,tj,tj1,result); - JBCheb(x,2.034878e-01,tj,tj1,result); - JBCheb(x,1.113868e-02,tj,tj1,result); - JBCheb(x,-4.030922e-02,tj,tj1,result); - JBCheb(x,-1.054022e-02,tj,tj1,result); - JBCheb(x,7.525623e-03,tj,tj1,result); - JBCheb(x,5.277360e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=6.0000) - { - x=2*(s-3.000000)/3.000000-1; - tj=1; - tj1=x; - JBCheb(x,-3.744750e+00,tj,tj1,result); - JBCheb(x,-5.977749e-01,tj,tj1,result); - JBCheb(x,4.223716e-02,tj,tj1,result); - JBCheb(x,-5.363889e-03,tj,tj1,result); - JBCheb(x,5.711774e-04,tj,tj1,result); - JBCheb(x,-5.557257e-04,tj,tj1,result); - JBCheb(x,4.254794e-04,tj,tj1,result); - JBCheb(x,9.034207e-05,tj,tj1,result); - JBCheb(x,5.498107e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=20.0000) - { - x=2*(s-6.000000)/14.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.872768e+00,tj,tj1,result); - JBCheb(x,-1.430689e+00,tj,tj1,result); - JBCheb(x,1.136575e-01,tj,tj1,result); - JBCheb(x,-1.726627e-02,tj,tj1,result); - JBCheb(x,3.421110e-03,tj,tj1,result); - JBCheb(x,-1.581510e-03,tj,tj1,result); - JBCheb(x,-5.559520e-04,tj,tj1,result); - JBCheb(x,-6.838208e-04,tj,tj1,result); - JBCheb(x,8.428839e-04,tj,tj1,result); - JBCheb(x,-7.170682e-04,tj,tj1,result); - JBCheb(x,-6.006647e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.539373e-01*(s-2.000000e+01))-7.206941e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 20 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl20(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.854794e+00,tj,tj1,result); - JBCheb(x,-1.948947e+00,tj,tj1,result); - JBCheb(x,1.632184e-01,tj,tj1,result); - JBCheb(x,2.139397e-01,tj,tj1,result); - JBCheb(x,-1.006237e-01,tj,tj1,result); - JBCheb(x,-3.810031e-02,tj,tj1,result); - JBCheb(x,3.573620e-02,tj,tj1,result); - JBCheb(x,9.951242e-03,tj,tj1,result); - JBCheb(x,-1.274092e-02,tj,tj1,result); - JBCheb(x,-3.464196e-03,tj,tj1,result); - JBCheb(x,4.882139e-03,tj,tj1,result); - JBCheb(x,1.575144e-03,tj,tj1,result); - JBCheb(x,-1.822804e-03,tj,tj1,result); - JBCheb(x,-7.061348e-04,tj,tj1,result); - JBCheb(x,5.908404e-04,tj,tj1,result); - JBCheb(x,1.978353e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.030989e+00,tj,tj1,result); - JBCheb(x,-1.327151e+00,tj,tj1,result); - JBCheb(x,1.346404e-01,tj,tj1,result); - JBCheb(x,-2.840051e-02,tj,tj1,result); - JBCheb(x,7.578551e-03,tj,tj1,result); - JBCheb(x,-9.813886e-04,tj,tj1,result); - JBCheb(x,5.905973e-05,tj,tj1,result); - JBCheb(x,-5.358489e-04,tj,tj1,result); - JBCheb(x,-3.450795e-04,tj,tj1,result); - JBCheb(x,-6.941157e-04,tj,tj1,result); - JBCheb(x,-7.432418e-04,tj,tj1,result); - JBCheb(x,-2.070537e-04,tj,tj1,result); - JBCheb(x,9.375654e-04,tj,tj1,result); - JBCheb(x,5.367378e-04,tj,tj1,result); - JBCheb(x,9.890859e-04,tj,tj1,result); - JBCheb(x,6.679782e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-7.015854e+00,tj,tj1,result); - JBCheb(x,-7.487737e-01,tj,tj1,result); - JBCheb(x,2.244254e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.318007e-01*(s-2.500000e+01))-7.742185e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 30 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl30(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.630822e+00,tj,tj1,result); - JBCheb(x,-1.724298e+00,tj,tj1,result); - JBCheb(x,7.872756e-02,tj,tj1,result); - JBCheb(x,1.658268e-01,tj,tj1,result); - JBCheb(x,-3.573597e-02,tj,tj1,result); - JBCheb(x,-2.994157e-02,tj,tj1,result); - JBCheb(x,5.994825e-03,tj,tj1,result); - JBCheb(x,7.394303e-03,tj,tj1,result); - JBCheb(x,-5.785029e-04,tj,tj1,result); - JBCheb(x,-1.990264e-03,tj,tj1,result); - JBCheb(x,-1.037838e-04,tj,tj1,result); - JBCheb(x,6.755546e-04,tj,tj1,result); - JBCheb(x,1.774473e-04,tj,tj1,result); - JBCheb(x,-2.821395e-04,tj,tj1,result); - JBCheb(x,-1.392603e-04,tj,tj1,result); - JBCheb(x,1.353313e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.539322e+00,tj,tj1,result); - JBCheb(x,-1.197018e+00,tj,tj1,result); - JBCheb(x,1.396848e-01,tj,tj1,result); - JBCheb(x,-2.804293e-02,tj,tj1,result); - JBCheb(x,6.867928e-03,tj,tj1,result); - JBCheb(x,-2.768758e-03,tj,tj1,result); - JBCheb(x,5.211792e-04,tj,tj1,result); - JBCheb(x,4.925799e-04,tj,tj1,result); - JBCheb(x,5.046235e-04,tj,tj1,result); - JBCheb(x,-9.536469e-05,tj,tj1,result); - JBCheb(x,-6.489642e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.263462e+00,tj,tj1,result); - JBCheb(x,-6.177316e-01,tj,tj1,result); - JBCheb(x,2.590637e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.028212e-01*(s-2.500000e+01))-6.855288e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 50 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl50(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.436279e+00,tj,tj1,result); - JBCheb(x,-1.519711e+00,tj,tj1,result); - JBCheb(x,1.148699e-02,tj,tj1,result); - JBCheb(x,1.001204e-01,tj,tj1,result); - JBCheb(x,-3.207620e-03,tj,tj1,result); - JBCheb(x,-1.034778e-02,tj,tj1,result); - JBCheb(x,-1.220322e-03,tj,tj1,result); - JBCheb(x,1.033260e-03,tj,tj1,result); - JBCheb(x,2.588280e-04,tj,tj1,result); - JBCheb(x,-1.851653e-04,tj,tj1,result); - JBCheb(x,-1.287733e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.234645e+00,tj,tj1,result); - JBCheb(x,-1.189127e+00,tj,tj1,result); - JBCheb(x,1.429738e-01,tj,tj1,result); - JBCheb(x,-3.058822e-02,tj,tj1,result); - JBCheb(x,9.086776e-03,tj,tj1,result); - JBCheb(x,-1.445783e-03,tj,tj1,result); - JBCheb(x,1.311671e-03,tj,tj1,result); - JBCheb(x,-7.261298e-04,tj,tj1,result); - JBCheb(x,6.496987e-04,tj,tj1,result); - JBCheb(x,2.605249e-04,tj,tj1,result); - JBCheb(x,8.162282e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.921095e+00,tj,tj1,result); - JBCheb(x,-5.888603e-01,tj,tj1,result); - JBCheb(x,3.080113e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(9.313116e-02*(s-2.500000e+01))-6.479154e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 65 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl65(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.360024e+00,tj,tj1,result); - JBCheb(x,-1.434631e+00,tj,tj1,result); - JBCheb(x,-6.514580e-03,tj,tj1,result); - JBCheb(x,7.332038e-02,tj,tj1,result); - JBCheb(x,1.158197e-03,tj,tj1,result); - JBCheb(x,-5.121233e-03,tj,tj1,result); - JBCheb(x,-1.051056e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.148601e+00,tj,tj1,result); - JBCheb(x,-1.214233e+00,tj,tj1,result); - JBCheb(x,1.487977e-01,tj,tj1,result); - JBCheb(x,-3.424720e-02,tj,tj1,result); - JBCheb(x,1.116715e-02,tj,tj1,result); - JBCheb(x,-4.043152e-03,tj,tj1,result); - JBCheb(x,1.718149e-03,tj,tj1,result); - JBCheb(x,-1.313701e-03,tj,tj1,result); - JBCheb(x,3.097305e-04,tj,tj1,result); - JBCheb(x,2.181031e-04,tj,tj1,result); - JBCheb(x,1.256975e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.858951e+00,tj,tj1,result); - JBCheb(x,-5.895179e-01,tj,tj1,result); - JBCheb(x,2.933237e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(9.443768e-02*(s-2.500000e+01))-6.419137e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 100 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl100(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.257021e+00,tj,tj1,result); - JBCheb(x,-1.313418e+00,tj,tj1,result); - JBCheb(x,-1.628931e-02,tj,tj1,result); - JBCheb(x,4.264287e-02,tj,tj1,result); - JBCheb(x,1.518487e-03,tj,tj1,result); - JBCheb(x,-1.499826e-03,tj,tj1,result); - JBCheb(x,-4.836044e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.056508e+00,tj,tj1,result); - JBCheb(x,-1.279690e+00,tj,tj1,result); - JBCheb(x,1.665746e-01,tj,tj1,result); - JBCheb(x,-4.290012e-02,tj,tj1,result); - JBCheb(x,1.487632e-02,tj,tj1,result); - JBCheb(x,-5.704465e-03,tj,tj1,result); - JBCheb(x,2.211669e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.866099e+00,tj,tj1,result); - JBCheb(x,-6.399767e-01,tj,tj1,result); - JBCheb(x,2.498208e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.080097e-01*(s-2.500000e+01))-6.481094e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 130 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl130(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.207999e+00,tj,tj1,result); - JBCheb(x,-1.253864e+00,tj,tj1,result); - JBCheb(x,-1.618032e-02,tj,tj1,result); - JBCheb(x,3.112729e-02,tj,tj1,result); - JBCheb(x,1.210546e-03,tj,tj1,result); - JBCheb(x,-4.732602e-04,tj,tj1,result); - JBCheb(x,-2.410527e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.026324e+00,tj,tj1,result); - JBCheb(x,-1.331990e+00,tj,tj1,result); - JBCheb(x,1.779129e-01,tj,tj1,result); - JBCheb(x,-4.674749e-02,tj,tj1,result); - JBCheb(x,1.669077e-02,tj,tj1,result); - JBCheb(x,-5.679136e-03,tj,tj1,result); - JBCheb(x,8.833221e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-5.893951e+00,tj,tj1,result); - JBCheb(x,-6.475304e-01,tj,tj1,result); - JBCheb(x,3.116734e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.045722e-01*(s-2.500000e+01))-6.510314e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 200 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl200(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.146155e+00,tj,tj1,result); - JBCheb(x,-1.177398e+00,tj,tj1,result); - JBCheb(x,-1.297970e-02,tj,tj1,result); - JBCheb(x,1.869745e-02,tj,tj1,result); - JBCheb(x,1.717288e-04,tj,tj1,result); - JBCheb(x,-1.982108e-04,tj,tj1,result); - JBCheb(x,6.427636e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.034235e+00,tj,tj1,result); - JBCheb(x,-1.455006e+00,tj,tj1,result); - JBCheb(x,1.942996e-01,tj,tj1,result); - JBCheb(x,-4.973795e-02,tj,tj1,result); - JBCheb(x,1.418812e-02,tj,tj1,result); - JBCheb(x,-3.156778e-03,tj,tj1,result); - JBCheb(x,4.896705e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.086071e+00,tj,tj1,result); - JBCheb(x,-7.152176e-01,tj,tj1,result); - JBCheb(x,3.725393e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.132404e-01*(s-2.500000e+01))-6.764034e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 301 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl301(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.104290e+00,tj,tj1,result); - JBCheb(x,-1.125800e+00,tj,tj1,result); - JBCheb(x,-9.595847e-03,tj,tj1,result); - JBCheb(x,1.219666e-02,tj,tj1,result); - JBCheb(x,1.502210e-04,tj,tj1,result); - JBCheb(x,-6.414543e-05,tj,tj1,result); - JBCheb(x,6.754115e-05,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.065955e+00,tj,tj1,result); - JBCheb(x,-1.582060e+00,tj,tj1,result); - JBCheb(x,2.004472e-01,tj,tj1,result); - JBCheb(x,-4.709092e-02,tj,tj1,result); - JBCheb(x,1.105779e-02,tj,tj1,result); - JBCheb(x,1.197391e-03,tj,tj1,result); - JBCheb(x,-8.386780e-04,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.311384e+00,tj,tj1,result); - JBCheb(x,-7.918763e-01,tj,tj1,result); - JBCheb(x,3.626584e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.293626e-01*(s-2.500000e+01))-7.066995e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 501 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl501(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.067426e+00,tj,tj1,result); - JBCheb(x,-1.079765e+00,tj,tj1,result); - JBCheb(x,-5.463005e-03,tj,tj1,result); - JBCheb(x,6.875659e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.127574e+00,tj,tj1,result); - JBCheb(x,-1.740694e+00,tj,tj1,result); - JBCheb(x,2.044502e-01,tj,tj1,result); - JBCheb(x,-3.746714e-02,tj,tj1,result); - JBCheb(x,3.810594e-04,tj,tj1,result); - JBCheb(x,1.197111e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.628194e+00,tj,tj1,result); - JBCheb(x,-8.846221e-01,tj,tj1,result); - JBCheb(x,4.386405e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.418332e-01*(s-2.500000e+01))-7.468952e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 701 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl701(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.050999e+00,tj,tj1,result); - JBCheb(x,-1.059769e+00,tj,tj1,result); - JBCheb(x,-3.922680e-03,tj,tj1,result); - JBCheb(x,4.847054e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.192182e+00,tj,tj1,result); - JBCheb(x,-1.860007e+00,tj,tj1,result); - JBCheb(x,1.963942e-01,tj,tj1,result); - JBCheb(x,-2.838711e-02,tj,tj1,result); - JBCheb(x,-2.893112e-04,tj,tj1,result); - JBCheb(x,2.159788e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-6.917851e+00,tj,tj1,result); - JBCheb(x,-9.817020e-01,tj,tj1,result); - JBCheb(x,5.383727e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(1.532706e-01*(s-2.500000e+01))-7.845715e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tabulation at the size of the array is 1401 | -//+------------------------------------------------------------------+ -static double CJarqueBera::JBTbl1401(const double s) - { -//--- create variables - double result=0; - double x; - double tj; - double tj1; -//--- check - if(s<=4.0000) - { - x=2*(s-0.000000)/4.000000-1; - tj=1; - tj1=x; - JBCheb(x,-1.026266e+00,tj,tj1,result); - JBCheb(x,-1.030061e+00,tj,tj1,result); - JBCheb(x,-1.259222e-03,tj,tj1,result); - JBCheb(x,2.536254e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=15.0000) - { - x=2*(s-4.000000)/11.000000-1; - tj=1; - tj1=x; - JBCheb(x,-4.329849e+00,tj,tj1,result); - JBCheb(x,-2.095443e+00,tj,tj1,result); - JBCheb(x,1.759363e-01,tj,tj1,result); - JBCheb(x,-7.751359e-03,tj,tj1,result); - JBCheb(x,-6.124368e-03,tj,tj1,result); - JBCheb(x,-1.793114e-03,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } -//--- check - if(s<=25.0000) - { - x=2*(s-15.000000)/10.000000-1; - tj=1; - tj1=x; - JBCheb(x,-7.544330e+00,tj,tj1,result); - JBCheb(x,-1.225382e+00,tj,tj1,result); - JBCheb(x,5.392349e-02,tj,tj1,result); - //--- check - if(result>0) - result=0; - //--- return result - return(result); - } - result=-(2.019375e-01*(s-2.500000e+01))-8.715788e+00; -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Mann-Whitney U-test | -//+------------------------------------------------------------------+ -class CMannWhitneyU - { -private: - static void UCheb(const double x,const double c,double &tj,double &tj1,double &r); - static double UThreePointInterpolate(const double p1,const double p2,const double p3,const int n); - static double USigma(double s,const int n1,const int n2); - static double USigma000(const int n1,const int n2); - static double USigma075(const int n1,const int n2); - static double USigma150(const int n1,const int n2); - static double USigma225(const int n1,const int n2); - static double USigma300(const int n1,const int n2); - static double USigma333(const int n1,const int n2); - static double USigma367(const int n1,const int n2); - static double USigma400(const int n1,const int n2); - static double UTbln5n5(const double s); - static double UTbln5n6(const double s); - static double UTbln5n7(const double s); - static double UTbln5n8(const double s); - static double UTbln5n9(const double s); - static double UTbln5n10(const double s); - static double UTbln5n11(const double s); - static double UTbln5n12(const double s); - static double UTbln5n13(const double s); - static double UTbln5n14(const double s); - static double UTbln5n15(const double s); - static double UTbln5n16(const double s); - static double UTbln5n17(const double s); - static double UTbln5n18(const double s); - static double UTbln5n19(const double s); - static double UTbln5n20(const double s); - static double UTbln5n21(const double s); - static double UTbln5n22(const double s); - static double UTbln5n23(const double s); - static double UTbln5n24(const double s); - static double UTbln5n25(const double s); - static double UTbln5n26(const double s); - static double UTbln5n27(const double s); - static double UTbln5n28(const double s); - static double UTbln5n29(const double s); - static double UTbln5n30(const double s); - static double UTbln5n100(const double s); - static double UTbln6n6(const double s); - static double UTbln6n7(const double s); - static double UTbln6n8(const double s); - static double UTbln6n9(const double s); - static double UTbln6n10(const double s); - static double UTbln6n11(const double s); - static double UTbln6n12(const double s); - static double UTbln6n13(const double s); - static double UTbln6n14(const double s); - static double UTbln6n15(const double s); - static double UTbln6n30(const double s); - static double UTbln6n100(const double s); - static double UTbln7n7(const double s); - static double UTbln7n8(const double s); - static double UTbln7n9(const double s); - static double UTbln7n10(const double s); - static double UTbln7n11(const double s); - static double UTbln7n12(const double s); - static double UTbln7n13(const double s); - static double UTbln7n14(const double s); - static double UTbln7n15(const double s); - static double UTbln7n30(const double s); - static double UTbln7n100(const double s); - static double UTbln8n8(const double s); - static double UTbln8n9(const double s); - static double UTbln8n10(const double s); - static double UTbln8n11(const double s); - static double UTbln8n12(const double s); - static double UTbln8n13(const double s); - static double UTbln8n14(const double s); - static double UTbln8n15(const double s); - static double UTbln8n30(const double s); - static double UTbln8n100(const double s); - static double UTbln9n9(const double s); - static double UTbln9n10(const double s); - static double UTbln9n11(const double s); - static double UTbln9n12(const double s); - static double UTbln9n13(const double s); - static double UTbln9n14(const double s); - static double UTbln9n15(const double s); - static double UTbln9n30(const double s); - static double UTbln9n100(const double s); - static double UTbln10n10(const double s); - static double UTbln10n11(const double s); - static double UTbln10n12(const double s); - static double UTbln10n13(const double s); - static double UTbln10n14(const double s); - static double UTbln10n15(const double s); - static double UTbln10n30(const double s); - static double UTbln10n100(const double s); - static double UTbln11n11(const double s); - static double UTbln11n12(const double s); - static double UTbln11n13(const double s); - static double UTbln11n14(const double s); - static double UTbln11n15(const double s); - static double UTbln11n30(const double s); - static double UTbln11n100(const double s); - static double UTbln12n12(const double s); - static double UTbln12n13(const double s); - static double UTbln12n14(const double s); - static double UTbln12n15(const double s); - static double UTbln12n30(const double s); - static double UTbln12n100(const double s); - static double UTbln13n13(const double s); - static double UTbln13n14(const double s); - static double UTbln13n15(const double s); - static double UTbln13n30(const double s); - static double UTbln13n100(const double s); - static double UTbln14n14(const double s); - static double UTbln14n15(const double s); - static double UTbln14n30(const double s); - static double UTbln14n100(const double s); -public: - //--- constructor, destructor - CMannWhitneyU(void); - ~CMannWhitneyU(void); - //--- method - static void CMannWhitneyUTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMannWhitneyU::CMannWhitneyU(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMannWhitneyU::~CMannWhitneyU(void) - { - - } -//+------------------------------------------------------------------+ -//| Mann-Whitney U-test | -//| This test checks hypotheses about whether X and Y are samples of | -//| two continuous distributions of the same shape and same median or| -//| whether their medians are different. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - the medians are equal) | -//| * left-tailed test (null hypothesis - the median of the first| -//| sample is greater than or equal to the median of the second| -//| sample) | -//| * right-tailed test (null hypothesis - the median of the | -//| first sample is less than or equal to the median of the | -//| second sample). | -//| Requirements: | -//| * the samples are independent | -//| * X and Y are continuous distributions (or discrete | -//| distributions well- approximating continuous distributions)| -//| * distributions of X and Y have the same shape. The only | -//| possible difference is their position (i.e. the value of | -//| the median) | -//| * the number of elements in each sample is not less than 5 | -//| * the scale of measurement should be ordinal, interval or | -//| ratio (i.e. the test could not be applied to nominal | -//| variables). | -//| The test is non-parametric and doesn't require distributions to | -//| be normal. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - size of the sample. N>=5 | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - size of the sample. M>=5 | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| To calculate p-values, special approximation is used. This | -//| method lets us calculate p-values with satisfactory accuracy in | -//| interval [0.0001, 1]. There is no approximation outside the | -//| [0.0001, 1] interval. Therefore, if the significance level | -//| outlies this interval, the test returns 0.0001. | -//| Relative precision of approximation of p-value: | -//| N M Max.err. Rms.err. | -//| 5..10 N..10 1.4e-02 6.0e-04 | -//| 5..10 N..100 2.2e-02 5.3e-06 | -//| 10..15 N..15 1.0e-02 3.2e-04 | -//| 10..15 N..100 1.0e-02 2.2e-05 | -//| 15..100 N..100 6.1e-03 2.7e-06 | -//| For N,M>100 accuracy checks weren't put into practice, but taking| -//| into account characteristics of asymptotic approximation used, | -//| precision should not be sharply different from the values for | -//| interval [5, 100]. | -//+------------------------------------------------------------------+ -static void CMannWhitneyU::CMannWhitneyUTest(const double &x[],const int n, - const double &y[],const int m, - double &bothTails,double &leftTail, - double &rightTail) - { -//--- Prepare - if(n<=4 || m<=4) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - return; - } -//--- create variables - int i=0; - int j=0; - int k=0; - int t=0; - double tmp=0; - int tmpi=0; - int ns=n+m; - double r[]; - int c[]; - double u=0; - double p=0; - double mp=0; - double s=0; - double sigma=0; - double mu=0; - int tiecount=0; - int tiesize[]; -//--- allocation - ArrayResizeAL(r,ns); - ArrayResizeAL(c,ns); -//--- fiiling arrays - for(i=0;i=r[t-1]) - t=1; - else - { - //--- change positions - tmp=r[k-1]; - r[k-1]=r[t-1]; - r[t-1]=tmp; - tmpi=c[k-1]; - c[k-1]=c[t-1]; - c[t-1]=tmpi; - t=k; - } - } - i++; - } - while(i<=ns); - //--- change value - i=ns-1; - do - { - //--- change positions - tmp=r[i]; - r[i]=r[0]; - r[0]=tmp; - tmpi=c[i]; - c[i]=c[0]; - c[0]=tmpi; - t=1; - //--- cycle - while(t!=0) - { - k=2*t; - //--- check - if(k>i) - t=0; - else - { - //--- check - if(kr[k-1]) - k++; - //--- check - if(r[t-1]>=r[k-1]) - t=0; - else - { - //--- change positions - tmp=r[k-1]; - r[k-1]=r[t-1]; - r[t-1]=tmp; - tmpi=c[k-1]; - c[k-1]=c[t-1]; - c[t-1]=tmpi; - t=k; - } - } - } - i--; - } - while(i>=1); - } -//--- compute tied ranks - i=0; - tiecount=0; - ArrayResizeAL(tiesize,ns-1+1); -//--- cycle - while(i29) - { - f0=UTbln5n15(s); - f1=UTbln5n30(s); - f2=UTbln5n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=6,n2=6,7,8... - if(MathMin(n1,n2)==6) - { - //--- check - if(MathMax(n1,n2)==6) - return(UTbln6n6(s)); - //--- check - if(MathMax(n1,n2)==7) - return(UTbln6n7(s)); - //--- check - if(MathMax(n1,n2)==8) - return(UTbln6n8(s)); - //--- check - if(MathMax(n1,n2)==9) - return(UTbln6n9(s)); - //--- check - if(MathMax(n1,n2)==10) - return(UTbln6n10(s)); - //--- check - if(MathMax(n1,n2)==11) - return(UTbln6n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln6n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln6n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln6n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln6n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln6n15(s); - f1=UTbln6n30(s); - f2=UTbln6n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=7,n2=7,8,9... - if(MathMin(n1,n2)==7) - { - //--- check - if(MathMax(n1,n2)==7) - return(UTbln7n7(s)); - //--- check - if(MathMax(n1,n2)==8) - return(UTbln7n8(s)); - //--- check - if(MathMax(n1,n2)==9) - return(UTbln7n9(s)); - //--- check - if(MathMax(n1,n2)==10) - return(UTbln7n10(s)); - //--- check - if(MathMax(n1,n2)==11) - return(UTbln7n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln7n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln7n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln7n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln7n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln7n15(s); - f1=UTbln7n30(s); - f2=UTbln7n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=8,n2=8,9,10... - if(MathMin(n1,n2)==8) - { - //--- check - if(MathMax(n1,n2)==8) - return(UTbln8n8(s)); - //--- check - if(MathMax(n1,n2)==9) - return(UTbln8n9(s)); - //--- check - if(MathMax(n1,n2)==10) - return(UTbln8n10(s)); - //--- check - if(MathMax(n1,n2)==11) - return(UTbln8n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln8n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln8n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln8n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln8n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln8n15(s); - f1=UTbln8n30(s); - f2=UTbln8n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=9,n2=9,10,11... - if(MathMin(n1,n2)==9) - { - //--- check - if(MathMax(n1,n2)==9) - return(UTbln9n9(s)); - //--- check - if(MathMax(n1,n2)==10) - return(UTbln9n10(s)); - //--- check - if(MathMax(n1,n2)==11) - return(UTbln9n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln9n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln9n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln9n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln9n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln9n15(s); - f1=UTbln9n30(s); - f2=UTbln9n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=10,n2=10,11,12... - if(MathMin(n1,n2)==10) - { - //--- check - if(MathMax(n1,n2)==10) - return(UTbln10n10(s)); - //--- check - if(MathMax(n1,n2)==11) - return(UTbln10n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln10n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln10n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln10n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln10n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln10n15(s); - f1=UTbln10n30(s); - f2=UTbln10n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=11,n2=11,12,13... - if(MathMin(n1,n2)==11) - { - //--- check - if(MathMax(n1,n2)==11) - return(UTbln11n11(s)); - //--- check - if(MathMax(n1,n2)==12) - return(UTbln11n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln11n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln11n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln11n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln11n15(s); - f1=UTbln11n30(s); - f2=UTbln11n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=12,n2=12,13,14... - if(MathMin(n1,n2)==12) - { - //--- check - if(MathMax(n1,n2)==12) - return(UTbln12n12(s)); - //--- check - if(MathMax(n1,n2)==13) - return(UTbln12n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln12n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln12n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln12n15(s); - f1=UTbln12n30(s); - f2=UTbln12n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=13,n2=13,14,15... - if(MathMin(n1,n2)==13) - { - //--- check - if(MathMax(n1,n2)==13) - return(UTbln13n13(s)); - //--- check - if(MathMax(n1,n2)==14) - return(UTbln13n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln13n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln13n15(s); - f1=UTbln13n30(s); - f2=UTbln13n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1=14,n2=14,15... - if(MathMin(n1,n2)==14) - { - //--- check - if(MathMax(n1,n2)==14) - return(UTbln14n14(s)); - //--- check - if(MathMax(n1,n2)==15) - return(UTbln14n15(s)); - //--- check - if(MathMax(n1,n2)>15) - { - f0=UTbln14n15(s); - f1=UTbln14n30(s); - f2=UTbln14n100(s); - //--- return result - return(UThreePointInterpolate(f0,f1,f2,MathMax(n1,n2))); - } - } -//--- n1>=15,n2>=15... - if(s>4) - s=4; -//--- check - if(s<3) - { - //--- calculation - s0=0.000000e+00; - f0=USigma000(n1,n2); - s1=7.500000e-01; - f1=USigma075(n1,n2); - s2=1.500000e+00; - f2=USigma150(n1,n2); - s3=2.250000e+00; - f3=USigma225(n1,n2); - s4=3.000000e+00; - f4=USigma300(n1,n2); - //--- calculation result - f1=((s-s0)*f1-(s-s1)*f0)/(s1-s0); - f2=((s-s0)*f2-(s-s2)*f0)/(s2-s0); - f3=((s-s0)*f3-(s-s3)*f0)/(s3-s0); - f4=((s-s0)*f4-(s-s4)*f0)/(s4-s0); - f2=((s-s1)*f2-(s-s2)*f1)/(s2-s1); - f3=((s-s1)*f3-(s-s3)*f1)/(s3-s1); - f4=((s-s1)*f4-(s-s4)*f1)/(s4-s1); - f3=((s-s2)*f3-(s-s3)*f2)/(s3-s2); - f4=((s-s2)*f4-(s-s4)*f2)/(s4-s2); - f4=((s-s3)*f4-(s-s4)*f3)/(s4-s3); - //--- return result - return(f4); - } -//--- else - s0=3.000000e+00; - f0=USigma300(n1,n2); - s1=3.333333e+00; - f1=USigma333(n1,n2); - s2=3.666667e+00; - f2=USigma367(n1,n2); - s3=4.000000e+00; - f3=USigma400(n1,n2); -//--- calculation result - f1=((s-s0)*f1-(s-s1)*f0)/(s1-s0); - f2=((s-s0)*f2-(s-s2)*f0)/(s2-s0); - f3=((s-s0)*f3-(s-s3)*f0)/(s3-s0); - f2=((s-s1)*f2-(s-s2)*f1)/(s2-s1); - f3=((s-s1)*f3-(s-s3)*f1)/(s3-s1); - f3=((s-s2)*f3-(s-s3)*f2)/(s3-s2); -//--- return result - return(f3); - } -//+------------------------------------------------------------------+ -//| Sign test | -//+------------------------------------------------------------------+ -class CSignTest - { -public: - //--- constructor, destructor - CSignTest(void); - ~CSignTest(void); - //--- method - static void OneSampleSignTest(const double &x[],const int n,const double median,double &bothTails,double &leftTail,double &rightTail); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSignTest::CSignTest(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSignTest::~CSignTest(void) - { - - } -//+------------------------------------------------------------------+ -//| Sign test | -//| This test checks three hypotheses about the median of the given | -//| sample. | -//| The following tests are performed: | -//| * two-tailed test (null hypothesis - the median is equal to | -//| the given value) | -//| * left-tailed test (null hypothesis - the median is greater | -//| than or equal to the given value) | -//| * right-tailed test (null hypothesis - the median is less | -//| than or equal to the given value) | -//| Requirements: | -//| * the scale of measurement should be ordinal, interval or | -//| ratio (i.e. the test could not be applied to nominal | -//| variables). | -//| The test is non-parametric and doesn't require distribution X to | -//| be normal | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of the sample. | -//| Median - assumed median value. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance levelthe null hypothesis is | -//| rejected. | -//| While calculating p-values high-precision binomial distribution | -//| approximation is used, so significance levels have about 15 exact| -//| digits. | -//+------------------------------------------------------------------+ -static void CSignTest::OneSampleSignTest(const double &x[],const int n, - const double median,double &bothTails, - double &leftTail,double &rightTail) - { -//--- check - if(n<=1) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - return; - } -//--- Calculate: -//--- GTCnt - count of x[i]>Median -//--- NECnt - count of x[i]<>Median - int i; - int greater=0; - int noteql=0; -//--- calculation - for(i=0;imedian) - greater++; - //--- check - if(x[i]!=median) - noteql++; - } -//--- check - if(noteql==0) - { - bothTails=0.0; - leftTail=0.0; - rightTail=0.0; - return; - } -//--- calculation - bothTails=2*CBinomialDistr::BinomialDistribution(MathMin(greater,noteql-greater),noteql,0.5); - leftTail=CBinomialDistr::BinomialDistribution(greater,noteql,0.5); - rightTail=CBinomialDistr::BinomialComplDistribution(greater-1,noteql,0.5); - } -//+------------------------------------------------------------------+ -//| Studentt tests | -//+------------------------------------------------------------------+ -class CStudentTests - { -public: - //--- constructor, destructor - CStudentTests(void); - ~CStudentTests(void); - //--- methods - static void StudentTest1(const double &x[],const int n,const double mean,double &bothTails,double &leftTail,double &rightTail); - static void StudentTest2(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - static void UnequalVarianceTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CStudentTests::CStudentTests(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CStudentTests::~CStudentTests(void) - { - - } -//+------------------------------------------------------------------+ -//| One-sample t-test | -//| This test checks three hypotheses about the mean of the given | -//| sample. The following tests are performed: | -//| * two-tailed test (null hypothesis - the mean is equal to the| -//| given value) | -//| * left-tailed test (null hypothesis - the mean is greater | -//| than or equal to the given value) | -//| * right-tailed test (null hypothesis - the mean is less than | -//| or equal to the given value). | -//| The test is based on the assumption that a given sample has a | -//| normal distribution and an unknown dispersion. If the | -//| distribution sharply differs from normal, the test will work | -//| incorrectly. | -//| Input parameters: | -//| X - sample. Array whose index goes from 0 to N-1. | -//| N - size of sample. | -//| Mean - assumed value of the mean. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CStudentTests::StudentTest1(const double &x[],const int n, - const double mean,double &bothTails, - double &leftTail,double &rightTail) - { -//--- check - if(n<=1) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - //--- exit the function - return; - } -//--- create variables - int i; - double xmean; - double xvariance=0; - double xstddev=0; - double v1=0; - double v2=0; - double stat=0; - double s=0; -//--- Mean - xmean=0; - for(i=0;i0) - p=1-0.5*CIncBetaF::IncompleteBeta(df/2,0.5,df/(df+CMath::Sqr(stat))); - else - p=0.5*CIncBetaF::IncompleteBeta(df/2,0.5,df/(df+CMath::Sqr(stat))); -//--- get parameters - bothTails=2*MathMin(p,1-p); - leftTail=p; - rightTail=1-p; - } -//+------------------------------------------------------------------+ -//| Variance tests | -//+------------------------------------------------------------------+ -class CVarianceTests - { -public: - //--- constructor, destructor - CVarianceTests(void); - ~CVarianceTests(void); - //--- method - static void FTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail); - static void OneSampleVarianceTest(const double &x[],const int n,const double variance,double &bothTails,double &leftTail,double &rightTail); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CVarianceTests::CVarianceTests(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CVarianceTests::~CVarianceTests(void) - { - - } -//+------------------------------------------------------------------+ -//| Two-sample F-test | -//| This test checks three hypotheses about dispersions of the given | -//| samples. The following tests are performed: | -//| * two-tailed test (null hypothesis - the dispersions are | -//| equal) | -//| * left-tailed test (null hypothesis - the dispersion of the | -//| first sample is greater than or equal to the dispersion of | -//| the second sample). | -//| * right-tailed test (null hypothesis - the dispersion of the | -//| first sample is less than or equal to the dispersion of | -//| the second sample) | -//| The test is based on the following assumptions: | -//| * the given samples have normal distributions | -//| * the samples are independent. | -//| Input parameters: | -//| X - sample 1. Array whose index goes from 0 to N-1. | -//| N - sample size. | -//| Y - sample 2. Array whose index goes from 0 to M-1. | -//| M - sample size. | -//| Output parameters: | -//| BothTails - p-value for two-tailed test. | -//| If BothTails is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//| LeftTail - p-value for left-tailed test. | -//| If LeftTail is less than the given | -//| significance level, the null hypothesis is | -//| rejected. | -//| RightTail - p-value for right-tailed test. | -//| If RightTail is less than the given | -//| significance level the null hypothesis is | -//| rejected. | -//+------------------------------------------------------------------+ -static void CVarianceTests::FTest(const double &x[],const int n,const double &y[], - const int m,double &bothTails,double &leftTail, - double &rightTail) - { -//--- check - if(n<=2 || m<=2) - { - bothTails=1.0; - leftTail=1.0; - rightTail=1.0; - //--- exit the function - return; - } -//--- create variables - int i; - double xmean=0; - double ymean=0; - double xvar=0; - double yvar=0; - int df1=0; - int df2=0; - double stat=0; -//--- Mean - for(i=0; i<=n-1; i++) - xmean+=x[i]; - xmean=xmean/n; - for(i=0; i<=m-1; i++) - ymean+=y[i]; - ymean=ymean/m; -//--- Variance (using corrected two-pass algorithm) - for(i=0;i=r[t-1]) - t=1; - else - { - //--- change values - tmp=r[k-1]; - r[k-1]=r[t-1]; - r[t-1]=tmp; - tmpi=c[k-1]; - c[k-1]=c[t-1]; - c[t-1]=tmpi; - t=k; - } - } - i++; - } - while(i<=ns); - //--- change value - i=ns-1; - //--- cycle - do - { - //--- change values - tmp=r[i]; - r[i]=r[0]; - r[0]=tmp; - tmpi=c[i]; - c[i]=c[0]; - c[0]=tmpi; - t=1; - //--- cycle - while(t!=0) - { - k=2*t; - //--- check - if(k>i) - t=0; - else - { - //--- check - if(kr[k-1]) - k++; - } - //--- check - if(r[t-1]>=r[k-1]) - t=0; - else - { - //--- change values - tmp=r[k-1]; - r[k-1]=r[t-1]; - r[t-1]=tmp; - tmpi=c[k-1]; - c[k-1]=c[t-1]; - c[t-1]=tmpi; - t=k; - } - } - } - i--; - } - while(i>=1); - } -//--- compute tied ranks - i=0; - while(ie) - w+=r[i]; - } -//--- Result - mu=(double)(ns*(ns+1))/4.0; - sigma=MathSqrt((double)(ns*(ns+1)*(2*ns+1))/24.0); - s=(w-mu)/sigma; -//--- check - if(s<=0) - { - p=MathExp(WSigma(-((w-mu)/sigma),ns)); - mp=1-MathExp(WSigma(-((w-1-mu)/sigma),ns)); - } - else - { - mp=MathExp(WSigma((w-mu)/sigma,ns)); - p=1-MathExp(WSigma((w+1-mu)/sigma,ns)); - } -//--- get parameters - bothTails=MathMax(2*MathMin(p,mp),1.0E-4); - leftTail=MathMax(p,1.0E-4); - rightTail=MathMax(mp,1.0E-4); - } -//+------------------------------------------------------------------+ -//| Sequential Chebyshev interpolation. | -//+------------------------------------------------------------------+ -static void CWilcoxonSignedRank::WCheb(const double x,const double c, - double &tj,double &tj1,double &r) - { -//--- create a variable - double t; -//--- change values - r+=c*tj; - t=2*x*tj1-tj; - tj=tj1; - tj1=t; - } -//+------------------------------------------------------------------+ -//| Tail(S, 5) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W5(const double s) - { -//--- create variables - int w=0; - double r=0; - w=(int)MathRound(-(3.708099e+00*s)+7.500000e+00); -//--- check - if(w>=7) - r=-6.931e-01; -//--- check - if(w==6) - r=-9.008e-01; -//--- check - if(w==5) - r=-1.163e+00; -//--- check - if(w==4) - r=-1.520e+00; -//--- check - if(w==3) - r=-1.856e+00; -//--- check - if(w==2) - r=-2.367e+00; -//--- check - if(w==1) - r=-2.773e+00; -//--- check - if(w<=0) - r=-3.466e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 6) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W6(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(4.769696e+00*s)+1.050000e+01); - if(w>=10) - r=-6.931e-01; -//--- check - if(w==9) - r=-8.630e-01; -//--- check - if(w==8) - r=-1.068e+00; -//--- check - if(w==7) - r=-1.269e+00; -//--- check - if(w==6) - r=-1.520e+00; -//--- check - if(w==5) - r=-1.856e+00; -//--- check - if(w==4) - r=-2.213e+00; -//--- check - if(w==3) - r=-2.549e+00; -//--- check - if(w==2) - r=-3.060e+00; -//--- check - if(w==1) - r=-3.466e+00; -//--- check - if(w<=0) - r=-4.159e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 7) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W7(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(5.916080e+00*s)+1.400000e+01); - if(w>=14) - r=-6.325e-01; -//--- check - if(w==13) - r=-7.577e-01; -//--- check - if(w==12) - r=-9.008e-01; -//--- check - if(w==11) - r=-1.068e+00; -//--- check - if(w==10) - r=-1.241e+00; -//--- check - if(w==9) - r=-1.451e+00; -//--- check - if(w==8) - r=-1.674e+00; -//--- check - if(w==7) - r=-1.908e+00; -//--- check - if(w==6) - r=-2.213e+00; -//--- check - if(w==5) - r=-2.549e+00; -//--- check - if(w==4) - r=-2.906e+00; -//--- check - if(w==3) - r=-3.243e+00; -//--- check - if(w==2) - r=-3.753e+00; -//--- check - if(w==1) - r=-4.159e+00; -//--- check - if(w<=0) - r=-4.852e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 8) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W8(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(7.141428e+00*s)+1.800000e+01); - if(w>=18) - r=-6.399e-01; -//--- check - if(w==17) - r=-7.494e-01; -//--- check - if(w==16) - r=-8.630e-01; -//--- check - if(w==15) - r=-9.913e-01; -//--- check - if(w==14) - r=-1.138e+00; -//--- check - if(w==13) - r=-1.297e+00; -//--- check - if(w==12) - r=-1.468e+00; -//--- check - if(w==11) - r=-1.653e+00; -//--- check - if(w==10) - r=-1.856e+00; -//--- check - if(w==9) - r=-2.079e+00; -//--- check - if(w==8) - r=-2.326e+00; -//--- check - if(w==7) - r=-2.601e+00; -//--- check - if(w==6) - r=-2.906e+00; -//--- check - if(w==5) - r=-3.243e+00; -//--- check - if(w==4) - r=-3.599e+00; -//--- check - if(w==3) - r=-3.936e+00; -//--- check - if(w==2) - r=-4.447e+00; -//--- check - if(w==1) - r=-4.852e+00; -//--- check - if(w<=0) - r=-5.545e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 9) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W9(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(8.440972e+00*s)+2.250000e+01); - if(w>=22) - r=-6.931e-01; -//--- check - if(w==21) - r=-7.873e-01; -//--- check - if(w==20) - r=-8.912e-01; -//--- check - if(w==19) - r=-1.002e+00; -//--- check - if(w==18) - r=-1.120e+00; -//--- check - if(w==17) - r=-1.255e+00; -//--- check - if(w==16) - r=-1.394e+00; -//--- check - if(w==15) - r=-1.547e+00; -//--- check - if(w==14) - r=-1.717e+00; -//--- check - if(w==13) - r=-1.895e+00; -//--- check - if(w==12) - r=-2.079e+00; -//--- check - if(w==11) - r=-2.287e+00; -//--- check - if(w==10) - r=-2.501e+00; -//--- check - if(w==9) - r=-2.742e+00; -//--- check - if(w==8) - r=-3.019e+00; -//--- check - if(w==7) - r=-3.294e+00; -//--- check - if(w==6) - r=-3.599e+00; -//--- check - if(w==5) - r=-3.936e+00; -//--- check - if(w==4) - r=-4.292e+00; -//--- check - if(w==3) - r=-4.629e+00; -//--- check - if(w==2) - r=-5.140e+00; -//--- check - if(w==1) - r=-5.545e+00; -//--- check - if(w<=0) - r=-6.238e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 10) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W10(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(9.810708e+00*s)+2.750000e+01); - if(w>=27) - r=-6.931e-01; -//--- check - if(w==26) - r=-7.745e-01; -//--- check - if(w==25) - r=-8.607e-01; -//--- check - if(w==24) - r=-9.551e-01; -//--- check - if(w==23) - r=-1.057e+00; -//--- check - if(w==22) - r=-1.163e+00; -//--- check - if(w==21) - r=-1.279e+00; -//--- check - if(w==20) - r=-1.402e+00; -//--- check - if(w==19) - r=-1.533e+00; -//--- check - if(w==18) - r=-1.674e+00; -//--- check - if(w==17) - r=-1.826e+00; -//--- check - if(w==16) - r=-1.983e+00; -//--- check - if(w==15) - r=-2.152e+00; -//--- check - if(w==14) - r=-2.336e+00; -//--- check - if(w==13) - r=-2.525e+00; -//--- check - if(w==12) - r=-2.727e+00; -//--- check - if(w==11) - r=-2.942e+00; -//--- check - if(w==10) - r=-3.170e+00; -//--- check - if(w==9) - r=-3.435e+00; -//--- check - if(w==8) - r=-3.713e+00; -//--- check - if(w==7) - r=-3.987e+00; -//--- check - if(w==6) - r=-4.292e+00; -//--- check - if(w==5) - r=-4.629e+00; -//--- check - if(w==4) - r=-4.986e+00; -//--- check - if(w==3) - r=-5.322e+00; -//--- check - if(w==2) - r=-5.833e+00; -//--- check - if(w==1) - r=-6.238e+00; -//--- check - if(w<=0) - r=-6.931e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 11) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W11(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.124722e+01*s)+3.300000e+01); - if(w>=33) - r=-6.595e-01; -//--- check - if(w==32) - r=-7.279e-01; -//--- check - if(w==31) - r=-8.002e-01; -//--- check - if(w==30) - r=-8.782e-01; -//--- check - if(w==29) - r=-9.615e-01; -//--- check - if(w==28) - r=-1.050e+00; -//--- check - if(w==27) - r=-1.143e+00; -//--- check - if(w==26) - r=-1.243e+00; -//--- check - if(w==25) - r=-1.348e+00; -//--- check - if(w==24) - r=-1.459e+00; -//--- check - if(w==23) - r=-1.577e+00; -//--- check - if(w==22) - r=-1.700e+00; -//--- check - if(w==21) - r=-1.832e+00; -//--- check - if(w==20) - r=-1.972e+00; -//--- check - if(w==19) - r=-2.119e+00; -//--- check - if(w==18) - r=-2.273e+00; -//--- check - if(w==17) - r=-2.437e+00; -//--- check - if(w==16) - r=-2.607e+00; -//--- check - if(w==15) - r=-2.788e+00; -//--- check - if(w==14) - r=-2.980e+00; -//--- check - if(w==13) - r=-3.182e+00; -//--- check - if(w==12) - r=-3.391e+00; -//--- check - if(w==11) - r=-3.617e+00; -//--- check - if(w==10) - r=-3.863e+00; -//--- check - if(w==9) - r=-4.128e+00; -//--- check - if(w==8) - r=-4.406e+00; -//--- check - if(w==7) - r=-4.680e+00; -//--- check - if(w==6) - r=-4.986e+00; -//--- check - if(w==5) - r=-5.322e+00; -//--- check - if(w==4) - r=-5.679e+00; -//--- check - if(w==3) - r=-6.015e+00; -//--- check - if(w==2) - r=-6.526e+00; -//--- check - if(w==1) - r=-6.931e+00; -//--- check - if(w<=0) - r=-7.625e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 12) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W12(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.274755e+01*s)+3.900000e+01); - if(w>=39) - r=-6.633e-01; -//--- check - if(w==38) - r=-7.239e-01; -//--- check - if(w==37) - r=-7.878e-01; -//--- check - if(w==36) - r=-8.556e-01; -//--- check - if(w==35) - r=-9.276e-01; -//--- check - if(w==34) - r=-1.003e+00; -//--- check - if(w==33) - r=-1.083e+00; -//--- check - if(w==32) - r=-1.168e+00; -//--- check - if(w==31) - r=-1.256e+00; -//--- check - if(w==30) - r=-1.350e+00; -//--- check - if(w==29) - r=-1.449e+00; -//--- check - if(w==28) - r=-1.552e+00; -//--- check - if(w==27) - r=-1.660e+00; -//--- check - if(w==26) - r=-1.774e+00; -//--- check - if(w==25) - r=-1.893e+00; -//--- check - if(w==24) - r=-2.017e+00; -//--- check - if(w==23) - r=-2.148e+00; -//--- check - if(w==22) - r=-2.285e+00; -//--- check - if(w==21) - r=-2.429e+00; -//--- check - if(w==20) - r=-2.581e+00; -//--- check - if(w==19) - r=-2.738e+00; -//--- check - if(w==18) - r=-2.902e+00; -//--- check - if(w==17) - r=-3.076e+00; -//--- check - if(w==16) - r=-3.255e+00; -//--- check - if(w==15) - r=-3.443e+00; -//--- check - if(w==14) - r=-3.645e+00; -//--- check - if(w==13) - r=-3.852e+00; -//--- check - if(w==12) - r=-4.069e+00; -//--- check - if(w==11) - r=-4.310e+00; -//--- check - if(w==10) - r=-4.557e+00; -//--- check - if(w==9) - r=-4.821e+00; -//--- check - if(w==8) - r=-5.099e+00; -//--- check - if(w==7) - r=-5.373e+00; -//--- check - if(w==6) - r=-5.679e+00; -//--- check - if(w==5) - r=-6.015e+00; -//--- check - if(w==4) - r=-6.372e+00; -//--- check - if(w==3) - r=-6.708e+00; -//--- check - if(w==2) - r=-7.219e+00; -//--- check - if(w==1) - r=-7.625e+00; -//--- check - if(w<=0) - r=-8.318e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 13) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W13(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.430909e+01*s)+4.550000e+01); - if(w>=45) - r=-6.931e-01; -//--- check - if(w==44) - r=-7.486e-01; -//--- check - if(w==43) - r=-8.068e-01; -//--- check - if(w==42) - r=-8.683e-01; -//--- check - if(w==41) - r=-9.328e-01; -//--- check - if(w==40) - r=-1.001e+00; -//--- check - if(w==39) - r=-1.072e+00; -//--- check - if(w==38) - r=-1.146e+00; -//--- check - if(w==37) - r=-1.224e+00; -//--- check - if(w==36) - r=-1.306e+00; -//--- check - if(w==35) - r=-1.392e+00; -//--- check - if(w==34) - r=-1.481e+00; -//--- check - if(w==33) - r=-1.574e+00; -//--- check - if(w==32) - r=-1.672e+00; -//--- check - if(w==31) - r=-1.773e+00; -//--- check - if(w==30) - r=-1.879e+00; -//--- check - if(w==29) - r=-1.990e+00; -//--- check - if(w==28) - r=-2.104e+00; -//--- check - if(w==27) - r=-2.224e+00; -//--- check - if(w==26) - r=-2.349e+00; -//--- check - if(w==25) - r=-2.479e+00; -//--- check - if(w==24) - r=-2.614e+00; -//--- check - if(w==23) - r=-2.755e+00; -//--- check - if(w==22) - r=-2.902e+00; -//--- check - if(w==21) - r=-3.055e+00; -//--- check - if(w==20) - r=-3.215e+00; -//--- check - if(w==19) - r=-3.380e+00; -//--- check - if(w==18) - r=-3.551e+00; -//--- check - if(w==17) - r=-3.733e+00; -//--- check - if(w==16) - r=-3.917e+00; -//--- check - if(w==15) - r=-4.113e+00; -//--- check - if(w==14) - r=-4.320e+00; -//--- check - if(w==13) - r=-4.534e+00; -//--- check - if(w==12) - r=-4.762e+00; -//--- check - if(w==11) - r=-5.004e+00; -//--- check - if(w==10) - r=-5.250e+00; -//--- check - if(w==9) - r=-5.514e+00; -//--- check - if(w==8) - r=-5.792e+00; -//--- check - if(w==7) - r=-6.066e+00; -//--- check - if(w==6) - r=-6.372e+00; -//--- check - if(w==5) - r=-6.708e+00; -//--- check - if(w==4) - r=-7.065e+00; -//--- check - if(w==3) - r=-7.401e+00; -//--- check - if(w==2) - r=-7.912e+00; -//--- check - if(w==1) - r=-8.318e+00; -//--- check - if(w<=0) - r=-9.011e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 14) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W14(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.592953e+01*s)+5.250000e+01); - if(w>=52) - r=-6.931e-01; -//--- check - if(w==51) - r=-7.428e-01; -//--- check - if(w==50) - r=-7.950e-01; -//--- check - if(w==49) - r=-8.495e-01; -//--- check - if(w==48) - r=-9.067e-01; -//--- check - if(w==47) - r=-9.664e-01; -//--- check - if(w==46) - r=-1.029e+00; -//--- check - if(w==45) - r=-1.094e+00; -//--- check - if(w==44) - r=-1.162e+00; -//--- check - if(w==43) - r=-1.233e+00; -//--- check - if(w==42) - r=-1.306e+00; -//--- check - if(w==41) - r=-1.383e+00; -//--- check - if(w==40) - r=-1.463e+00; -//--- check - if(w==39) - r=-1.546e+00; -//--- check - if(w==38) - r=-1.632e+00; -//--- check - if(w==37) - r=-1.722e+00; -//--- check - if(w==36) - r=-1.815e+00; -//--- check - if(w==35) - r=-1.911e+00; -//--- check - if(w==34) - r=-2.011e+00; -//--- check - if(w==33) - r=-2.115e+00; -//--- check - if(w==32) - r=-2.223e+00; -//--- check - if(w==31) - r=-2.334e+00; -//--- check - if(w==30) - r=-2.450e+00; -//--- check - if(w==29) - r=-2.570e+00; -//--- check - if(w==28) - r=-2.694e+00; -//--- check - if(w==27) - r=-2.823e+00; -//--- check - if(w==26) - r=-2.956e+00; -//--- check - if(w==25) - r=-3.095e+00; -//--- check - if(w==24) - r=-3.238e+00; -//--- check - if(w==23) - r=-3.387e+00; -//--- check - if(w==22) - r=-3.541e+00; -//--- check - if(w==21) - r=-3.700e+00; -//--- check - if(w==20) - r=-3.866e+00; -//--- check - if(w==19) - r=-4.038e+00; -//--- check - if(w==18) - r=-4.215e+00; -//--- check - if(w==17) - r=-4.401e+00; -//--- check - if(w==16) - r=-4.592e+00; -//--- check - if(w==15) - r=-4.791e+00; -//--- check - if(w==14) - r=-5.004e+00; -//--- check - if(w==13) - r=-5.227e+00; -//--- check - if(w==12) - r=-5.456e+00; -//--- check - if(w==11) - r=-5.697e+00; -//--- check - if(w==10) - r=-5.943e+00; -//--- check - if(w==9) - r=-6.208e+00; -//--- check - if(w==8) - r=-6.485e+00; -//--- check - if(w==7) - r=-6.760e+00; -//--- check - if(w==6) - r=-7.065e+00; -//--- check - if(w==5) - r=-7.401e+00; -//--- check - if(w==4) - r=-7.758e+00; -//--- check - if(w==3) - r=-8.095e+00; -//--- check - if(w==2) - r=-8.605e+00; -//--- check - if(w==1) - r=-9.011e+00; -//--- check - if(w<=0) - r=-9.704e+00; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 15) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W15(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.760682e+01*s)+6.000000e+01); - if(w>=60) - r=-6.714e-01; -//--- check - if(w==59) - r=-7.154e-01; -//--- check - if(w==58) - r=-7.613e-01; -//--- check - if(w==57) - r=-8.093e-01; -//--- check - if(w==56) - r=-8.593e-01; -//--- check - if(w==55) - r=-9.114e-01; -//--- check - if(w==54) - r=-9.656e-01; -//--- check - if(w==53) - r=-1.022e+00; -//--- check - if(w==52) - r=-1.081e+00; -//--- check - if(w==51) - r=-1.142e+00; -//--- check - if(w==50) - r=-1.205e+00; -//--- check - if(w==49) - r=-1.270e+00; -//--- check - if(w==48) - r=-1.339e+00; -//--- check - if(w==47) - r=-1.409e+00; -//--- check - if(w==46) - r=-1.482e+00; -//--- check - if(w==45) - r=-1.558e+00; -//--- check - if(w==44) - r=-1.636e+00; -//--- check - if(w==43) - r=-1.717e+00; -//--- check - if(w==42) - r=-1.801e+00; -//--- check - if(w==41) - r=-1.888e+00; -//--- check - if(w==40) - r=-1.977e+00; -//--- check - if(w==39) - r=-2.070e+00; -//--- check - if(w==38) - r=-2.166e+00; -//--- check - if(w==37) - r=-2.265e+00; -//--- check - if(w==36) - r=-2.366e+00; -//--- check - if(w==35) - r=-2.472e+00; -//--- check - if(w==34) - r=-2.581e+00; -//--- check - if(w==33) - r=-2.693e+00; -//--- check - if(w==32) - r=-2.809e+00; -//--- check - if(w==31) - r=-2.928e+00; -//--- check - if(w==30) - r=-3.051e+00; -//--- check - if(w==29) - r=-3.179e+00; -//--- check - if(w==28) - r=-3.310e+00; -//--- check - if(w==27) - r=-3.446e+00; -//--- check - if(w==26) - r=-3.587e+00; -//--- check - if(w==25) - r=-3.732e+00; -//--- check - if(w==24) - r=-3.881e+00; -//--- check - if(w==23) - r=-4.036e+00; -//--- check - if(w==22) - r=-4.195e+00; -//--- check - if(w==21) - r=-4.359e+00; -//--- check - if(w==20) - r=-4.531e+00; -//--- check - if(w==19) - r=-4.707e+00; -//--- check - if(w==18) - r=-4.888e+00; -//--- check - if(w==17) - r=-5.079e+00; -//--- check - if(w==16) - r=-5.273e+00; -//--- check - if(w==15) - r=-5.477e+00; -//--- check - if(w==14) - r=-5.697e+00; -//--- check - if(w==13) - r=-5.920e+00; -//--- check - if(w==12) - r=-6.149e+00; -//--- check - if(w==11) - r=-6.390e+00; -//--- check - if(w==10) - r=-6.636e+00; -//--- check - if(w==9) - r=-6.901e+00; -//--- check - if(w==8) - r=-7.178e+00; -//--- check - if(w==7) - r=-7.453e+00; -//--- check - if(w==6) - r=-7.758e+00; -//--- check - if(w==5) - r=-8.095e+00; -//--- check - if(w==4) - r=-8.451e+00; -//--- check - if(w==3) - r=-8.788e+00; -//--- check - if(w==2) - r=-9.299e+00; -//--- check - if(w==1) - r=-9.704e+00; -//--- check - if(w<=0) - r=-1.040e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 16) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W16(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(1.933908e+01*s)+6.800000e+01); - if(w>=68) - r=-6.733e-01; -//--- check - if(w==67) - r=-7.134e-01; -//--- check - if(w==66) - r=-7.551e-01; -//--- check - if(w==65) - r=-7.986e-01; -//--- check - if(w==64) - r=-8.437e-01; -//--- check - if(w==63) - r=-8.905e-01; -//--- check - if(w==62) - r=-9.391e-01; -//--- check - if(w==61) - r=-9.895e-01; -//--- check - if(w==60) - r=-1.042e+00; -//--- check - if(w==59) - r=-1.096e+00; -//--- check - if(w==58) - r=-1.152e+00; -//--- check - if(w==57) - r=-1.210e+00; -//--- check - if(w==56) - r=-1.270e+00; -//--- check - if(w==55) - r=-1.331e+00; -//--- check - if(w==54) - r=-1.395e+00; -//--- check - if(w==53) - r=-1.462e+00; -//--- check - if(w==52) - r=-1.530e+00; -//--- check - if(w==51) - r=-1.600e+00; -//--- check - if(w==50) - r=-1.673e+00; -//--- check - if(w==49) - r=-1.748e+00; -//--- check - if(w==48) - r=-1.825e+00; -//--- check - if(w==47) - r=-1.904e+00; -//--- check - if(w==46) - r=-1.986e+00; -//--- check - if(w==45) - r=-2.071e+00; -//--- check - if(w==44) - r=-2.158e+00; -//--- check - if(w==43) - r=-2.247e+00; -//--- check - if(w==42) - r=-2.339e+00; -//--- check - if(w==41) - r=-2.434e+00; -//--- check - if(w==40) - r=-2.532e+00; -//--- check - if(w==39) - r=-2.632e+00; -//--- check - if(w==38) - r=-2.735e+00; -//--- check - if(w==37) - r=-2.842e+00; -//--- check - if(w==36) - r=-2.951e+00; -//--- check - if(w==35) - r=-3.064e+00; -//--- check - if(w==34) - r=-3.179e+00; -//--- check - if(w==33) - r=-3.298e+00; -//--- check - if(w==32) - r=-3.420e+00; -//--- check - if(w==31) - r=-3.546e+00; -//--- check - if(w==30) - r=-3.676e+00; -//--- check - if(w==29) - r=-3.810e+00; -//--- check - if(w==28) - r=-3.947e+00; -//--- check - if(w==27) - r=-4.088e+00; -//--- check - if(w==26) - r=-4.234e+00; -//--- check - if(w==25) - r=-4.383e+00; -//--- check - if(w==24) - r=-4.538e+00; -//--- check - if(w==23) - r=-4.697e+00; -//--- check - if(w==22) - r=-4.860e+00; -//--- check - if(w==21) - r=-5.029e+00; -//--- check - if(w==20) - r=-5.204e+00; -//--- check - if(w==19) - r=-5.383e+00; -//--- check - if(w==18) - r=-5.569e+00; -//--- check - if(w==17) - r=-5.762e+00; -//--- check - if(w==16) - r=-5.960e+00; -//--- check - if(w==15) - r=-6.170e+00; -//--- check - if(w==14) - r=-6.390e+00; -//--- check - if(w==13) - r=-6.613e+00; -//--- check - if(w==12) - r=-6.842e+00; -//--- check - if(w==11) - r=-7.083e+00; -//--- check - if(w==10) - r=-7.329e+00; -//--- check - if(w==9) - r=-7.594e+00; -//--- check - if(w==8) - r=-7.871e+00; -//--- check - if(w==7) - r=-8.146e+00; -//--- check - if(w==6) - r=-8.451e+00; -//--- check - if(w==5) - r=-8.788e+00; -//--- check - if(w==4) - r=-9.144e+00; -//--- check - if(w==3) - r=-9.481e+00; -//--- check - if(w==2) - r=-9.992e+00; -//--- check - if(w==1) - r=-1.040e+01; -//--- check - if(w<=0) - r=-1.109e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 17) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W17(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(2.112463e+01*s)+7.650000e+01); - if(w>=76) - r=-6.931e-01; -//--- check - if(w==75) - r=-7.306e-01; -//--- check - if(w==74) - r=-7.695e-01; -//--- check - if(w==73) - r=-8.097e-01; -//--- check - if(w==72) - r=-8.514e-01; -//--- check - if(w==71) - r=-8.946e-01; -//--- check - if(w==70) - r=-9.392e-01; -//--- check - if(w==69) - r=-9.853e-01; -//--- check - if(w==68) - r=-1.033e+00; -//--- check - if(w==67) - r=-1.082e+00; -//--- check - if(w==66) - r=-1.133e+00; -//--- check - if(w==65) - r=-1.185e+00; -//--- check - if(w==64) - r=-1.240e+00; -//--- check - if(w==63) - r=-1.295e+00; -//--- check - if(w==62) - r=-1.353e+00; -//--- check - if(w==61) - r=-1.412e+00; -//--- check - if(w==60) - r=-1.473e+00; -//--- check - if(w==59) - r=-1.536e+00; -//--- check - if(w==58) - r=-1.600e+00; -//--- check - if(w==57) - r=-1.666e+00; -//--- check - if(w==56) - r=-1.735e+00; -//--- check - if(w==55) - r=-1.805e+00; -//--- check - if(w==54) - r=-1.877e+00; -//--- check - if(w==53) - r=-1.951e+00; -//--- check - if(w==52) - r=-2.028e+00; -//--- check - if(w==51) - r=-2.106e+00; -//--- check - if(w==50) - r=-2.186e+00; -//--- check - if(w==49) - r=-2.269e+00; -//--- check - if(w==48) - r=-2.353e+00; -//--- check - if(w==47) - r=-2.440e+00; -//--- check - if(w==46) - r=-2.530e+00; -//--- check - if(w==45) - r=-2.621e+00; -//--- check - if(w==44) - r=-2.715e+00; -//--- check - if(w==43) - r=-2.812e+00; -//--- check - if(w==42) - r=-2.911e+00; -//--- check - if(w==41) - r=-3.012e+00; -//--- check - if(w==40) - r=-3.116e+00; -//--- check - if(w==39) - r=-3.223e+00; -//--- check - if(w==38) - r=-3.332e+00; -//--- check - if(w==37) - r=-3.445e+00; -//--- check - if(w==36) - r=-3.560e+00; -//--- check - if(w==35) - r=-3.678e+00; -//--- check - if(w==34) - r=-3.799e+00; -//--- check - if(w==33) - r=-3.924e+00; -//--- check - if(w==32) - r=-4.052e+00; -//--- check - if(w==31) - r=-4.183e+00; -//--- check - if(w==30) - r=-4.317e+00; -//--- check - if(w==29) - r=-4.456e+00; -//--- check - if(w==28) - r=-4.597e+00; -//--- check - if(w==27) - r=-4.743e+00; -//--- check - if(w==26) - r=-4.893e+00; -//--- check - if(w==25) - r=-5.047e+00; -//--- check - if(w==24) - r=-5.204e+00; -//--- check - if(w==23) - r=-5.367e+00; -//--- check - if(w==22) - r=-5.534e+00; -//--- check - if(w==21) - r=-5.706e+00; -//--- check - if(w==20) - r=-5.884e+00; -//--- check - if(w==19) - r=-6.066e+00; -//--- check - if(w==18) - r=-6.254e+00; -//--- check - if(w==17) - r=-6.451e+00; -//--- check - if(w==16) - r=-6.654e+00; -//--- check - if(w==15) - r=-6.864e+00; -//--- check - if(w==14) - r=-7.083e+00; -//--- check - if(w==13) - r=-7.306e+00; -//--- check - if(w==12) - r=-7.535e+00; -//--- check - if(w==11) - r=-7.776e+00; -//--- check - if(w==10) - r=-8.022e+00; -//--- check - if(w==9) - r=-8.287e+00; -//--- check - if(w==8) - r=-8.565e+00; -//--- check - if(w==7) - r=-8.839e+00; -//--- check - if(w==6) - r=-9.144e+00; -//--- check - if(w==5) - r=-9.481e+00; -//--- check - if(w==4) - r=-9.838e+00; -//--- check - if(w==3) - r=-1.017e+01; -//--- check - if(w==2) - r=-1.068e+01; -//--- check - if(w==1) - r=-1.109e+01; -//--- check - if(w<=0) - r=-1.178e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 18) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W18(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(2.296193e+01*s)+8.550000e+01); - if(w>=85) - r=-6.931e-01; -//--- check - if(w==84) - r=-7.276e-01; -//--- check - if(w==83) - r=-7.633e-01; -//--- check - if(w==82) - r=-8.001e-01; -//--- check - if(w==81) - r=-8.381e-01; -//--- check - if(w==80) - r=-8.774e-01; -//--- check - if(w==79) - r=-9.179e-01; -//--- check - if(w==78) - r=-9.597e-01; -//--- check - if(w==77) - r=-1.003e+00; -//--- check - if(w==76) - r=-1.047e+00; -//--- check - if(w==75) - r=-1.093e+00; -//--- check - if(w==74) - r=-1.140e+00; -//--- check - if(w==73) - r=-1.188e+00; -//--- check - if(w==72) - r=-1.238e+00; -//--- check - if(w==71) - r=-1.289e+00; -//--- check - if(w==70) - r=-1.342e+00; -//--- check - if(w==69) - r=-1.396e+00; -//--- check - if(w==68) - r=-1.452e+00; -//--- check - if(w==67) - r=-1.509e+00; -//--- check - if(w==66) - r=-1.568e+00; -//--- check - if(w==65) - r=-1.628e+00; -//--- check - if(w==64) - r=-1.690e+00; -//--- check - if(w==63) - r=-1.753e+00; -//--- check - if(w==62) - r=-1.818e+00; -//--- check - if(w==61) - r=-1.885e+00; -//--- check - if(w==60) - r=-1.953e+00; -//--- check - if(w==59) - r=-2.023e+00; -//--- check - if(w==58) - r=-2.095e+00; -//--- check - if(w==57) - r=-2.168e+00; -//--- check - if(w==56) - r=-2.244e+00; -//--- check - if(w==55) - r=-2.321e+00; -//--- check - if(w==54) - r=-2.400e+00; -//--- check - if(w==53) - r=-2.481e+00; -//--- check - if(w==52) - r=-2.564e+00; -//--- check - if(w==51) - r=-2.648e+00; -//--- check - if(w==50) - r=-2.735e+00; -//--- check - if(w==49) - r=-2.824e+00; -//--- check - if(w==48) - r=-2.915e+00; -//--- check - if(w==47) - r=-3.008e+00; -//--- check - if(w==46) - r=-3.104e+00; -//--- check - if(w==45) - r=-3.201e+00; -//--- check - if(w==44) - r=-3.301e+00; -//--- check - if(w==43) - r=-3.403e+00; -//--- check - if(w==42) - r=-3.508e+00; -//--- check - if(w==41) - r=-3.615e+00; -//--- check - if(w==40) - r=-3.724e+00; -//--- check - if(w==39) - r=-3.836e+00; -//--- check - if(w==38) - r=-3.950e+00; -//--- check - if(w==37) - r=-4.068e+00; -//--- check - if(w==36) - r=-4.188e+00; -//--- check - if(w==35) - r=-4.311e+00; -//--- check - if(w==34) - r=-4.437e+00; -//--- check - if(w==33) - r=-4.565e+00; -//--- check - if(w==32) - r=-4.698e+00; -//--- check - if(w==31) - r=-4.833e+00; -//--- check - if(w==30) - r=-4.971e+00; -//--- check - if(w==29) - r=-5.113e+00; -//--- check - if(w==28) - r=-5.258e+00; -//--- check - if(w==27) - r=-5.408e+00; -//--- check - if(w==26) - r=-5.561e+00; -//--- check - if(w==25) - r=-5.717e+00; -//--- check - if(w==24) - r=-5.878e+00; -//--- check - if(w==23) - r=-6.044e+00; -//--- check - if(w==22) - r=-6.213e+00; -//--- check - if(w==21) - r=-6.388e+00; -//--- check - if(w==20) - r=-6.569e+00; -//--- check - if(w==19) - r=-6.753e+00; -//--- check - if(w==18) - r=-6.943e+00; -//--- check - if(w==17) - r=-7.144e+00; -//--- check - if(w==16) - r=-7.347e+00; -//--- check - if(w==15) - r=-7.557e+00; -//--- check - if(w==14) - r=-7.776e+00; -//--- check - if(w==13) - r=-7.999e+00; -//--- check - if(w==12) - r=-8.228e+00; -//--- check - if(w==11) - r=-8.469e+00; -//--- check - if(w==10) - r=-8.715e+00; -//--- check - if(w==9) - r=-8.980e+00; -//--- check - if(w==8) - r=-9.258e+00; -//--- check - if(w==7) - r=-9.532e+00; -//--- check - if(w==6) - r=-9.838e+00; -//--- check - if(w==5) - r=-1.017e+01; -//--- check - if(w==4) - r=-1.053e+01; -//--- check - if(w==3) - r=-1.087e+01; -//--- check - if(w==2) - r=-1.138e+01; -//--- check - if(w==1) - r=-1.178e+01; -//--- check - if(w<=0) - r=-1.248e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 19) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W19(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(2.484955e+01*s)+9.500000e+01); - if(w>=95) - r=-6.776e-01; -//--- check - if(w==94) - r=-7.089e-01; -//--- check - if(w==93) - r=-7.413e-01; -//--- check - if(w==92) - r=-7.747e-01; -//--- check - if(w==91) - r=-8.090e-01; -//--- check - if(w==90) - r=-8.445e-01; -//--- check - if(w==89) - r=-8.809e-01; -//--- check - if(w==88) - r=-9.185e-01; -//--- check - if(w==87) - r=-9.571e-01; -//--- check - if(w==86) - r=-9.968e-01; -//--- check - if(w==85) - r=-1.038e+00; -//--- check - if(w==84) - r=-1.080e+00; -//--- check - if(w==83) - r=-1.123e+00; -//--- check - if(w==82) - r=-1.167e+00; -//--- check - if(w==81) - r=-1.213e+00; -//--- check - if(w==80) - r=-1.259e+00; -//--- check - if(w==79) - r=-1.307e+00; -//--- check - if(w==78) - r=-1.356e+00; -//--- check - if(w==77) - r=-1.407e+00; -//--- check - if(w==76) - r=-1.458e+00; -//--- check - if(w==75) - r=-1.511e+00; -//--- check - if(w==74) - r=-1.565e+00; -//--- check - if(w==73) - r=-1.621e+00; -//--- check - if(w==72) - r=-1.678e+00; -//--- check - if(w==71) - r=-1.736e+00; -//--- check - if(w==70) - r=-1.796e+00; -//--- check - if(w==69) - r=-1.857e+00; -//--- check - if(w==68) - r=-1.919e+00; -//--- check - if(w==67) - r=-1.983e+00; -//--- check - if(w==66) - r=-2.048e+00; -//--- check - if(w==65) - r=-2.115e+00; -//--- check - if(w==64) - r=-2.183e+00; -//--- check - if(w==63) - r=-2.253e+00; -//--- check - if(w==62) - r=-2.325e+00; -//--- check - if(w==61) - r=-2.398e+00; -//--- check - if(w==60) - r=-2.472e+00; -//--- check - if(w==59) - r=-2.548e+00; -//--- check - if(w==58) - r=-2.626e+00; -//--- check - if(w==57) - r=-2.706e+00; -//--- check - if(w==56) - r=-2.787e+00; -//--- check - if(w==55) - r=-2.870e+00; -//--- check - if(w==54) - r=-2.955e+00; -//--- check - if(w==53) - r=-3.042e+00; -//--- check - if(w==52) - r=-3.130e+00; -//--- check - if(w==51) - r=-3.220e+00; -//--- check - if(w==50) - r=-3.313e+00; -//--- check - if(w==49) - r=-3.407e+00; -//--- check - if(w==48) - r=-3.503e+00; -//--- check - if(w==47) - r=-3.601e+00; -//--- check - if(w==46) - r=-3.702e+00; -//--- check - if(w==45) - r=-3.804e+00; -//--- check - if(w==44) - r=-3.909e+00; -//--- check - if(w==43) - r=-4.015e+00; -//--- check - if(w==42) - r=-4.125e+00; -//--- check - if(w==41) - r=-4.236e+00; -//--- check - if(w==40) - r=-4.350e+00; -//--- check - if(w==39) - r=-4.466e+00; -//--- check - if(w==38) - r=-4.585e+00; -//--- check - if(w==37) - r=-4.706e+00; -//--- check - if(w==36) - r=-4.830e+00; -//--- check - if(w==35) - r=-4.957e+00; -//--- check - if(w==34) - r=-5.086e+00; -//--- check - if(w==33) - r=-5.219e+00; -//--- check - if(w==32) - r=-5.355e+00; -//--- check - if(w==31) - r=-5.493e+00; -//--- check - if(w==30) - r=-5.634e+00; -//--- check - if(w==29) - r=-5.780e+00; -//--- check - if(w==28) - r=-5.928e+00; -//--- check - if(w==27) - r=-6.080e+00; -//--- check - if(w==26) - r=-6.235e+00; -//--- check - if(w==25) - r=-6.394e+00; -//--- check - if(w==24) - r=-6.558e+00; -//--- check - if(w==23) - r=-6.726e+00; -//--- check - if(w==22) - r=-6.897e+00; -//--- check - if(w==21) - r=-7.074e+00; -//--- check - if(w==20) - r=-7.256e+00; -//--- check - if(w==19) - r=-7.443e+00; -//--- check - if(w==18) - r=-7.636e+00; -//--- check - if(w==17) - r=-7.837e+00; -//--- check - if(w==16) - r=-8.040e+00; -//--- check - if(w==15) - r=-8.250e+00; -//--- check - if(w==14) - r=-8.469e+00; -//--- check - if(w==13) - r=-8.692e+00; -//--- check - if(w==12) - r=-8.921e+00; -//--- check - if(w==11) - r=-9.162e+00; -//--- check - if(w==10) - r=-9.409e+00; -//--- check - if(w==9) - r=-9.673e+00; -//--- check - if(w==8) - r=-9.951e+00; -//--- check - if(w==7) - r=-1.023e+01; -//--- check - if(w==6) - r=-1.053e+01; -//--- check - if(w==5) - r=-1.087e+01; -//--- check - if(w==4) - r=-1.122e+01; -//--- check - if(w==3) - r=-1.156e+01; -//--- check - if(w==2) - r=-1.207e+01; -//--- check - if(w==1) - r=-1.248e+01; -//--- check - if(w<=0) - r=-1.317e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 20) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W20(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(2.678619e+01*s)+1.050000e+02); - if(w>=105) - r=-6.787e-01; -//--- check - if(w==104) - r=-7.078e-01; -//--- check - if(w==103) - r=-7.378e-01; -//--- check - if(w==102) - r=-7.686e-01; -//--- check - if(w==101) - r=-8.004e-01; -//--- check - if(w==100) - r=-8.330e-01; -//--- check - if(w==99) - r=-8.665e-01; -//--- check - if(w==98) - r=-9.010e-01; -//--- check - if(w==97) - r=-9.363e-01; -//--- check - if(w==96) - r=-9.726e-01; -//--- check - if(w==95) - r=-1.010e+00; -//--- check - if(w==94) - r=-1.048e+00; -//--- check - if(w==93) - r=-1.087e+00; -//--- check - if(w==92) - r=-1.128e+00; -//--- check - if(w==91) - r=-1.169e+00; -//--- check - if(w==90) - r=-1.211e+00; -//--- check - if(w==89) - r=-1.254e+00; -//--- check - if(w==88) - r=-1.299e+00; -//--- check - if(w==87) - r=-1.344e+00; -//--- check - if(w==86) - r=-1.390e+00; -//--- check - if(w==85) - r=-1.438e+00; -//--- check - if(w==84) - r=-1.486e+00; -//--- check - if(w==83) - r=-1.536e+00; -//--- check - if(w==82) - r=-1.587e+00; -//--- check - if(w==81) - r=-1.639e+00; -//--- check - if(w==80) - r=-1.692e+00; -//--- check - if(w==79) - r=-1.746e+00; -//--- check - if(w==78) - r=-1.802e+00; -//--- check - if(w==77) - r=-1.859e+00; -//--- check - if(w==76) - r=-1.916e+00; -//--- check - if(w==75) - r=-1.976e+00; -//--- check - if(w==74) - r=-2.036e+00; -//--- check - if(w==73) - r=-2.098e+00; -//--- check - if(w==72) - r=-2.161e+00; -//--- check - if(w==71) - r=-2.225e+00; -//--- check - if(w==70) - r=-2.290e+00; -//--- check - if(w==69) - r=-2.357e+00; -//--- check - if(w==68) - r=-2.426e+00; -//--- check - if(w==67) - r=-2.495e+00; -//--- check - if(w==66) - r=-2.566e+00; -//--- check - if(w==65) - r=-2.639e+00; -//--- check - if(w==64) - r=-2.713e+00; -//--- check - if(w==63) - r=-2.788e+00; -//--- check - if(w==62) - r=-2.865e+00; -//--- check - if(w==61) - r=-2.943e+00; -//--- check - if(w==60) - r=-3.023e+00; -//--- check - if(w==59) - r=-3.104e+00; -//--- check - if(w==58) - r=-3.187e+00; -//--- check - if(w==57) - r=-3.272e+00; -//--- check - if(w==56) - r=-3.358e+00; -//--- check - if(w==55) - r=-3.446e+00; -//--- check - if(w==54) - r=-3.536e+00; -//--- check - if(w==53) - r=-3.627e+00; -//--- check - if(w==52) - r=-3.721e+00; -//--- check - if(w==51) - r=-3.815e+00; -//--- check - if(w==50) - r=-3.912e+00; -//--- check - if(w==49) - r=-4.011e+00; -//--- check - if(w==48) - r=-4.111e+00; -//--- check - if(w==47) - r=-4.214e+00; -//--- check - if(w==46) - r=-4.318e+00; -//--- check - if(w==45) - r=-4.425e+00; -//--- check - if(w==44) - r=-4.534e+00; -//--- check - if(w==43) - r=-4.644e+00; -//--- check - if(w==42) - r=-4.757e+00; -//--- check - if(w==41) - r=-4.872e+00; -//--- check - if(w==40) - r=-4.990e+00; -//--- check - if(w==39) - r=-5.109e+00; -//--- check - if(w==38) - r=-5.232e+00; -//--- check - if(w==37) - r=-5.356e+00; -//--- check - if(w==36) - r=-5.484e+00; -//--- check - if(w==35) - r=-5.614e+00; -//--- check - if(w==34) - r=-5.746e+00; -//--- check - if(w==33) - r=-5.882e+00; -//--- check - if(w==32) - r=-6.020e+00; -//--- check - if(w==31) - r=-6.161e+00; -//--- check - if(w==30) - r=-6.305e+00; -//--- check - if(w==29) - r=-6.453e+00; -//--- check - if(w==28) - r=-6.603e+00; -//--- check - if(w==27) - r=-6.757e+00; -//--- check - if(w==26) - r=-6.915e+00; -//--- check - if(w==25) - r=-7.076e+00; -//--- check - if(w==24) - r=-7.242e+00; -//--- check - if(w==23) - r=-7.411e+00; -//--- check - if(w==22) - r=-7.584e+00; -//--- check - if(w==21) - r=-7.763e+00; -//--- check - if(w==20) - r=-7.947e+00; -//--- check - if(w==19) - r=-8.136e+00; -//--- check - if(w==18) - r=-8.330e+00; -//--- check - if(w==17) - r=-8.530e+00; -//--- check - if(w==16) - r=-8.733e+00; -//--- check - if(w==15) - r=-8.943e+00; -//--- check - if(w==14) - r=-9.162e+00; -//--- check - if(w==13) - r=-9.386e+00; -//--- check - if(w==12) - r=-9.614e+00; -//--- check - if(w==11) - r=-9.856e+00; -//--- check - if(w==10) - r=-1.010e+01; -//--- check - if(w==9) - r=-1.037e+01; -//--- check - if(w==8) - r=-1.064e+01; -//--- check - if(w==7) - r=-1.092e+01; -//--- check - if(w==6) - r=-1.122e+01; -//--- check - if(w==5) - r=-1.156e+01; -//--- check - if(w==4) - r=-1.192e+01; -//--- check - if(w==3) - r=-1.225e+01; -//--- check - if(w==2) - r=-1.276e+01; -//--- check - if(w==1) - r=-1.317e+01; -//--- check - if(w<=0) - r=-1.386e+01; -//--- - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 21) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W21(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(2.877064e+01*s)+1.155000e+02); - if(w>=115) - r=-6.931e-01; -//--- check - if(w==114) - r=-7.207e-01; -//--- check - if(w==113) - r=-7.489e-01; -//--- check - if(w==112) - r=-7.779e-01; -//--- check - if(w==111) - r=-8.077e-01; -//--- check - if(w==110) - r=-8.383e-01; -//--- check - if(w==109) - r=-8.697e-01; -//--- check - if(w==108) - r=-9.018e-01; -//--- check - if(w==107) - r=-9.348e-01; -//--- check - if(w==106) - r=-9.685e-01; -//--- check - if(w==105) - r=-1.003e+00; -//--- check - if(w==104) - r=-1.039e+00; -//--- check - if(w==103) - r=-1.075e+00; -//--- check - if(w==102) - r=-1.112e+00; -//--- check - if(w==101) - r=-1.150e+00; -//--- check - if(w==100) - r=-1.189e+00; -//--- check - if(w==99) - r=-1.229e+00; -//--- check - if(w==98) - r=-1.269e+00; -//--- check - if(w==97) - r=-1.311e+00; -//--- check - if(w==96) - r=-1.353e+00; -//--- check - if(w==95) - r=-1.397e+00; -//--- check - if(w==94) - r=-1.441e+00; -//--- check - if(w==93) - r=-1.486e+00; -//--- check - if(w==92) - r=-1.533e+00; -//--- check - if(w==91) - r=-1.580e+00; -//--- check - if(w==90) - r=-1.628e+00; -//--- check - if(w==89) - r=-1.677e+00; -//--- check - if(w==88) - r=-1.728e+00; -//--- check - if(w==87) - r=-1.779e+00; -//--- check - if(w==86) - r=-1.831e+00; -//--- check - if(w==85) - r=-1.884e+00; -//--- check - if(w==84) - r=-1.939e+00; -//--- check - if(w==83) - r=-1.994e+00; -//--- check - if(w==82) - r=-2.051e+00; -//--- check - if(w==81) - r=-2.108e+00; -//--- check - if(w==80) - r=-2.167e+00; -//--- check - if(w==79) - r=-2.227e+00; -//--- check - if(w==78) - r=-2.288e+00; -//--- check - if(w==77) - r=-2.350e+00; -//--- check - if(w==76) - r=-2.414e+00; -//--- check - if(w==75) - r=-2.478e+00; -//--- check - if(w==74) - r=-2.544e+00; -//--- check - if(w==73) - r=-2.611e+00; -//--- check - if(w==72) - r=-2.679e+00; -//--- check - if(w==71) - r=-2.748e+00; -//--- check - if(w==70) - r=-2.819e+00; -//--- check - if(w==69) - r=-2.891e+00; -//--- check - if(w==68) - r=-2.964e+00; -//--- check - if(w==67) - r=-3.039e+00; -//--- check - if(w==66) - r=-3.115e+00; -//--- check - if(w==65) - r=-3.192e+00; -//--- check - if(w==64) - r=-3.270e+00; -//--- check - if(w==63) - r=-3.350e+00; -//--- check - if(w==62) - r=-3.432e+00; -//--- check - if(w==61) - r=-3.515e+00; -//--- check - if(w==60) - r=-3.599e+00; -//--- check - if(w==59) - r=-3.685e+00; -//--- check - if(w==58) - r=-3.772e+00; -//--- check - if(w==57) - r=-3.861e+00; -//--- check - if(w==56) - r=-3.952e+00; -//--- check - if(w==55) - r=-4.044e+00; -//--- check - if(w==54) - r=-4.138e+00; -//--- check - if(w==53) - r=-4.233e+00; -//--- check - if(w==52) - r=-4.330e+00; -//--- check - if(w==51) - r=-4.429e+00; -//--- check - if(w==50) - r=-4.530e+00; -//--- check - if(w==49) - r=-4.632e+00; -//--- check - if(w==48) - r=-4.736e+00; -//--- check - if(w==47) - r=-4.842e+00; -//--- check - if(w==46) - r=-4.950e+00; -//--- check - if(w==45) - r=-5.060e+00; -//--- check - if(w==44) - r=-5.172e+00; -//--- check - if(w==43) - r=-5.286e+00; -//--- check - if(w==42) - r=-5.402e+00; -//--- check - if(w==41) - r=-5.520e+00; -//--- check - if(w==40) - r=-5.641e+00; -//--- check - if(w==39) - r=-5.763e+00; -//--- check - if(w==38) - r=-5.889e+00; -//--- check - if(w==37) - r=-6.016e+00; -//--- check - if(w==36) - r=-6.146e+00; -//--- check - if(w==35) - r=-6.278e+00; -//--- check - if(w==34) - r=-6.413e+00; -//--- check - if(w==33) - r=-6.551e+00; -//--- check - if(w==32) - r=-6.692e+00; -//--- check - if(w==31) - r=-6.835e+00; -//--- check - if(w==30) - r=-6.981e+00; -//--- check - if(w==29) - r=-7.131e+00; -//--- check - if(w==28) - r=-7.283e+00; -//--- check - if(w==27) - r=-7.439e+00; -//--- check - if(w==26) - r=-7.599e+00; -//--- check - if(w==25) - r=-7.762e+00; -//--- check - if(w==24) - r=-7.928e+00; -//--- check - if(w==23) - r=-8.099e+00; -//--- check - if(w==22) - r=-8.274e+00; -//--- check - if(w==21) - r=-8.454e+00; -//--- check - if(w==20) - r=-8.640e+00; -//--- check - if(w==19) - r=-8.829e+00; -//--- check - if(w==18) - r=-9.023e+00; -//--- check - if(w==17) - r=-9.223e+00; -//--- check - if(w==16) - r=-9.426e+00; -//--- check - if(w==15) - r=-9.636e+00; -//--- check - if(w==14) - r=-9.856e+00; -//--- check - if(w==13) - r=-1.008e+01; -//--- check - if(w==12) - r=-1.031e+01; -//--- check - if(w==11) - r=-1.055e+01; -//--- check - if(w==10) - r=-1.079e+01; -//--- check - if(w==9) - r=-1.106e+01; -//--- check - if(w==8) - r=-1.134e+01; -//--- check - if(w==7) - r=-1.161e+01; -//--- check - if(w==6) - r=-1.192e+01; -//--- check - if(w==5) - r=-1.225e+01; -//--- check - if(w==4) - r=-1.261e+01; -//--- check - if(w==3) - r=-1.295e+01; -//--- check - if(w==2) - r=-1.346e+01; -//--- check - if(w==1) - r=-1.386e+01; -//--- check - if(w<=0) - r=-1.456e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 22) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W22(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(3.080179e+01*s)+1.265000e+02); - if(w>=126) - r=-6.931e-01; -//--- check - if(w==125) - r=-7.189e-01; -//--- check - if(w==124) - r=-7.452e-01; -//--- check - if(w==123) - r=-7.722e-01; -//--- check - if(w==122) - r=-7.999e-01; -//--- check - if(w==121) - r=-8.283e-01; -//--- check - if(w==120) - r=-8.573e-01; -//--- check - if(w==119) - r=-8.871e-01; -//--- check - if(w==118) - r=-9.175e-01; -//--- check - if(w==117) - r=-9.486e-01; -//--- check - if(w==116) - r=-9.805e-01; -//--- check - if(w==115) - r=-1.013e+00; -//--- check - if(w==114) - r=-1.046e+00; -//--- check - if(w==113) - r=-1.080e+00; -//--- check - if(w==112) - r=-1.115e+00; -//--- check - if(w==111) - r=-1.151e+00; -//--- check - if(w==110) - r=-1.187e+00; -//--- check - if(w==109) - r=-1.224e+00; -//--- check - if(w==108) - r=-1.262e+00; -//--- check - if(w==107) - r=-1.301e+00; -//--- check - if(w==106) - r=-1.340e+00; -//--- check - if(w==105) - r=-1.381e+00; -//--- check - if(w==104) - r=-1.422e+00; -//--- check - if(w==103) - r=-1.464e+00; -//--- check - if(w==102) - r=-1.506e+00; -//--- check - if(w==101) - r=-1.550e+00; -//--- check - if(w==100) - r=-1.594e+00; -//--- check - if(w==99) - r=-1.640e+00; -//--- check - if(w==98) - r=-1.686e+00; -//--- check - if(w==97) - r=-1.733e+00; -//--- check - if(w==96) - r=-1.781e+00; -//--- check - if(w==95) - r=-1.830e+00; -//--- check - if(w==94) - r=-1.880e+00; -//--- check - if(w==93) - r=-1.930e+00; -//--- check - if(w==92) - r=-1.982e+00; -//--- check - if(w==91) - r=-2.034e+00; -//--- check - if(w==90) - r=-2.088e+00; -//--- check - if(w==89) - r=-2.142e+00; -//--- check - if(w==88) - r=-2.198e+00; -//--- check - if(w==87) - r=-2.254e+00; -//--- check - if(w==86) - r=-2.312e+00; -//--- check - if(w==85) - r=-2.370e+00; -//--- check - if(w==84) - r=-2.429e+00; -//--- check - if(w==83) - r=-2.490e+00; -//--- check - if(w==82) - r=-2.551e+00; -//--- check - if(w==81) - r=-2.614e+00; -//--- check - if(w==80) - r=-2.677e+00; -//--- check - if(w==79) - r=-2.742e+00; -//--- check - if(w==78) - r=-2.808e+00; -//--- check - if(w==77) - r=-2.875e+00; -//--- check - if(w==76) - r=-2.943e+00; -//--- check - if(w==75) - r=-3.012e+00; -//--- check - if(w==74) - r=-3.082e+00; -//--- check - if(w==73) - r=-3.153e+00; -//--- check - if(w==72) - r=-3.226e+00; -//--- check - if(w==71) - r=-3.300e+00; -//--- check - if(w==70) - r=-3.375e+00; -//--- check - if(w==69) - r=-3.451e+00; -//--- check - if(w==68) - r=-3.529e+00; -//--- check - if(w==67) - r=-3.607e+00; -//--- check - if(w==66) - r=-3.687e+00; -//--- check - if(w==65) - r=-3.769e+00; -//--- check - if(w==64) - r=-3.851e+00; -//--- check - if(w==63) - r=-3.935e+00; -//--- check - if(w==62) - r=-4.021e+00; -//--- check - if(w==61) - r=-4.108e+00; -//--- check - if(w==60) - r=-4.196e+00; -//--- check - if(w==59) - r=-4.285e+00; -//--- check - if(w==58) - r=-4.376e+00; -//--- check - if(w==57) - r=-4.469e+00; -//--- check - if(w==56) - r=-4.563e+00; -//--- check - if(w==55) - r=-4.659e+00; -//--- check - if(w==54) - r=-4.756e+00; -//--- check - if(w==53) - r=-4.855e+00; -//--- check - if(w==52) - r=-4.955e+00; -//--- check - if(w==51) - r=-5.057e+00; -//--- check - if(w==50) - r=-5.161e+00; -//--- check - if(w==49) - r=-5.266e+00; -//--- check - if(w==48) - r=-5.374e+00; -//--- check - if(w==47) - r=-5.483e+00; -//--- check - if(w==46) - r=-5.594e+00; -//--- check - if(w==45) - r=-5.706e+00; -//--- check - if(w==44) - r=-5.821e+00; -//--- check - if(w==43) - r=-5.938e+00; -//--- check - if(w==42) - r=-6.057e+00; -//--- check - if(w==41) - r=-6.177e+00; -//--- check - if(w==40) - r=-6.300e+00; -//--- check - if(w==39) - r=-6.426e+00; -//--- check - if(w==38) - r=-6.553e+00; -//--- check - if(w==37) - r=-6.683e+00; -//--- check - if(w==36) - r=-6.815e+00; -//--- check - if(w==35) - r=-6.949e+00; -//--- check - if(w==34) - r=-7.086e+00; -//--- check - if(w==33) - r=-7.226e+00; -//--- check - if(w==32) - r=-7.368e+00; -//--- check - if(w==31) - r=-7.513e+00; -//--- check - if(w==30) - r=-7.661e+00; -//--- check - if(w==29) - r=-7.813e+00; -//--- check - if(w==28) - r=-7.966e+00; -//--- check - if(w==27) - r=-8.124e+00; -//--- check - if(w==26) - r=-8.285e+00; -//--- check - if(w==25) - r=-8.449e+00; -//--- check - if(w==24) - r=-8.617e+00; -//--- check - if(w==23) - r=-8.789e+00; -//--- check - if(w==22) - r=-8.965e+00; -//--- check - if(w==21) - r=-9.147e+00; -//--- check - if(w==20) - r=-9.333e+00; -//--- check - if(w==19) - r=-9.522e+00; -//--- check - if(w==18) - r=-9.716e+00; -//--- check - if(w==17) - r=-9.917e+00; -//--- check - if(w==16) - r=-1.012e+01; -//--- check - if(w==15) - r=-1.033e+01; -//--- check - if(w==14) - r=-1.055e+01; -//--- check - if(w==13) - r=-1.077e+01; -//--- check - if(w==12) - r=-1.100e+01; -//--- check - if(w==11) - r=-1.124e+01; -//--- check - if(w==10) - r=-1.149e+01; -//--- check - if(w==9) - r=-1.175e+01; -//--- check - if(w==8) - r=-1.203e+01; -//--- check - if(w==7) - r=-1.230e+01; -//--- check - if(w==6) - r=-1.261e+01; -//--- check - if(w==5) - r=-1.295e+01; -//--- check - if(w==4) - r=-1.330e+01; -//--- check - if(w==3) - r=-1.364e+01; -//--- check - if(w==2) - r=-1.415e+01; -//--- check - if(w==1) - r=-1.456e+01; -//--- check - if(w<=0) - r=-1.525e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 23) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W23(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(3.287856e+01*s)+1.380000e+02); - if(w>=138) - r=-6.813e-01; -//--- check - if(w==137) - r=-7.051e-01; -//--- check - if(w==136) - r=-7.295e-01; -//--- check - if(w==135) - r=-7.544e-01; -//--- check - if(w==134) - r=-7.800e-01; -//--- check - if(w==133) - r=-8.061e-01; -//--- check - if(w==132) - r=-8.328e-01; -//--- check - if(w==131) - r=-8.601e-01; -//--- check - if(w==130) - r=-8.880e-01; -//--- check - if(w==129) - r=-9.166e-01; -//--- check - if(w==128) - r=-9.457e-01; -//--- check - if(w==127) - r=-9.755e-01; -//--- check - if(w==126) - r=-1.006e+00; -//--- check - if(w==125) - r=-1.037e+00; -//--- check - if(w==124) - r=-1.069e+00; -//--- check - if(w==123) - r=-1.101e+00; -//--- check - if(w==122) - r=-1.134e+00; -//--- check - if(w==121) - r=-1.168e+00; -//--- check - if(w==120) - r=-1.202e+00; -//--- check - if(w==119) - r=-1.237e+00; -//--- check - if(w==118) - r=-1.273e+00; -//--- check - if(w==117) - r=-1.309e+00; -//--- check - if(w==116) - r=-1.347e+00; -//--- check - if(w==115) - r=-1.384e+00; -//--- check - if(w==114) - r=-1.423e+00; -//--- check - if(w==113) - r=-1.462e+00; -//--- check - if(w==112) - r=-1.502e+00; -//--- check - if(w==111) - r=-1.543e+00; -//--- check - if(w==110) - r=-1.585e+00; -//--- check - if(w==109) - r=-1.627e+00; -//--- check - if(w==108) - r=-1.670e+00; -//--- check - if(w==107) - r=-1.714e+00; -//--- check - if(w==106) - r=-1.758e+00; -//--- check - if(w==105) - r=-1.804e+00; -//--- check - if(w==104) - r=-1.850e+00; -//--- check - if(w==103) - r=-1.897e+00; -//--- check - if(w==102) - r=-1.944e+00; -//--- check - if(w==101) - r=-1.993e+00; -//--- check - if(w==100) - r=-2.042e+00; -//--- check - if(w==99) - r=-2.093e+00; -//--- check - if(w==98) - r=-2.144e+00; -//--- check - if(w==97) - r=-2.195e+00; -//--- check - if(w==96) - r=-2.248e+00; -//--- check - if(w==95) - r=-2.302e+00; -//--- check - if(w==94) - r=-2.356e+00; -//--- check - if(w==93) - r=-2.412e+00; -//--- check - if(w==92) - r=-2.468e+00; -//--- check - if(w==91) - r=-2.525e+00; -//--- check - if(w==90) - r=-2.583e+00; -//--- check - if(w==89) - r=-2.642e+00; -//--- check - if(w==88) - r=-2.702e+00; -//--- check - if(w==87) - r=-2.763e+00; -//--- check - if(w==86) - r=-2.825e+00; -//--- check - if(w==85) - r=-2.888e+00; -//--- check - if(w==84) - r=-2.951e+00; -//--- check - if(w==83) - r=-3.016e+00; -//--- check - if(w==82) - r=-3.082e+00; -//--- check - if(w==81) - r=-3.149e+00; -//--- check - if(w==80) - r=-3.216e+00; -//--- check - if(w==79) - r=-3.285e+00; -//--- check - if(w==78) - r=-3.355e+00; -//--- check - if(w==77) - r=-3.426e+00; -//--- check - if(w==76) - r=-3.498e+00; -//--- check - if(w==75) - r=-3.571e+00; -//--- check - if(w==74) - r=-3.645e+00; -//--- check - if(w==73) - r=-3.721e+00; -//--- check - if(w==72) - r=-3.797e+00; -//--- check - if(w==71) - r=-3.875e+00; -//--- check - if(w==70) - r=-3.953e+00; -//--- check - if(w==69) - r=-4.033e+00; -//--- check - if(w==68) - r=-4.114e+00; -//--- check - if(w==67) - r=-4.197e+00; -//--- check - if(w==66) - r=-4.280e+00; -//--- check - if(w==65) - r=-4.365e+00; -//--- check - if(w==64) - r=-4.451e+00; -//--- check - if(w==63) - r=-4.539e+00; -//--- check - if(w==62) - r=-4.628e+00; -//--- check - if(w==61) - r=-4.718e+00; -//--- check - if(w==60) - r=-4.809e+00; -//--- check - if(w==59) - r=-4.902e+00; -//--- check - if(w==58) - r=-4.996e+00; -//--- check - if(w==57) - r=-5.092e+00; -//--- check - if(w==56) - r=-5.189e+00; -//--- check - if(w==55) - r=-5.287e+00; -//--- check - if(w==54) - r=-5.388e+00; -//--- check - if(w==53) - r=-5.489e+00; -//--- check - if(w==52) - r=-5.592e+00; -//--- check - if(w==51) - r=-5.697e+00; -//--- check - if(w==50) - r=-5.804e+00; -//--- check - if(w==49) - r=-5.912e+00; -//--- check - if(w==48) - r=-6.022e+00; -//--- check - if(w==47) - r=-6.133e+00; -//--- check - if(w==46) - r=-6.247e+00; -//--- check - if(w==45) - r=-6.362e+00; -//--- check - if(w==44) - r=-6.479e+00; -//--- check - if(w==43) - r=-6.598e+00; -//--- check - if(w==42) - r=-6.719e+00; -//--- check - if(w==41) - r=-6.842e+00; -//--- check - if(w==40) - r=-6.967e+00; -//--- check - if(w==39) - r=-7.094e+00; -//--- check - if(w==38) - r=-7.224e+00; -//--- check - if(w==37) - r=-7.355e+00; -//--- check - if(w==36) - r=-7.489e+00; -//--- check - if(w==35) - r=-7.625e+00; -//--- check - if(w==34) - r=-7.764e+00; -//--- check - if(w==33) - r=-7.905e+00; -//--- check - if(w==32) - r=-8.049e+00; -//--- check - if(w==31) - r=-8.196e+00; -//--- check - if(w==30) - r=-8.345e+00; -//--- check - if(w==29) - r=-8.498e+00; -//--- check - if(w==28) - r=-8.653e+00; -//--- check - if(w==27) - r=-8.811e+00; -//--- check - if(w==26) - r=-8.974e+00; -//--- check - if(w==25) - r=-9.139e+00; -//--- check - if(w==24) - r=-9.308e+00; -//--- check - if(w==23) - r=-9.481e+00; -//--- check - if(w==22) - r=-9.658e+00; -//--- check - if(w==21) - r=-9.840e+00; -//--- check - if(w==20) - r=-1.003e+01; -//--- check - if(w==19) - r=-1.022e+01; -//--- check - if(w==18) - r=-1.041e+01; -//--- check - if(w==17) - r=-1.061e+01; -//--- check - if(w==16) - r=-1.081e+01; -//--- check - if(w==15) - r=-1.102e+01; -//--- check - if(w==14) - r=-1.124e+01; -//--- check - if(w==13) - r=-1.147e+01; -//--- check - if(w==12) - r=-1.169e+01; -//--- check - if(w==11) - r=-1.194e+01; -//--- check - if(w==10) - r=-1.218e+01; -//--- check - if(w==9) - r=-1.245e+01; -//--- check - if(w==8) - r=-1.272e+01; -//--- check - if(w==7) - r=-1.300e+01; -//--- check - if(w==6) - r=-1.330e+01; -//--- check - if(w==5) - r=-1.364e+01; -//--- check - if(w==4) - r=-1.400e+01; -//--- check - if(w==3) - r=-1.433e+01; -//--- check - if(w==2) - r=-1.484e+01; -//--- check - if(w==1) - r=-1.525e+01; -//--- check - if(w<=0) - r=-1.594e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 24) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W24(const double s) - { -//--- create variables - int w=0; - double r=0; -//--- check - w=(int)MathRound(-(3.500000e+01*s)+1.500000e+02); - if(w>=150) - r=-6.820e-01; -//--- check - if(w==149) - r=-7.044e-01; -//--- check - if(w==148) - r=-7.273e-01; -//--- check - if(w==147) - r=-7.507e-01; -//--- check - if(w==146) - r=-7.746e-01; -//--- check - if(w==145) - r=-7.990e-01; -//--- check - if(w==144) - r=-8.239e-01; -//--- check - if(w==143) - r=-8.494e-01; -//--- check - if(w==142) - r=-8.754e-01; -//--- check - if(w==141) - r=-9.020e-01; -//--- check - if(w==140) - r=-9.291e-01; -//--- check - if(w==139) - r=-9.567e-01; -//--- check - if(w==138) - r=-9.849e-01; -//--- check - if(w==137) - r=-1.014e+00; -//--- check - if(w==136) - r=-1.043e+00; -//--- check - if(w==135) - r=-1.073e+00; -//--- check - if(w==134) - r=-1.103e+00; -//--- check - if(w==133) - r=-1.135e+00; -//--- check - if(w==132) - r=-1.166e+00; -//--- check - if(w==131) - r=-1.198e+00; -//--- check - if(w==130) - r=-1.231e+00; -//--- check - if(w==129) - r=-1.265e+00; -//--- check - if(w==128) - r=-1.299e+00; -//--- check - if(w==127) - r=-1.334e+00; -//--- check - if(w==126) - r=-1.369e+00; -//--- check - if(w==125) - r=-1.405e+00; -//--- check - if(w==124) - r=-1.441e+00; -//--- check - if(w==123) - r=-1.479e+00; -//--- check - if(w==122) - r=-1.517e+00; -//--- check - if(w==121) - r=-1.555e+00; -//--- check - if(w==120) - r=-1.594e+00; -//--- check - if(w==119) - r=-1.634e+00; -//--- check - if(w==118) - r=-1.675e+00; -//--- check - if(w==117) - r=-1.716e+00; -//--- check - if(w==116) - r=-1.758e+00; -//--- check - if(w==115) - r=-1.800e+00; -//--- check - if(w==114) - r=-1.844e+00; -//--- check - if(w==113) - r=-1.888e+00; -//--- check - if(w==112) - r=-1.932e+00; -//--- check - if(w==111) - r=-1.978e+00; -//--- check - if(w==110) - r=-2.024e+00; -//--- check - if(w==109) - r=-2.070e+00; -//--- check - if(w==108) - r=-2.118e+00; -//--- check - if(w==107) - r=-2.166e+00; -//--- check - if(w==106) - r=-2.215e+00; -//--- check - if(w==105) - r=-2.265e+00; -//--- check - if(w==104) - r=-2.316e+00; -//--- check - if(w==103) - r=-2.367e+00; -//--- check - if(w==102) - r=-2.419e+00; -//--- check - if(w==101) - r=-2.472e+00; -//--- check - if(w==100) - r=-2.526e+00; -//--- check - if(w==99) - r=-2.580e+00; -//--- check - if(w==98) - r=-2.636e+00; -//--- check - if(w==97) - r=-2.692e+00; -//--- check - if(w==96) - r=-2.749e+00; -//--- check - if(w==95) - r=-2.806e+00; -//--- check - if(w==94) - r=-2.865e+00; -//--- check - if(w==93) - r=-2.925e+00; -//--- check - if(w==92) - r=-2.985e+00; -//--- check - if(w==91) - r=-3.046e+00; -//--- check - if(w==90) - r=-3.108e+00; -//--- check - if(w==89) - r=-3.171e+00; -//--- check - if(w==88) - r=-3.235e+00; -//--- check - if(w==87) - r=-3.300e+00; -//--- check - if(w==86) - r=-3.365e+00; -//--- check - if(w==85) - r=-3.432e+00; -//--- check - if(w==84) - r=-3.499e+00; -//--- check - if(w==83) - r=-3.568e+00; -//--- check - if(w==82) - r=-3.637e+00; -//--- check - if(w==81) - r=-3.708e+00; -//--- check - if(w==80) - r=-3.779e+00; -//--- check - if(w==79) - r=-3.852e+00; -//--- check - if(w==78) - r=-3.925e+00; -//--- check - if(w==77) - r=-4.000e+00; -//--- check - if(w==76) - r=-4.075e+00; -//--- check - if(w==75) - r=-4.151e+00; -//--- check - if(w==74) - r=-4.229e+00; -//--- check - if(w==73) - r=-4.308e+00; -//--- check - if(w==72) - r=-4.387e+00; -//--- check - if(w==71) - r=-4.468e+00; -//--- check - if(w==70) - r=-4.550e+00; -//--- check - if(w==69) - r=-4.633e+00; -//--- check - if(w==68) - r=-4.718e+00; -//--- check - if(w==67) - r=-4.803e+00; -//--- check - if(w==66) - r=-4.890e+00; -//--- check - if(w==65) - r=-4.978e+00; -//--- check - if(w==64) - r=-5.067e+00; -//--- check - if(w==63) - r=-5.157e+00; -//--- check - if(w==62) - r=-5.249e+00; -//--- check - if(w==61) - r=-5.342e+00; -//--- check - if(w==60) - r=-5.436e+00; -//--- check - if(w==59) - r=-5.531e+00; -//--- check - if(w==58) - r=-5.628e+00; -//--- check - if(w==57) - r=-5.727e+00; -//--- check - if(w==56) - r=-5.826e+00; -//--- check - if(w==55) - r=-5.927e+00; -//--- check - if(w==54) - r=-6.030e+00; -//--- check - if(w==53) - r=-6.134e+00; -//--- check - if(w==52) - r=-6.240e+00; -//--- check - if(w==51) - r=-6.347e+00; -//--- check - if(w==50) - r=-6.456e+00; -//--- check - if(w==49) - r=-6.566e+00; -//--- check - if(w==48) - r=-6.678e+00; -//--- check - if(w==47) - r=-6.792e+00; -//--- check - if(w==46) - r=-6.907e+00; -//--- check - if(w==45) - r=-7.025e+00; -//--- check - if(w==44) - r=-7.144e+00; -//--- check - if(w==43) - r=-7.265e+00; -//--- check - if(w==42) - r=-7.387e+00; -//--- check - if(w==41) - r=-7.512e+00; -//--- check - if(w==40) - r=-7.639e+00; -//--- check - if(w==39) - r=-7.768e+00; -//--- check - if(w==38) - r=-7.899e+00; -//--- check - if(w==37) - r=-8.032e+00; -//--- check - if(w==36) - r=-8.167e+00; -//--- check - if(w==35) - r=-8.305e+00; -//--- check - if(w==34) - r=-8.445e+00; -//--- check - if(w==33) - r=-8.588e+00; -//--- check - if(w==32) - r=-8.733e+00; -//--- check - if(w==31) - r=-8.881e+00; -//--- check - if(w==30) - r=-9.031e+00; -//--- check - if(w==29) - r=-9.185e+00; -//--- check - if(w==28) - r=-9.341e+00; -//--- check - if(w==27) - r=-9.501e+00; -//--- check - if(w==26) - r=-9.664e+00; -//--- check - if(w==25) - r=-9.830e+00; -//--- check - if(w==24) - r=-1.000e+01; -//--- check - if(w==23) - r=-1.017e+01; -//--- check - if(w==22) - r=-1.035e+01; -//--- check - if(w==21) - r=-1.053e+01; -//--- check - if(w==20) - r=-1.072e+01; -//--- check - if(w==19) - r=-1.091e+01; -//--- check - if(w==18) - r=-1.110e+01; -//--- check - if(w==17) - r=-1.130e+01; -//--- check - if(w==16) - r=-1.151e+01; -//--- check - if(w==15) - r=-1.172e+01; -//--- check - if(w==14) - r=-1.194e+01; -//--- check - if(w==13) - r=-1.216e+01; -//--- check - if(w==12) - r=-1.239e+01; -//--- check - if(w==11) - r=-1.263e+01; -//--- check - if(w==10) - r=-1.287e+01; -//--- check - if(w==9) - r=-1.314e+01; -//--- check - if(w==8) - r=-1.342e+01; -//--- check - if(w==7) - r=-1.369e+01; -//--- check - if(w==6) - r=-1.400e+01; -//--- check - if(w==5) - r=-1.433e+01; -//--- check - if(w==4) - r=-1.469e+01; -//--- check - if(w==3) - r=-1.503e+01; -//--- check - if(w==2) - r=-1.554e+01; -//--- check - if(w==1) - r=-1.594e+01; -//--- check - if(w<=0) - r=-1.664e+01; -//--- return result - return(r); - } -//+------------------------------------------------------------------+ -//| Tail(S, 25) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W25(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.150509e+00,tj,tj1,result); - WCheb(x,-5.695528e+00,tj,tj1,result); - WCheb(x,-1.437637e+00,tj,tj1,result); - WCheb(x,-2.611906e-01,tj,tj1,result); - WCheb(x,-7.625722e-02,tj,tj1,result); - WCheb(x,-2.579892e-02,tj,tj1,result); - WCheb(x,-1.086876e-02,tj,tj1,result); - WCheb(x,-2.906543e-03,tj,tj1,result); - WCheb(x,-2.354881e-03,tj,tj1,result); - WCheb(x,1.007195e-04,tj,tj1,result); - WCheb(x,-8.437327e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 26) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W26(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.117622e+00,tj,tj1,result); - WCheb(x,-5.635159e+00,tj,tj1,result); - WCheb(x,-1.395167e+00,tj,tj1,result); - WCheb(x,-2.382823e-01,tj,tj1,result); - WCheb(x,-6.531987e-02,tj,tj1,result); - WCheb(x,-2.060112e-02,tj,tj1,result); - WCheb(x,-8.203697e-03,tj,tj1,result); - WCheb(x,-1.516523e-03,tj,tj1,result); - WCheb(x,-1.431364e-03,tj,tj1,result); - WCheb(x,6.384553e-04,tj,tj1,result); - WCheb(x,-3.238369e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 27) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W27(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.089731e+00,tj,tj1,result); - WCheb(x,-5.584248e+00,tj,tj1,result); - WCheb(x,-1.359966e+00,tj,tj1,result); - WCheb(x,-2.203696e-01,tj,tj1,result); - WCheb(x,-5.753344e-02,tj,tj1,result); - WCheb(x,-1.761891e-02,tj,tj1,result); - WCheb(x,-7.096897e-03,tj,tj1,result); - WCheb(x,-1.419108e-03,tj,tj1,result); - WCheb(x,-1.581214e-03,tj,tj1,result); - WCheb(x,3.033766e-04,tj,tj1,result); - WCheb(x,-5.901441e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 28) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W28(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.065046e+00,tj,tj1,result); - WCheb(x,-5.539163e+00,tj,tj1,result); - WCheb(x,-1.328939e+00,tj,tj1,result); - WCheb(x,-2.046376e-01,tj,tj1,result); - WCheb(x,-5.061515e-02,tj,tj1,result); - WCheb(x,-1.469271e-02,tj,tj1,result); - WCheb(x,-5.711578e-03,tj,tj1,result); - WCheb(x,-8.389153e-04,tj,tj1,result); - WCheb(x,-1.250575e-03,tj,tj1,result); - WCheb(x,4.047245e-04,tj,tj1,result); - WCheb(x,-5.128555e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 29) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W29(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.043413e+00,tj,tj1,result); - WCheb(x,-5.499756e+00,tj,tj1,result); - WCheb(x,-1.302137e+00,tj,tj1,result); - WCheb(x,-1.915129e-01,tj,tj1,result); - WCheb(x,-4.516329e-02,tj,tj1,result); - WCheb(x,-1.260064e-02,tj,tj1,result); - WCheb(x,-4.817269e-03,tj,tj1,result); - WCheb(x,-5.478130e-04,tj,tj1,result); - WCheb(x,-1.111668e-03,tj,tj1,result); - WCheb(x,4.093451e-04,tj,tj1,result); - WCheb(x,-5.135860e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 30) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W30(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-5.024071e+00,tj,tj1,result); - WCheb(x,-5.464515e+00,tj,tj1,result); - WCheb(x,-1.278342e+00,tj,tj1,result); - WCheb(x,-1.800030e-01,tj,tj1,result); - WCheb(x,-4.046294e-02,tj,tj1,result); - WCheb(x,-1.076162e-02,tj,tj1,result); - WCheb(x,-3.968677e-03,tj,tj1,result); - WCheb(x,-1.911679e-04,tj,tj1,result); - WCheb(x,-8.619185e-04,tj,tj1,result); - WCheb(x,5.125362e-04,tj,tj1,result); - WCheb(x,-3.984370e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 40) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W40(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-4.904809e+00,tj,tj1,result); - WCheb(x,-5.248327e+00,tj,tj1,result); - WCheb(x,-1.136698e+00,tj,tj1,result); - WCheb(x,-1.170982e-01,tj,tj1,result); - WCheb(x,-1.824427e-02,tj,tj1,result); - WCheb(x,-3.888648e-03,tj,tj1,result); - WCheb(x,-1.344929e-03,tj,tj1,result); - WCheb(x,2.790407e-04,tj,tj1,result); - WCheb(x,-4.619858e-04,tj,tj1,result); - WCheb(x,3.359121e-04,tj,tj1,result); - WCheb(x,-2.883026e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 60) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W60(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-4.809656e+00,tj,tj1,result); - WCheb(x,-5.077191e+00,tj,tj1,result); - WCheb(x,-1.029402e+00,tj,tj1,result); - WCheb(x,-7.507931e-02,tj,tj1,result); - WCheb(x,-6.506226e-03,tj,tj1,result); - WCheb(x,-1.391278e-03,tj,tj1,result); - WCheb(x,-4.263635e-04,tj,tj1,result); - WCheb(x,2.302271e-04,tj,tj1,result); - WCheb(x,-2.384348e-04,tj,tj1,result); - WCheb(x,1.865587e-04,tj,tj1,result); - WCheb(x,-1.622355e-04,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 120) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W120(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-4.729426e+00,tj,tj1,result); - WCheb(x,-4.934426e+00,tj,tj1,result); - WCheb(x,-9.433231e-01,tj,tj1,result); - WCheb(x,-4.492504e-02,tj,tj1,result); - WCheb(x,1.673948e-05,tj,tj1,result); - WCheb(x,-6.077014e-04,tj,tj1,result); - WCheb(x,-7.215768e-05,tj,tj1,result); - WCheb(x,9.086734e-05,tj,tj1,result); - WCheb(x,-8.447980e-05,tj,tj1,result); - WCheb(x,6.705028e-05,tj,tj1,result); - WCheb(x,-5.828507e-05,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S, 200) | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::W200(const double s) - { -//--- create variables - double result=0; - double x=0; - double tj=0; - double tj1=0; -//--- change values - x=MathMin(2*(s-0.000000e+00)/4.000000e+00-1,1.0); - tj=1; - tj1=x; -//--- interpolating - WCheb(x,-4.700240e+00,tj,tj1,result); - WCheb(x,-4.883080e+00,tj,tj1,result); - WCheb(x,-9.132168e-01,tj,tj1,result); - WCheb(x,-3.512684e-02,tj,tj1,result); - WCheb(x,1.726342e-03,tj,tj1,result); - WCheb(x,-5.189796e-04,tj,tj1,result); - WCheb(x,-1.628659e-06,tj,tj1,result); - WCheb(x,4.261786e-05,tj,tj1,result); - WCheb(x,-4.002498e-05,tj,tj1,result); - WCheb(x,3.146287e-05,tj,tj1,result); - WCheb(x,-2.727576e-05,tj,tj1,result); -//--- return result - return(result); - } -//+------------------------------------------------------------------+ -//| Tail(S,N), S>=0 | -//+------------------------------------------------------------------+ -static double CWilcoxonSignedRank::WSigma(const double s,const int n) - { -//--- create variables - double f0; - double f1; - double f2; - double f3; - double f4; - double x0; - double x1; - double x2; - double x3; - double x4; - double x; -//--- initialization - f4=0; -//--- check - if(n==5) - return(W5(s)); -//--- check - if(n==6) - return(W6(s)); -//--- check - if(n==7) - return(W7(s)); -//--- check - if(n==8) - return(W8(s)); -//--- check - if(n==9) - return(W9(s)); -//--- check - if(n==10) - return(W10(s)); -//--- check - if(n==11) - return(W11(s)); -//--- check - if(n==12) - return(W12(s)); -//--- check - if(n==13) - return(W13(s)); -//--- check - if(n==14) - return(W14(s)); -//--- check - if(n==15) - return(W15(s)); -//--- check - if(n==16) - return(W16(s)); -//--- check - if(n==17) - return(W17(s)); -//--- check - if(n==18) - return(W18(s)); -//--- check - if(n==19) - return(W19(s)); -//--- check - if(n==20) - return(W20(s)); -//--- check - if(n==21) - return(W21(s)); -//--- check - if(n==22) - return(W22(s)); -//--- check - if(n==23) - return(W23(s)); -//--- check - if(n==24) - return(W24(s)); -//--- check - if(n==25) - return(W25(s)); -//--- check - if(n==26) - return(W26(s)); -//--- check - if(n==27) - return(W27(s)); -//--- check - if(n==28) - return(W28(s)); -//--- check - if(n==29) - return(W29(s)); -//--- check - if(n==30) - return(W30(s)); -//--- check - if(n>30) - { - x=1.0/n; - x0=1.0/30; - f0=W30(s); - x1=1.0/40; - f1=W40(s); - x2=1.0/60; - f2=W60(s); - x3=1.0/120; - f3=W120(s); - x4=1.0/200; - f4=W200(s); - //--- get result - f1=((x-x0)*f1-(x-x1)*f0)/(x1-x0); - f2=((x-x0)*f2-(x-x2)*f0)/(x2-x0); - f3=((x-x0)*f3-(x-x3)*f0)/(x3-x0); - f4=((x-x0)*f4-(x-x4)*f0)/(x4-x0); - f2=((x-x1)*f2-(x-x2)*f1)/(x2-x1); - f3=((x-x1)*f3-(x-x3)*f1)/(x3-x1); - f4=((x-x1)*f4-(x-x4)*f1)/(x4-x1); - f3=((x-x2)*f3-(x-x3)*f2)/(x3-x2); - f4=((x-x2)*f4-(x-x4)*f2)/(x4-x2); - f4=((x-x3)*f4-(x-x4)*f3)/(x4-x3); - } -//--- return result - return(f4); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/dictionary.mqh b/Include/Math/Fuzzy/dictionary.mqh deleted file mode 100644 index 5e93a4c..0000000 --- a/Include/Math/Fuzzy/dictionary.mqh +++ /dev/null @@ -1,197 +0,0 @@ -//+------------------------------------------------------------------+ -//| dictionary.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include -#include "RuleParser.mqh" -//+------------------------------------------------------------------+ -//| Gets the value associated with the specified key in the CList | -//| Where key - string, value - CObject | -//+------------------------------------------------------------------+ -bool TryGetValue(CList *list,string key,CObject *&value) - { - for(int i=0; i -#include "FuzzyVariable.mqh" -#include "InferenceMethod.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Creating fuzzy rules | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| And/Or operator type | -//+------------------------------------------------------------------+ -enum OperatorType - { - And, // And operator - Or // Or operator - }; -//+------------------------------------------------------------------+ -//| Hedge modifiers | -//+------------------------------------------------------------------+ -enum HedgeType - { - None, // None - Slightly, // Cube root - Somewhat, // Square root - Very, // Square - Extremely // Cube - }; -//+------------------------------------------------------------------+ -//| Class of CConditions used in the 'if' expression | -//+------------------------------------------------------------------+ -class ICondition : public CObject - { -public: - //--- method to check type - virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_ICondition); } - }; -//+------------------------------------------------------------------+ -//| Single condition | -//+------------------------------------------------------------------+ -class CSingleCondition : public ICondition - { -private: - INamedVariable *m_var; // Type of variable - INamedValue *m_term; // Type of value - bool m_not; // Is MF inverted - -public: - CSingleCondition(void); - CSingleCondition(INamedVariable *var,INamedValue *term); - CSingleCondition(INamedVariable *var,INamedValue *term,bool not); - ~CSingleCondition(void); - //--- methods gets or sets the varriable - INamedVariable *Var(void) { return(m_var); } - void Var(INamedVariable *value) { m_var=value; } - //--- methods gets or sets mark "Is MF inverted" - bool Not(void) { return(m_not); } - void Not(bool not) { m_not=not; } - //--- methods gets or sets term in expression - INamedValue *Term(void) { return(m_term); } - void Term(INamedValue *value) { m_term=value; } - //--- method to check type - virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_SingleCondition); } - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSingleCondition::CSingleCondition(void) - { - m_var = NULL; - m_not = false; - m_term=NULL; - }; -//+------------------------------------------------------------------+ -//| First constructor with parameters | -//+------------------------------------------------------------------+ -CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term) - { - m_var=var; - m_term=term; - } -//+------------------------------------------------------------------+ -//| Second constructor with parameters | -//+------------------------------------------------------------------+ -CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term,bool not) - { - m_var=var; - m_term=term; - m_not=not; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSingleCondition::~CSingleCondition(void) - { - if(CheckPointer(m_var)==POINTER_DYNAMIC) - delete m_var; - if(CheckPointer(m_term)==POINTER_DYNAMIC) - delete m_term; - } -//+------------------------------------------------------------------+ -//| Condition of fuzzy rule for the both Mamdani and Sugeno systems | -//+------------------------------------------------------------------+ -class CFuzzyCondition : public CSingleCondition - { -private: - HedgeType m_hedge; // hedge type - -public: - CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not); - CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge); - CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term); - ~CFuzzyCondition(void); - //--- methods gets or sets the hedge type - HedgeType Hedge(void) { return (m_hedge); } - void Hedge(HedgeType value) { m_hedge=value; } - //--- method to check type - virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_FuzzyCondition); } - }; -//+------------------------------------------------------------------+ -//| First constructor with parameters | -//+------------------------------------------------------------------+ -CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not) - { - CSingleCondition::Var(var); - CSingleCondition::Term(term); - CSingleCondition::Not(not); - m_hedge=None; - } -//+------------------------------------------------------------------+ -//| Second constructor with parameters | -//+------------------------------------------------------------------+ -CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge) - { - CSingleCondition::Var(var); - CSingleCondition::Term(term); - CSingleCondition::Not(not); - m_hedge=hedge; - } -//+------------------------------------------------------------------+ -//| Thrid constructor with parameters | -//+------------------------------------------------------------------+ -CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term) - - { - CSingleCondition::Var(var); - CSingleCondition::Term(term); - CSingleCondition::Not(false); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFuzzyCondition::~CFuzzyCondition(void) - { - - } -//+------------------------------------------------------------------+ -//| Several CConditions linked by or/and operators | -//+------------------------------------------------------------------+ -class CConditions : public ICondition - { -private: - bool m_not; // Default : false - OperatorType m_op; // Type of operator. Default : And - CList *m_conditions; // List of CConditions - -public: - CConditions(void); - ~CConditions(void); - //--- methods gets or sets the mark "Is MF inverted" - bool Not(void) { return(m_not); } - void Not(bool value) { m_not=value; } - //--- methods gets or sets operator that links expressions (and/or) - OperatorType Op(void) { return (m_op); } - void Op(OperatorType value) { m_op=value; } - //--- method gets the list of CConditions (single or multiples) - CList *ConditionsList(void) { return(m_conditions); } - //--- method to check type - virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_Conditions); } - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CConditions::CConditions(void) - { - m_not=false; - m_op = And; - m_conditions=new CList; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CConditions::~CConditions(void) - { - delete m_conditions; - } -//+------------------------------------------------------------------+ -//| Class used by rule parser | -//+------------------------------------------------------------------+ -class IParsableRule : public CObject - { -public: - //--- methods gets or sets the condition (IF) part of the rule - virtual CConditions *Condition(void) { return(NULL); } - virtual void Condition(CConditions *value) { } - //--- methods gets or sets the conclusion (THEN) part of the rule - virtual CSingleCondition *Conclusion(void) { return(NULL); } - virtual void Conclusion(CSingleCondition *value) { } - //--- method to check type - virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_IParsableRule); } - }; -//+------------------------------------------------------------------+ -//| Implements common functionality of fuzzy rules | -//+------------------------------------------------------------------+ -class CGenericFuzzyRule : public IParsableRule - { -private: - CConditions *m_generic_condition; // Generic path of condition - -public: - CGenericFuzzyRule(void); - ~CGenericFuzzyRule(void); - //--- methods gets or sets the condition (IF) part of the rule - CConditions *Condition(void) { return(m_generic_condition); } - void Condition(CConditions *value) { m_generic_condition=value; } - //--- methods create a single condition - CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term); - CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not); - CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge); - //--- methods gets or sets the conclusion (THEN) part of the rule - virtual CSingleCondition *Conclusion(void) { return(NULL); } - virtual void Conclusion(CSingleCondition *value) { } - //--- method to check type - virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_GenericFuzzyRule); } - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CGenericFuzzyRule::CGenericFuzzyRule(void) - { - m_generic_condition=new CConditions(); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CGenericFuzzyRule::~CGenericFuzzyRule(void) - { - delete m_generic_condition; - } -//+------------------------------------------------------------------+ -//| Create a single condition(1) | -//+------------------------------------------------------------------+ -CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term) - { -//--- return fuzzy condition - return new CFuzzyCondition(var, term); - } -//+------------------------------------------------------------------+ -//| Create a single condition(2) | -//+------------------------------------------------------------------+ -CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not) - { -//--- return fuzzy condition - return new CFuzzyCondition(var, term, not); - } -//+------------------------------------------------------------------+ -//| Create a single condition(3) | -//+------------------------------------------------------------------+ -CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge) - { -//--- return fuzzy condition - return new CFuzzyCondition(var, term, not, hedge); - } -//+------------------------------------------------------------------+ -//| Fuzzy rule for Mamdani fuzzy system. | -//| NOTE: a rule cannot be created directly, only via | -//| MamdaniFuzzySystem::EmptyRule or MamdaniFuzzySystem::ParseRule | -//+------------------------------------------------------------------+ -class CMamdaniFuzzyRule : public CGenericFuzzyRule - { -private: - CSingleCondition *m_mamdani_conclusion; // Mamdani conclusion - double m_weight; // Weight of Mamdani rule - -public: - CMamdaniFuzzyRule(void); - ~CMamdaniFuzzyRule(void); - //--- methods gets or sets the conclusion (THEN) part of the rule - CSingleCondition *Conclusion(void) { return(m_mamdani_conclusion); } - void Conclusion(CSingleCondition *value) { m_mamdani_conclusion=value; } - //--- methods gets or sets the rule weight - double Weight(void) { return(m_weight); } - void Weight(const double value) { m_weight=value; } - //--- method to check type - virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_MamdaniFuzzyRule); } - }; -//+---------------------------------------------------------------+ -//| Constructor without parameters | -//+---------------------------------------------------------------+ -CMamdaniFuzzyRule::CMamdaniFuzzyRule(void) - { - m_weight=1.0; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMamdaniFuzzyRule::~CMamdaniFuzzyRule(void) - { - if(CheckPointer(m_mamdani_conclusion)==POINTER_DYNAMIC) - delete m_mamdani_conclusion; - } -//+------------------------------------------------------------------+ -//| Fuzzy rule for Sugeno fuzzy system | -//| NOTE: a rule cannot be created directly, only via | -//| SugenoFuzzySystem::EmptyRule or SugenoFuzzySystem::ParseRule | -//+------------------------------------------------------------------+ -class CSugenoFuzzyRule : public CGenericFuzzyRule - { -private: - CSingleCondition *m_sugeno_conclusion; // Sugeno conclusion - -public: - CSugenoFuzzyRule(void); - ~CSugenoFuzzyRule(void); - //--- methods gets or sets the conclusion (THEN) part of the rule - CSingleCondition *Conclusion(void) { return(m_sugeno_conclusion); } - void Conclusion(CSingleCondition *value) { m_sugeno_conclusion=value; } - //--- method to check type - virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_SugenoFuzzyRule); } - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+-------------------------- ---------------------------------------+ -CSugenoFuzzyRule::CSugenoFuzzyRule(void) - { - - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSugenoFuzzyRule::~CSugenoFuzzyRule(void) - { - if(CheckPointer(m_sugeno_conclusion)==POINTER_DYNAMIC) - delete m_sugeno_conclusion; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/fuzzyterm.mqh b/Include/Math/Fuzzy/fuzzyterm.mqh deleted file mode 100644 index 9ea5823..0000000 --- a/Include/Math/Fuzzy/fuzzyterm.mqh +++ /dev/null @@ -1,69 +0,0 @@ -//+------------------------------------------------------------------+ -//| fuzzyterm.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "MembershipFunction.mqh" -#include "Helper.mqh" -//+------------------------------------------------------------------+ -//| Purpose: creating fuzzy term. | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Fuzzy or linguistic term. | -//+------------------------------------------------------------------+ -class CFuzzyTerm : public CNamedValueImpl - { -private: - IMembershipFunction *m_mf; // The membership function of the term - -public: - CFuzzyTerm(const string name,IMembershipFunction *mf); - ~CFuzzyTerm(void); - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_FuzzyTerm); } - //--- method gets the membership function initially associated with the term - IMembershipFunction *MembershipFunction() { return(m_mf); } - }; -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CFuzzyTerm::CFuzzyTerm(const string name,IMembershipFunction *mf) - { - CNamedValueImpl::Name(name); - m_mf=mf; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFuzzyTerm::~CFuzzyTerm(void) - { - if(CheckPointer(m_mf)==POINTER_DYNAMIC) - { - delete m_mf; - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/fuzzyvariable.mqh b/Include/Math/Fuzzy/fuzzyvariable.mqh deleted file mode 100644 index ab5ce97..0000000 --- a/Include/Math/Fuzzy/fuzzyvariable.mqh +++ /dev/null @@ -1,113 +0,0 @@ -//+------------------------------------------------------------------+ -//| fuzzyvariable.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "FuzzyTerm.mqh" -//+------------------------------------------------------------------+ -//| Purpose: creating fuzzy variable | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Fuzzy or linguistic variable. | -//+------------------------------------------------------------------+ -class CFuzzyVariable : public CNamedVariableImpl - { -private: - double m_min; // Minimum value of the variable - double m_max; // Maximum value of the variable - CList *m_terms; // List of terms in a variable - -public : - CFuzzyVariable(const string name,const double min,const double max); - ~CFuzzyVariable(void); - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_FuzzyVariable); } - //--- methods gets or sets parameters of varriable - void Max(const double max) { m_max=max; } - double Max(void) { return (m_max); } - void Min(const double min) { m_min=min; } - double Min(void) { return (m_min); } - //--- methods gets or sets the terms - CList *Terms() { return(m_terms); } - void Terms(CList *terms) { m_terms=terms; } - //--- add fuzzy term - void AddTerm(CFuzzyTerm *term); - //--- get membership function by name - CFuzzyTerm *GetTermByName(const string name); - //--- overload - CList *Values() { return(m_terms); } - }; -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CFuzzyVariable::CFuzzyVariable(const string name,const double min,const double max) - { - CNamedVariableImpl::Name(name); - m_terms=new CList(); - if(min>max) - { - Print("Incorrect parameters! Maximum value must be greater than minimum one."); - } - else - { - m_min = min; - m_max = max; - } - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFuzzyVariable::~CFuzzyVariable(void) - { - delete m_terms; - } -//+------------------------------------------------------------------+ -//| Add fuzzy term to list terms in a variable | -//+------------------------------------------------------------------+ -void CFuzzyVariable::AddTerm(CFuzzyTerm *term) - { - m_terms.Add(term); - } -//+------------------------------------------------------------------+ -//| Get membership function (term) by name | -//+------------------------------------------------------------------+ -CFuzzyTerm *CFuzzyVariable::GetTermByName(const string name) - { - for(int i=0; i -#include -#include "FuzzyRule.mqh" -#include "InferenceMethod.mqh" -#include "Dictionary.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Creating generic fuzzy system | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Common functionality of Mamdani and Sugeno fuzzy systems | -//+------------------------------------------------------------------+ -class CGenericFuzzySystem - { -private: - CList *m_input; // List of input fuzzy variables - AndMethod m_and_method; // And method from InferenceMethod - OrMethod m_or_method; // Or method from InferenceMethod - -protected: - CGenericFuzzySystem(void); - ~CGenericFuzzySystem(void); -public: - //--- method gets the input linguistic variables - CList *Input(void) { return(m_input); } - //--- method gets or sets the type of "And method" - void AndMethod(AndMethod value) { m_and_method=value; } - AndMethod AndMethod(void) { return (m_and_method); } - //--- method gets or sets the type of "Or method" - void OrMethod(OrMethod value) { m_or_method=value; } - OrMethod OrMethod(void) { return (m_or_method); } - //--- method gets the varriable by name - CFuzzyVariable *InputByName(const string name); - //--- common steps of calculating - CList *Fuzzify(CList *inputValues); -protected: - double EvaluateCondition(ICondition *condition,CList *fuzzifiedInput); - double EvaluateConditionPair(const double cond1,const double cond2,OperatorType op); -private: - bool ValidateInputValues(CList *inputValues,string &msg); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CGenericFuzzySystem::CGenericFuzzySystem(void) - { - m_input=new CList; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CGenericFuzzySystem::~CGenericFuzzySystem(void) - { - if(CheckPointer(m_input)==POINTER_DYNAMIC) - { - delete m_input; - } - } -//+------------------------------------------------------------------+ -//| Get input linguistic variable by its name | -//+------------------------------------------------------------------+ -CFuzzyVariable *CGenericFuzzySystem::InputByName(const string name) - { - CList *result=CGenericFuzzySystem::Input(); - for(int i=0; ivar.Max()) - { - msg=StringFormat("Value for the %s variable is out of range.",var.Name()); - //--- return false - return (false); - } - } - } - if(contain==false) - { - msg=StringFormat("Value for the %s variable does not present.",var.Name()); - //--- return false - return (false); - } - } -//--- return true - return (true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/helper.mqh b/Include/Math/Fuzzy/helper.mqh deleted file mode 100644 index 9530145..0000000 --- a/Include/Math/Fuzzy/helper.mqh +++ /dev/null @@ -1,158 +0,0 @@ -//+------------------------------------------------------------------+ -//| helper.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include "InferenceMethod.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Analysis of the fuzzy rules | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| This class must be implemented by values in parsable rules | -//+------------------------------------------------------------------+ -class INamedValue : public CObject - { -public: - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_INamedValue); } - //--- methods gets or sets the name - virtual string Name(void) { return(""); } - virtual void Name(const string name) { } - }; -//+------------------------------------------------------------------+ -//| This class must be implemented by values in parsable rules | -//+------------------------------------------------------------------+ -class INamedVariable : public INamedValue - { -public: - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_INamedValue); } - //--- get list of values that belongs to the variable - virtual CList *Values(void) { return(NULL); } - }; -//+------------------------------------------------------------------+ -//| Named variable | -//+------------------------------------------------------------------+ -class CNamedVariableImpl : public INamedVariable - { -private: - string m_name; // Name of the variable - -public: - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_NamedVariableImpl); } - //--- methods gets or sets varriable name - virtual void Name(const string name); - virtual string Name(void) { return(m_name); } - //--- get list of values that belongs to the variable - virtual CList *Values(void) { return(NULL); } - }; -//+------------------------------------------------------------------+ -//| Set variable name | -//+------------------------------------------------------------------+ -void CNamedVariableImpl::Name(const string name) - { - if(!CNameHelper::IsValidName(name)) - { - Print("Invalid variable name."); - } - m_name=name; - } -//+------------------------------------------------------------------+ -//| Named value of variable | -//+------------------------------------------------------------------+ -class CNamedValueImpl : public INamedValue - { -private: - string m_name; // Name of the value - -public: - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_NamedVariableImpl); } - //--- methods gets or sets varriable name - virtual void Name(const string name); - virtual string Name(void) { return(m_name); } - }; -//+------------------------------------------------------------------+ -//| Set variable name | -//+------------------------------------------------------------------+ -void CNamedValueImpl::Name(const string name) - { - if(!CNameHelper::IsValidName(name)) - { - Print("Invalid term name."); - } - m_name=name; - } -//+------------------------------------------------------------------+ -//| Keywords: | -//+------------------------------------------------------------------+ -static string KEYWORDS[]={ "if","then","is","and","or","not","(",")","slightly","somewhat","very","extremely" }; // Keywords in rules -//+------------------------------------------------------------------+ -//| Class NameHelper checks the availability of names | -//+------------------------------------------------------------------+ -class CNameHelper - { -public: - //+------------------------------------------------------------------+ - //| Check the name of variable/term | - //+------------------------------------------------------------------+ - static bool IsValidName(const string name) - { - //--- Empty names are not allowed - if(StringLen(name)==0) - { - //--- return false - return (false); - } - - for(int i=0; i=48 && s<=57) // Not numbers and symbol '_' - && !( s >= 65 && s <= 90 ) // Not capital letters - && !( s >= 97 && s <= 122 )) // Not letters - { - //--- return false - return (false); - } - } - //--- Identifier cannot be a keword - for(int i=0; i -//+------------------------------------------------------------------+ -//| Purpose: Contains a number of enumerations, | -//| for the convenience of working with other files | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| And evaluating method | -//+------------------------------------------------------------------+ -enum AndMethod - { - MinAnd, // Minimum: min(a, b) - ProductionAnd // Production: a * b - }; -//+------------------------------------------------------------------+ -//| Or evaluating method | -//+------------------------------------------------------------------+ -enum OrMethod - { - MaxOr, // Maximum: max(a, b) - ProbabilisticOr // Probabilistic OR: a + b - a * b - }; -//+------------------------------------------------------------------+ -//| Fuzzy implication method | -//+------------------------------------------------------------------+ -enum ImplicationMethod - { - MinIpm, // Truncation of output fuzzy set - ProductionImp // Scaling of output fuzzy set - }; -//+------------------------------------------------------------------+ -//| Aggregation method for membership functions | -//+------------------------------------------------------------------+ -enum AggregationMethod - { - MaxAgg, // Maximum of rule outpus - SumAgg // Sum of rule output - }; -//+------------------------------------------------------------------+ -//| Defuzzification method | -//+------------------------------------------------------------------+ -enum DefuzzificationMethod - { - CentroidDef, // Center of area of fuzzy result MF - BisectorDef, // The point divides the area under the MF into two equal - AverageMaximumDef, // Arithmetic mean of all the maxima of the MF - LargestMaximumDef, // The largest of the maxima of the membership function - SmallestMaximumDef // The smallest of the maxima of the membership function - }; -//+------------------------------------------------------------------+ -//| Type of varriable and term | -//+------------------------------------------------------------------+ -enum EnType - { - TYPE_CLASS_INamedValue, // Base class - TYPE_CLASS_INamedVariable, // INamedVariable : INamedValue - TYPE_CLASS_NamedVariableImpl, // NamedVariableImpl : INamedVariable - TYPE_CLASS_NamedValueImpl, // NamedValueImpl : INamedValue - TYPE_CLASS_FuzzyTerm, // FuzzyTerm : NamedValueImpl - TYPE_CLASS_FuzzyVariable, // FuzzyVariable : NamedVariableImpl - TYPE_CLASS_SugenoVariable, // SugenoVariable : NamedVariableImpl - TYPE_CLASS_ISugenoFunction, // ISugenoFunction : NamedValueImpl - TYPE_CLASS_LinearSugenoFunction // LinearSugenoFunction : ISugenoFunction - }; -//+------------------------------------------------------------------+ -//| Type of expression | -//+------------------------------------------------------------------+ -enum EnLexem - { - TYPE_CLASS_IExpression, // Base class - TYPE_CLASS_Lexem, // Lexem : IExpression - TYPE_CLASS_ConditionExpression, // ConditionExpression : IExpression - TYPE_CLASS_VarLexem, // VarLexem : Lexem - TYPE_CLASS_KeywordLexem, // KeywordLexem : Lexem - TYPE_CLASS_AltLexem, // AltLexem : Lexem - TYPE_CLASS_TermLexem // TermLexem : AltLexem - }; -//+------------------------------------------------------------------+ -//| Type of condition | -//+------------------------------------------------------------------+ -enum EnCondition - { - TYPE_CLASS_ICondition, // Base class - TYPE_CLASS_Conditions, // Conditions : ICondition - TYPE_CLASS_SingleCondition, // SingleCondition : ICondition - TYPE_CLASS_FuzzyCondition // FuzzyCondition : SingleCondition - }; -//+------------------------------------------------------------------+ -//| Type of rule | -//+------------------------------------------------------------------+ -enum EnRule - { - TYPE_CLASS_IParsableRule, // Base class - TYPE_CLASS_GenericFuzzyRule, // GenericFuzzyRule : IParsableRule - TYPE_CLASS_MamdaniFuzzyRule, // MamdaniFuzzyRule : GenericFuzzyRule - TYPE_CLASS_SugenoFuzzyRule // SugenoFuzzyRule : GenericFuzzyRule - }; -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/mamdanifuzzysystem.mqh b/Include/Math/Fuzzy/mamdanifuzzysystem.mqh deleted file mode 100644 index 26eb2bc..0000000 --- a/Include/Math/Fuzzy/mamdanifuzzysystem.mqh +++ /dev/null @@ -1,552 +0,0 @@ -//+------------------------------------------------------------------+ -//| mandanifuzzysystem.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -#include -#include "GenericFuzzySystem.mqh" -#include "InferenceMethod.mqh" -#include "RuleParser.mqh" -#include "FuzzyRule.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Creating Mamdani fuzzy system | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Mamdani fuzzy inference system | -//+------------------------------------------------------------------+ -class CMamdaniFuzzySystem : public CGenericFuzzySystem - { -private: - CList *m_output; // List of fuzzy variable - CList *m_rules; // List of Mamdani fuzzy rule - ImplicationMethod m_impl_method; // Implication method - AggregationMethod m_aggr_method; // Aggregation method - DefuzzificationMethod m_defuzz_method; // Defuzzification method - -public: - CMamdaniFuzzySystem(void); - ~CMamdaniFuzzySystem(void); - //--- method gets the output linguistic variables - CList *Output() { return(m_output); } - //--- method gets the fuzzy rule - CList *Rules() { return(m_rules); } - //--- methods gets or sets the implication method - ImplicationMethod ImplicationMethod() { return (m_impl_method); } - void ImplicationMethod(ImplicationMethod value) { m_impl_method=value; } - //--- methods gets or sets the aggregation method - AggregationMethod AggregationMethod() { return (m_aggr_method); } - void AggregationMethod(AggregationMethod value) { m_aggr_method=value; } - //--- methods gets or sets the defuzzification method - DefuzzificationMethod DefuzzificationMethod() { return (m_defuzz_method); } - void DefuzzificationMethod(DefuzzificationMethod value) { m_defuzz_method=value; } - //--- maethod gets the variable by name - CFuzzyVariable *OutputByName(const string name); - //--- create a new rule - CMamdaniFuzzyRule *EmptyRule(); - //--- parse rule - CMamdaniFuzzyRule *ParseRule(const string rule); - //--- method for calculate result - CList *Calculate(CList *inputValues); - CList *EvaluateConditions(CList *fuzzifiedInput); - CList *Implicate(CList *conditions); - CList *Aggregate(CList *conclusions); - CList *Defuzzify(CList *fuzzyResult); - double Defuzzify(IMembershipFunction *mf,const double min,const double max); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CMamdaniFuzzySystem::CMamdaniFuzzySystem(void) - { - m_output= new CList; - m_rules = new CList; - m_impl_method = MinIpm; // Implication method default is Min - m_aggr_method =MaxAgg; // Aggregation method default is Max - m_defuzz_method = CentroidDef; // Defuzzification method default is Centroid - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CMamdaniFuzzySystem::~CMamdaniFuzzySystem(void) - { - delete m_output; - delete m_rules; - } -//+------------------------------------------------------------------+ -//| Get output linguistic variable by its name | -//+------------------------------------------------------------------+ -CFuzzyVariable *CMamdaniFuzzySystem::OutputByName(const string name) - { - for(int i=0; i=halfArea) - { - break; - } - now=now+(max-min)/k; - } - delete mf; - //--- return result - return (now); - } - else if(m_defuzz_method==AverageMaximumDef) - { - //+------------------------------------------------------------------------------------------+ - //| AverageMaximum method is the arithmetic mean of all the maxima of the membership function| - //+------------------------------------------------------------------------------------------+ - double sum_max=0; // Sum of local maxima - double count_max=0; // Count of local maxima - int k=50; // The function is divided into "k" steps - double now=min; // The current position - double step=(max-min)/k; // Calculate the step function - for(int i=1; imf.GetValue(min+step)) - { - sum_max+=mf.GetValue(min); - count_max++; - } - } - //--- check the second element - if(i==k-1) - { - if(mf.GetValue(max)>mf.GetValue(max-step)) - { - sum_max+=mf.GetValue(max); - count_max++; - } - } - //--- check all the other elements - if((point_1>point_0) && (point_1>point_2)) - { - sum_max+=point_1; - count_max++; - } - } - if(count_max==0) - { - delete mf; - //--- return result - return (0); - } - else - { - delete mf; - //--- return result - return (sum_max/count_max); - } - } - else if(m_defuzz_method==LargestMaximumDef) - { - CArrayDouble *local_max=new CArrayDouble; // Array of all local maximum - double result; // Result of defuzzification method - int k=50; // The function is divided into "k" steps - double now=min; // The current position - double step=(max-min)/k; // Calculate the step function - for(int i=1; imf.GetValue(min+step)) - { - local_max.Add(mf.GetValue(min)); - } - } - //--- check the second element - if(i==k-1) - { - if(mf.GetValue(max)>mf.GetValue(max-step)) - { - local_max.Add(mf.GetValue(max)); - } - } - //--- check all the other elements - if((point_1>point_0) && (point_1>point_2)) - { - local_max.Add(point_1); - } - now+=step; - } - result=local_max.At(0); - for(int i=0; imf.GetValue(min+step)) - { - local_max.Add(mf.GetValue(min)); - } - } - //--- check the second element - if(i==k-1) - { - if(mf.GetValue(max)>mf.GetValue(max-step)) - { - local_max.Add(mf.GetValue(max)); - } - } - //--- check all the other elements - if((point_1>point_0) && (point_1>point_2)) - { - local_max.Add(point_1); - } - now+=step; - } - result=local_max.At(0); - for(int i=0; i=local_max.At(i)) - { - result=local_max.At(i); - } - } - now=min; - while(true) - { - if(mf.GetValue(now)==result) - { - break; - } - now+=step; - } - delete local_max; - delete mf; - //--- return result - return (now); - } - else - { - Print("Internal exception."); - delete mf; - //--- return - return (0); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Fuzzy/membershipfunction.mqh b/Include/Math/Fuzzy/membershipfunction.mqh deleted file mode 100644 index cd77783..0000000 --- a/Include/Math/Fuzzy/membershipfunction.mqh +++ /dev/null @@ -1,1008 +0,0 @@ -//+------------------------------------------------------------------+ -//| membershipfunction.mqh | -//| Copyright 2015-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//| Implementation of Fuzzy library in MetaQuotes Language 5 | -//| | -//| The features of the library include: | -//| - Create Mamdani fuzzy model | -//| - Create Sugeno fuzzy model | -//| - Normal membership function | -//| - Triangular membership function | -//| - Trapezoidal membership function | -//| - Constant membership function | -//| - Defuzzification method of center of gravity (COG) | -//| - Defuzzification method of bisector of area (BOA) | -//| - Defuzzification method of mean of maxima (MeOM) | -//| | -//| This file is free software; you can redistribute it and/or | -//| modify it under the terms of the GNU General Public License as | -//| published by the Free Software Foundation (www.fsf.org); either | -//| version 2 of the License, or (at your option) any later version. | -//| | -//| This program is distributed in the hope that it will be useful, | -//| but WITHOUT ANY WARRANTY; without even the implied warranty of | -//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -//| GNU General Public License for more details. | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Purpose: creating membership functions. | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Types of membership functions composition | -//+------------------------------------------------------------------+ -enum MfCompositionType - { - MinMF, // Minumum of functions - MaxMF, // Maximum of functions - ProdMF, // Production of functions - SumMF // Sum of functions - }; -//+------------------------------------------------------------------+ -//| The base class of all classes of membership functions | -//+------------------------------------------------------------------+ -class IMembershipFunction : public CObject - { -public: - //--- method evaluate value of the membership function - virtual double GetValue(const double x)=NULL; - }; -//+------------------------------------------------------------------+ -//| Gaussian combination membership function | -//+------------------------------------------------------------------+ -class CNormalCombinationMembershipFunction : public IMembershipFunction - { -private: - double m_b1; // Parametr b1: coordinate of the minimum membership function - double m_sigma1; // Parametr sigma1: concentration factor of the left path of function - double m_b2; // Parametr b2: coordinate of the maximum membership function - double m_sigma2; // Parametr sigma2: concentration factor of the rigth path of function - -public: - CNormalCombinationMembershipFunction(void); - CNormalCombinationMembershipFunction(const double b1,const double sigma1,const double b2,const double sigma2); - ~CNormalCombinationMembershipFunction(void); - //--- methods gets or sets the parametrs - void B1(const double b1) { m_b1=b1; } - double B1(void) { return(m_b1); } - void Sigma1(const double sigma1) { m_sigma1=sigma1; } - double Sigma1(void) { return(m_sigma1); } - void B2(const double b2) { m_b2=b2; } - double B2(void) { return(m_b2); } - void Sigma2(const double sigma2) { m_sigma2=sigma2; } - double Sigma2(void) { return(m_sigma2); } - //--- method gets the argument (x axis value) - double GetValue(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CNormalCombinationMembershipFunction::CNormalCombinationMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CNormalCombinationMembershipFunction::CNormalCombinationMembershipFunction(const double b1,const double sigma1,const double b2,const double sigma2) - { - m_b1=b1; - m_sigma1=sigma1; - m_b2=b2; - m_sigma2=sigma2; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CNormalCombinationMembershipFunction::~CNormalCombinationMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CNormalCombinationMembershipFunction::GetValue(const double x) - { - if(m_b1<=m_b2) - { - if(xm_b2) - { - //--- return result - return (exp((x - m_b2) * (x - m_b2) / ( -2.0 * m_sigma2 * m_sigma2))); - } - else - { - //--- m_b1 <= x && x <= m_b2 - //--- return result - return (1); - } - } - if(m_b1>m_b2) - { - if(xm_b1) - { - //--- return result - return (exp((x - m_b2) * (x - m_b2) / ( -2.0 * m_sigma2 * m_sigma2))); - } - else - { - //--- m_b1 <= x && x <= m_b2 - //--- return result - return ( exp((x - m_b1) * (x - m_b1) / ( -2.0 * m_sigma1 * m_sigma1)) * exp((x - m_b2) * (x - m_b2) / ( -2.0 * m_sigma2 * m_sigma2)) ); - } - } -//--- m_b1 == m_b2 -//--- return result - return (m_b1); - } -//+------------------------------------------------------------------+ -//| Generalized bell-shaped membership function | -//+------------------------------------------------------------------+ -class CGeneralizedBellShapedMembershipFunction : public IMembershipFunction - { -private: - double m_a; // Parametr a: the concentration factor of the membership function - double m_b; // Parametr b: coefficients slope of the membership function - double m_c; // Parametr c: the maximum coordinate of the membership function - -public: - CGeneralizedBellShapedMembershipFunction(void); - CGeneralizedBellShapedMembershipFunction(const double a,const double b,const double c); - ~CGeneralizedBellShapedMembershipFunction(void); - //--- methods gets or sets the parametrs - void A(const double a) { m_a=a; } - double A(void) { return(m_a); } - void B(const double b) { m_b=b; } - double B(void) { return(m_b); } - void C(const double c) { m_c=c; } - double C(void) { return(m_c); } - //--- method gets the argument (x axis value) - double GetValue(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CGeneralizedBellShapedMembershipFunction::CGeneralizedBellShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CGeneralizedBellShapedMembershipFunction::CGeneralizedBellShapedMembershipFunction(const double a,const double b,const double c) - { - m_a=a; - m_b=b; - m_c=c; - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -CGeneralizedBellShapedMembershipFunction::~CGeneralizedBellShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CGeneralizedBellShapedMembershipFunction::GetValue(const double x) - { -//--- return result - return (1 / (1 + pow( fabs((x - m_a) / m_c) , 2 * m_b ))); - } -//+------------------------------------------------------------------+ -//| S-shaped membership function | -//+------------------------------------------------------------------+ -class CS_ShapedMembershipFunction : public IMembershipFunction - { -private: - double m_a; // Parametr a: beginning of the interval increases - double m_b; // Parametr b: end of the interval increases - -public: - CS_ShapedMembershipFunction(void); - CS_ShapedMembershipFunction(const double a,const double b); - ~CS_ShapedMembershipFunction(void); - //--- methods gets or sets the parametrs - void A(const double a) { m_a=a; } - double A(void) { return(m_a); } - void B(const double b) { m_b=b; } - double B(void) { return(m_b); } - //--- method gets the argument (x axis value) - double GetValue(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CS_ShapedMembershipFunction::CS_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CS_ShapedMembershipFunction::CS_ShapedMembershipFunction(const double a,const double b) - { - m_a=a; - m_b=b; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CS_ShapedMembershipFunction::~CS_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CS_ShapedMembershipFunction::GetValue(const double x) - { - if(x<=m_a) - { - //--- return result - return (0.0); - } - else if(m_a= m_b - //--- return result - return (1.0); - } - } -//+------------------------------------------------------------------+ -//| Z-shaped membership function | -//+------------------------------------------------------------------+ -class CZ_ShapedMembershipFunction : public IMembershipFunction - { -private: - double m_a; // Parametr a: beginning of the interval decreasing - double m_b; // Parametr b: end of the interval decreasing - -public: - CZ_ShapedMembershipFunction(void); - CZ_ShapedMembershipFunction(const double a,const double b); - ~CZ_ShapedMembershipFunction(void); - //--- methods gets or sets the parametrs - void A(const double a) { m_a=a; } - double A(void) { return(m_a); } - void B(const double b) { m_b=b; } - double B(void) { return(m_b); } - //--- method gets the argument (x axis value) - double GetValue(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CZ_ShapedMembershipFunction::CZ_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CZ_ShapedMembershipFunction::CZ_ShapedMembershipFunction(const double a,const double b) - { - m_a=a; - m_b=b; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CZ_ShapedMembershipFunction::~CZ_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CZ_ShapedMembershipFunction::GetValue(const double x) - { - if(x<=m_a) - { - //--- return result - return (1.0); - } - else if(m_a= m_b - //--- return result - return (0.0); - } - } -//+------------------------------------------------------------------+ -//| P-shaped membership function | -//+------------------------------------------------------------------+ -class CP_ShapedMembershipFunction : public IMembershipFunction - { -private: - double m_a; // Parametr a: carrier fuzzy set - double m_d; // Parametr d: carrier fuzzy set - double m_b; // Parametr b: the core of a fuzzy set - double m_c; // Parametr c: the core of a fuzzy set - -public: - CP_ShapedMembershipFunction(void); - CP_ShapedMembershipFunction(const double a,const double b,const double c,const double d); - ~CP_ShapedMembershipFunction(void); - //--- methods gets or sets the parametrs - void A(const double a) { m_a=a; } - double A(void) { return(m_a); } - void D(const double d) { m_d=d; } - double D(void) { return(m_d); } - void B(const double b) { m_b=b; } - double B(void) { return(m_b); } - void C(const double c) { m_c=c; } - double C(void) { return(m_c); } - //--- method gets the argument (x axis value) - double GetValue(const double x); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CP_ShapedMembershipFunction::CP_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CP_ShapedMembershipFunction::CP_ShapedMembershipFunction(const double a,const double b,const double c,const double d) - { - m_a=a; - m_d=d; - m_b=b; - m_c=c; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CP_ShapedMembershipFunction::~CP_ShapedMembershipFunction(void) - { - - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CP_ShapedMembershipFunction::GetValue(const double x) - { - if(x<=m_a) - { - return(0.0); - } - else - if(m_a=m_x4) - { - result=0; - } - else if((x>=m_x2) && (x<=m_x3)) - { - result=1; - } - else if((x>m_x1) && (x=m_x3) - { - result=0; - } - else if(x==m_x2) - { - result=1; - } - else if((x>m_x1) && (x1.0) - { - Print("Incorrect parameter! It is necessary to re-initialize them."); - } - m_constValue=constValue; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CConstantMembershipFunction::~CConstantMembershipFunction(void) - { - - } -//+--------------------------------------------------------------------------------------+ -//| Composition of several membership functions represened as single membership function | -//+--------------------------------------------------------------------------------------+ -class CCompositeMembershipFunction : public IMembershipFunction - { -private: - CList *m_mfs; // List of membership functions - MfCompositionType m_composType; // Composite Type - -public: - CCompositeMembershipFunction(MfCompositionType composType); - CCompositeMembershipFunction(MfCompositionType composType,IMembershipFunction *mf1,IMembershipFunction *mf2); - CCompositeMembershipFunction(MfCompositionType composType,CList *mfs); - ~CCompositeMembershipFunction(void); - //--- methods gets or sets the parametrs - CList *MembershipFunctions(void) { return(m_mfs); } - MfCompositionType CompositionType(void) { return(m_composType); } - void CompositionType(MfCompositionType value) { m_composType=value; } - //--- method gets the argument (x axis value) - - //+------------------------------------------------------------------+ - //| Get argument (x axis value) | - //+------------------------------------------------------------------+ - double GetValue(double const x); -private: - //--- composition of the membership functions - double Compose(const double val1,const double val2); - }; -//+------------------------------------------------------------------+ -//| First constructor with parameters | -//+------------------------------------------------------------------+ -CCompositeMembershipFunction::CCompositeMembershipFunction(MfCompositionType composType) - { - m_mfs=new CList; - m_composType=composType; - } -//+------------------------------------------------------------------+ -//| Second constructor with parameters | -//+------------------------------------------------------------------+ -CCompositeMembershipFunction::CCompositeMembershipFunction(MfCompositionType composType,IMembershipFunction *mf1,IMembershipFunction *mf2) - { - m_mfs=new CList; - m_mfs.Add(mf1); - m_mfs.Add(mf2); - m_composType=composType; - } -//+------------------------------------------------------------------+ -//| Third constructor with parameters | -//+------------------------------------------------------------------+ -CCompositeMembershipFunction::CCompositeMembershipFunction(MfCompositionType composType,CList *mfs) - { - m_mfs=mfs; - m_composType=composType; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCompositeMembershipFunction::~CCompositeMembershipFunction() - { - m_mfs.FreeMode(false); - delete m_mfs; - } -//+------------------------------------------------------------------+ -//| Get argument (x axis value) | -//+------------------------------------------------------------------+ -double CCompositeMembershipFunction::GetValue(double const x) - { - if(m_mfs.Total()==0) - { - //--- return result - return 0.0; - } - else if(m_mfs.Total()==1) - { - IMembershipFunction *fun=m_mfs.GetNodeAtIndex(0); - //--- return result - return fun.GetValue(x); - } - else - { - IMembershipFunction *fun=m_mfs.GetNodeAtIndex(0); - double result=fun.GetValue(x); - for(int i=1; i -#include -#include "Dictionary.mqh" -#include "FuzzyRule.mqh" -#include "Helper.mqh" -#include "InferenceMethod.mqh" -#include "SugenoVariable.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Analysis of the fuzzy rules | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Base class for all expression | -//+------------------------------------------------------------------+ -class IExpression : public CObject - { -public: - //--- method gets the text of expression - virtual string Text(void)=NULL; - //--- method to check type - virtual bool IsTypeOf(EnLexem type) { return(type==TYPE_CLASS_IExpression); } - }; -//+------------------------------------------------------------------+ -//| Class for creating lexem | -//+------------------------------------------------------------------+ -class CLexem : public IExpression - { -public: - //--- method gets the text of expression - virtual string Text(void)=NULL; - //--- method to check type - virtual bool IsTypeOf(EnLexem type) { return(type==TYPE_CLASS_Lexem); } - }; -//+------------------------------------------------------------------+ -//| Class condition expression | -//+------------------------------------------------------------------+ -class CConditionExpression : public IExpression - { -private: - CArrayObj *m_expressions; // List of expression - CFuzzyCondition *m_condition; // Fuzzy condition - -public: - CConditionExpression(CArrayObj *expressions,CFuzzyCondition *condition); - ~CConditionExpression(void); - //--- methods gets or sets array of expression - CArrayObj *Expressions(void) { return (m_expressions); } - void Expressions(CArrayObj *value) { m_expressions=value; } - //--- methods gets or sets fuzzy condition - CFuzzyCondition *Condition(void) { return m_condition; } - void Condition(CFuzzyCondition *value) { m_condition=value; } - //--- method gets the text of expressions - string Text(void); - //--- method to check type - virtual bool IsTypeOf(EnLexem type) { return(type==TYPE_CLASS_ConditionExpression); } - }; -//+------------------------------------------------------------------+ -//| Constructor with parameters | -//+------------------------------------------------------------------+ -CConditionExpression::CConditionExpression(CArrayObj *expressions,CFuzzyCondition *condition) - { - m_expressions=expressions; - m_condition=condition; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CConditionExpression::~CConditionExpression(void) - { - - } -//+------------------------------------------------------------------+ -//| Convert all expressions to text(string) | -//+------------------------------------------------------------------+ -string CConditionExpression::Text(void) - { - string sb; - for(int i=0; i0 && StringGetCharacter(sb,StringLen(sb)-1)==' ') - { - //--- Do not duplicate spaces - } - else - { - sb+=CharToString(' '); - } - sb+=CharToString(ch); - sb+=CharToString(' '); - } - else - { - if(ch==' ' && StringLen(sb)>0 && StringGetCharacter(sb,StringLen(sb)-1)==' ') - { - // Do not duplicate spaces - } - else - { - sb+=CharToString(ch); - } - } - } -//--- Remove spaces -//+------------------------------------------------------------------+ -//| Use conditional compilation to determine | -//| the type of program MQL4 or MQL5 because they have | -//| different realization of StringTrimRight() and StringTrimLeft() | -//+------------------------------------------------------------------+ -#ifdef __MQL5__ - StringTrimRight(sb); - StringTrimLeft(sb); -#else -#ifdef __MQL4__ - sb=StringTrimRight(sb); - sb=StringTrimLeft(sb); -#endif -#endif - string prepRule=sb; -//--- Build lexems dictionary - CList *lexemsDict=BuildLexemsList(in,out); -//--- At first we parse lexems - CArrayObj *expressions=ParseLexems(prepRule,lexemsDict); - if(expressions.Total()==0) - { - Print("No valid identifiers found."); - //--- return - return (NULL); - } -//--- Find condition & conclusion parts part - CDictionary_String_Obj *p_so; - for(int i=0; i0) - { - IExpression *expr0=copyExpressions.At(index); - if(expr0.IsTypeOf(TYPE_CLASS_VarLexem)) - { - //--- Parse variable - CVarLexem *varLexem=copyExpressions.At(index); - if(copyExpressions.Total()<3) - { - Print(StringFormat("Condition strated with '%s' is incorrect.",varLexem.Text())); - //--- return - return(NULL); - } - if(varLexem.Input()==false) - { - Print("The variable in condition part must be an input variable."); - //--- return - return(NULL); - } - //--- Parse 'is' lexem - CLexem *exprIs=copyExpressions.At(index+1); - CDictionary_String_Obj *p_so; - for(int i=0;i0) - { - ICondition *cond=NULL; - for(int i=0; i0) - { - if((copyExpressions.At(index)==p_so_and.Value() && p_so_and.Key()=="and") || (copyExpressions.At(index)==p_so_or.Value() && p_so_or.Key()=="or")) - { - if(copyExpressions.Total()-index<2) - { - condExp=copyExpressions.At(index); - Print(StringFormat("Error at %s in condition part.",condExp.Text())); - //--- return - return (NULL); - } - //--- Set and/or for conditions list - OperatorType newOp=NULL; - if(copyExpressions.At(index)==p_so_and.Value() && p_so_and.Key()=="and") - { - newOp=And; - } - if(copyExpressions.At(index)==p_so_or.Value() && p_so_or.Key()=="or") - { - newOp=Or; - } - if(setOrAnd) - { - if(conds.Op()!=newOp) - { - Print("At the one nesting level cannot be mixed and/or operations."); - //--- return - return (NULL); - } - } - else - { - conds.Op(newOp); - setOrAnd=true; - } - index=index+1; - } - else - { - string str; - condExp=copyExpressions.At(index); - str=condExp.Text(); - condExp=copyExpressions.At(index+1); - Print(StringFormat("%s cannot goes after %s",str,condExp.Text())); - //--- return - return (NULL); - } - } - } - //--- return conditions - return (conds); - } - } -//+------------------------------------------------------------------+ -//| Parse conclusion | -//+------------------------------------------------------------------+ -static CSingleCondition *CRuleParser::ParseConclusion(CArrayObj *conditionExpression,CList *out,CList *lexems) - { - CArrayObj *copyExpression=conditionExpression; -//--- Remove extra brackets - CDictionary_String_Obj *p_so; - CDictionary_String_Obj *p_so_open; - CDictionary_String_Obj *p_so_close; - for(int i=0; i=2 && (copyExpression.At(index)==p_so_open.Value() && copyExpression.At(index+conditionExpression.Total()-1)==p_so_close.Value())) - { - index=index+1; - Total=Total-2; - } - if(Total!=3) - { - Print("Conclusion part of the rule should be in form: 'variable is term'"); - //--- return - return (NULL); - } -//--- Parse variable - CLexem *exprVariable=copyExpression.At(index); - if(!exprVariable.IsTypeOf(TYPE_CLASS_VarLexem)) - { - Print(StringFormat("Wrong identifier '%s' in conclusion part of the rule.",exprVariable.Text())); - //--- return - return (NULL); - } - CVarLexem *varLexem=exprVariable; - if(varLexem.Input()==true) - { - Print("The variable in conclusion part must be an output variable."); - //--- return - return (NULL); - } -//--- Parse 'is' lexem - CLexem *exprIs=copyExpression.At(index+1); - for(int i=0; i -#include "GenericFuzzySystem.mqh" -#include "InferenceMethod.mqh" -#include "RuleParser.mqh" -#include "FuzzyRule.mqh" -#include "SugenoVariable.mqh" -//+------------------------------------------------------------------+ -//| Purpose: Creating Sugeno fuzzy system | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Sugeno fuzzy inference system | -//+------------------------------------------------------------------+ -class CSugenoFuzzySystem : public CGenericFuzzySystem - { -private: - CList *m_output; // List of Sugeno variable - CList *m_rules; // List of Sugeno fuzzy rule - -public: - CSugenoFuzzySystem(void); - ~CSugenoFuzzySystem(void); - //--- method gets the output linguistic variables - CList *Output() { return(m_output); } - //--- method gets the fuzzy rule - CList *Rules() { return(m_rules); } - //--- maethod gets the variable by name - CSugenoVariable *OutputByName(const string name); - //--- method create new linear function - CLinearSugenoFunction *CreateSugenoFunction(const string name,CList *coeffs,const double constValue); - CLinearSugenoFunction *CreateSugenoFunction(const string name,const double &coeffs[]); - //--- method create a new rule - CSugenoFuzzyRule *EmptyRule(); - //--- method for calculate result - CSugenoFuzzyRule *ParseRule(const string rule); - CList *EvaluateConditions(CList *fuzzifiedInput); - CList *EvaluateFunctions(CList *inputValues); - CList *CombineResult(CList *ruleWeights,CList *functionResults); - CList *Calculate(CList *inputValues); - }; -//+------------------------------------------------------------------+ -//| Constructor without parameters | -//+------------------------------------------------------------------+ -CSugenoFuzzySystem::CSugenoFuzzySystem(void) - { - m_output=new CList; - m_rules=new CList; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSugenoFuzzySystem::~CSugenoFuzzySystem(void) - { - delete m_output; - delete m_rules; - } -//+------------------------------------------------------------------+ -//| Get the output variable of the system by name | -//+------------------------------------------------------------------+ -CSugenoVariable *CSugenoFuzzySystem::OutputByName(const string name) - { - for(int i=0; i -#include "FuzzyVariable.mqh" -#include "Dictionary.mqh" -//+------------------------------------------------------------------+ -//| Purpose: creating Sugeno variable. | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| The base class for Linear Sugeno Function | -//+------------------------------------------------------------------+ -class ISugenoFunction : public CNamedValueImpl - { -public: - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_ISugenoFunction); } - }; -//+------------------------------------------------------------------+ -//| Lenear function for Sugeno Fuzzy System | -//+------------------------------------------------------------------+ -class CLinearSugenoFunction : public ISugenoFunction - { -private: - CList *m_input; // List of input variables - CList *m_coeffs; // The dictionary which stores variables and their coefficients - double m_const_value; // The constant term of the linear equation - -public: - CLinearSugenoFunction(const string name,CList *in); - CLinearSugenoFunction(const string name,CList *in,CList *coeffs,const double constValue); - CLinearSugenoFunction(const string name,CList *in,const double &coeffs[]); - ~CLinearSugenoFunction(void); - //--- method to check type - virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_LinearSugenoFunction); } - //--- methods gets or sets constant coefficient - double ConstValue() { return(m_const_value); } - void ConstValue(const double value) { m_const_value=value; } - //--- methods gets or sets coefficient by fuzzy variable - double GetCoefficient(CFuzzyVariable *var); - void SetCoefficient(CFuzzyVariable *var,const double coeff); - //--- calculate - double Evaluate(CList *inputValues); - }; -//+------------------------------------------------------------------+ -//| First constructor with parameters | -//+------------------------------------------------------------------+ -CLinearSugenoFunction::CLinearSugenoFunction(const string name,CList *in) - { - m_coeffs=new CList; - CNamedValueImpl::Name(name); - m_input=in; - } -//+------------------------------------------------------------------+ -//| Second constructor with parameters | -//+------------------------------------------------------------------+ -CLinearSugenoFunction::CLinearSugenoFunction(const string name,CList *in,CList *coeffs,const double constValue) - { - CNamedValueImpl::Name(name); - m_input=in; -//--- Check that all coeffecients are related to the variable from input - for(int i=0; i0) | -//| b : Second shape parameter (b>0) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityBeta(const double x,const double a,const double b,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x range - if(x<=0.0 || x>=1.0) - return TailLog0(true,log_mode); - - double log_result=(a-1.0)*MathLog(x)+(b-1.0)*MathLog(1.0-x)-MathBetaLog(a,b); -//--- return log beta density - if(log_mode==true) - return log_result; -//--- return beta density - return MathExp(log_result); - } -//+------------------------------------------------------------------+ -//| Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of | -//| the Beta distribution with shape parameters a and b. | -//| | -//| f(x,a,b)= (1/Beta(a,b))*x^(a-1)*(1-x)^(b-1) | -//| Arguments: | -//| x : Random variable | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityBeta(const double x,const double a,const double b,int &error_code) - { - return MathProbabilityDensityBeta(x,a,b,false,error_code); - } -//+------------------------------------------------------------------+ -//| Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of the | -//| Beta distribution with shape parameters a and b for values in | -//| x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityBeta(const double &x[],const double a,const double b,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i=1.0) - result[i]=TailLog0(true,log_mode); - else - { - double log_result=(a-1.0)*MathLog(x_arg)+(b-1.0)*MathLog(1.0-x_arg)-MathBetaLog(a,b); - if(log_mode==true) - result[i]=log_result; - else - result[i]=MathExp(log_result); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of the | -//| Beta distribution with shape parameters a and b for values in | -//| x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityBeta(const double &x[],const double a,const double b,double &result[]) - { - return MathProbabilityDensityBeta(x,a,b,false,result); - } -//+------------------------------------------------------------------+ -//| Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Beta distribution with shape parameters a and b, evaluated | -//| at x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Beta cumulative distribution function with | -//| shape parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionBeta(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x range - if(x<=0.0) - return TailLog0(tail,log_mode); - if(x>=1.0) - return TailLog1(tail,log_mode); -//--- calculate probability and take into account round-off errors - double cdf=MathMin(MathBetaIncomplete(x,a,b),1.0); -//--- return result depending on arguments - return TailLogValue(cdf,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Beta distribution with shape parameters a and b, evaluated | -//| at x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Beta cumulative distribution function with | -//| shape parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionBeta(const double x,const double a,const double b,int &error_code) - { - return MathCumulativeDistributionBeta(x,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| The Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Beta distribution with shape parameters a and b for values | -//| in x[] array | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionBeta(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i=1.0) - result[i]=TailLog1(tail,log_mode); - else - { - //--- calculate probability and take into account round-off errors - double cdf=MathMin(MathBetaIncomplete(x_arg,a,b),1.0); - //--- return result depending on arguments - result[i]=TailLogValue(cdf,tail,log_mode); - } - } - else - return false; - } - return(true); - } -//+------------------------------------------------------------------+ -//| Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Beta distribution with shape parameters a and b for values | -//| in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionBeta(const double &x[],const double a,const double b,double &result[]) - { - return MathCumulativeDistributionBeta(x,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Beta distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Beta distribution with shape parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function of | -//| the Beta distribution with shape parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileBeta(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check probabilty - if(prob==0.0) - return 0.0; - if(prob==1.0) - return 1.0; - - const double eps=10e-16; -//--- set h and h_min - double h=1.0; - double h_min=MathSqrt(eps); - -//--- initial x value - double x=a/(a+b); - if(x==0.0) - x=h_min; - else - if(x==1.0) - x=1.0-h_min; - - int err_code=0; - const int max_iterations=100; - int iterations=0; -//--- Newton iterations - while(iterationsh_min*MathAbs(x)) && (MathAbs(h)>h_min))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityBeta(x,a,b,false,err_code); - double cdf=MathCumulativeDistributionBeta(x,a,b,true,false,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - x=x_new; - - iterations++; - } -//--- check convergence - if(iterations0) | -//| b : Second shape parameter (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Beta distribution with shape parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileBeta(const double probability,const double a,const double b,int &error_code) - { - return MathQuantileBeta(probability,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Beta distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the the inverse cumulative distribution | -//| function of the Beta distribution with shape parameters a and b | -//| for the probability values from probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probability values | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| tail : Lower tail flag (lower tail of probability used) | -//| log_mode : Logarithm mode flag (log probability used) | -//| result : Output array with quantile values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileBeta(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - - const double eps=10e-16; - double h_min=MathSqrt(eps); - - int err_code=0; - const int max_iterations=1000; - for(int i=0; i1.0) - return false; - //--- check probabilty - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=1.0; - else - { - //--- initial x value - double x=a/(a+b); - if(x==0.0) - x=h_min; - else - if(x==1.0) - x=1.0-h_min; - - double h=1.0; - int iterations=0; - //--- Newton iterations - while(iterationsh_min*MathAbs(x)) && (MathAbs(h)>h_min))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityBeta(x,a,b,false,err_code); - double cdf=MathCumulativeDistributionBeta(x,a,b,true,false,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - x=x_new; - - iterations++; - } - //--- check convergence - if(iterations0) | -//| b : Second shape parameter (b>0) | -//| result : Output array with quantile values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileBeta(const double &probability[],const double a,const double b,double &result[]) - { - return MathQuantileBeta(probability,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Beta distribution | -//+------------------------------------------------------------------+ -//| The function returns a single random deviate from the Beta | -//| distribution with parameters a and b. | -//| | -//| Arguments: | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| | -//| Return value: | -//| The random value with Beta distribution. | -//| | -//| Reference: | -//| Russell Cheng, | -//| "Generating Beta Variates with Nonintegral Shape Parameters", | -//| Communications of the ACM, | -//| Volume 21, Number 4, April 1978, pages 317-322. | -//| | -//| Original FORTRAN77 version by Barry Brown, James Lovato. | -//| C version by John Burkardt. | -//+------------------------------------------------------------------+ -double MathRandomBeta(const double a,const double b) - { - const double log4 = MathLog(4); - const double log5 = MathLog(5); - double a1,b1,alpha,beta,gamma,delta,r,s,u1,u2,v,y,z; - double w=0.0; - double value=0; -//--- - if(1.00) | -//| b : Second shape parameter (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Beta distribution. | -//+------------------------------------------------------------------+ -double MathRandomBeta(const double a,const double b,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- return beta random value - return MathRandomBeta(a,b); - } -//+------------------------------------------------------------------+ -//| Random variate from Beta distribution | -//+------------------------------------------------------------------+ -//| The function generates random variables from Beta distribution | -//| with parameters a and b. | -//| | -//| Arguments: | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomBeta(const double a,const double b,const int data_count,double &result[]) - { - if(data_count<=0) - return false; -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - return false; - -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i0) | -//| b : Second shape parameter (b>0) | -//| mean : Variable for mean value (1st moment) | -//| variance : Variable for variance value (2nd moment) | -//| skewness : Variable for skewness value (3rd moment) | -//| kurtosis : Variable for kurtosis value (4th moment) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if moments calculated successfully, otherwise false. | -//+------------------------------------------------------------------+ -bool MathMomentsBeta(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) - { -//--- initial values - mean =QNaN; - variance=QNaN; - skewness=QNaN; - kurtosis=QNaN; -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return false; - } -//--- a and b must be positive - if(a<=0.0 || b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- calculate moments - mean =a/(a+b); - variance=(a*b)/((a+b)*(a+b)*(a+b+1)); - skewness=2*(b-a)*MathSqrt(a+b+1)/(MathSqrt(a*b)*(a+b+2)); - kurtosis=6*(a*a*a+a*a*(1-2*b)+b*b*(1+b)-2*a*b*(2+b))/(a*b*(a+b+2)*(a+b+3)); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Binomial.mqh b/Include/Math/Stat/Binomial.mqh deleted file mode 100644 index a47b736..0000000 --- a/Include/Math/Stat/Binomial.mqh +++ /dev/null @@ -1,874 +0,0 @@ -//+------------------------------------------------------------------+ -//| Binomial.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "Beta.mqh" - -//+------------------------------------------------------------------+ -//| Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the Binomial probability mass function | -//| with parameters n and p at x. | -//| | -//| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) | -//| | -//| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) | -//| | -//| Arguments: | -//| x : Integer random variable | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass function evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityBinomial(const double x,const double n,const double p,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check n - if(n<0 || n!=MathRound(n)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check p range - if(p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- case p=0 - if(p==0.0 || p==1.0) - return TailLog0(true,log_mode); -//--- check x range - if(x<0 || x>n) - return TailLog0(true,log_mode); - - double log_result=MathGammaLog(n+1.0)-MathGammaLog(x+1.0)-MathGammaLog(n-x+1.0)+x*MathLog(p)+(n-x)*MathLog(1.0-p); - if(log_mode==true) - return log_result; -//--- return probability mass - return MathExp(log_result); - } -//+------------------------------------------------------------------+ -//| Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the Binomial probability mass function | -//| with parameters n and p at x. | -//| | -//| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) | -//| | -//| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) | -//| | -//| Arguments: | -//| x : Integer random variable | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass function evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityBinomial(const double x,const double n,const double p,int &error_code) - { - return MathProbabilityDensityBinomial(x,n,p,false,error_code); - } -//+------------------------------------------------------------------+ -//| Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the Binomial probability mass function | -//| with parameters n and p for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with integer random variables | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) - return false; -//--- check n - if(n<0 || n!=MathRound(n)) - return false; -//--- check p range - if(p<0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); -//--- case p=0 or p=1 - if(p==0.0 || p==1.0) - { - for(int i=0; in) - result[i]=TailLog0(true,log_mode); - else - { - double log_result=MathGammaLog(n+1.0)-MathGammaLog(x_arg+1.0)-MathGammaLog(n-x_arg+1.0)+x_arg*MathLog(p)+(n-x_arg)*MathLog(1.0-p); - if(log_mode==true) - result[i]=log_result; - else - result[i]=MathExp(log_result); - } - } - else - return false; - } - return true; - } -//+------------------------------------------------------------------+ -//| Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the Binomial probability mass function | -//| with parameters n and p for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with integer random variables | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,double &result[]) - { - return MathProbabilityDensityBinomial(x,n,p,false,result); - } -//+------------------------------------------------------------------+ -//| Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the value of the Binomial cumulative | -//| distribution function with given n and p at the desired x. | -//| | -//| Arguments: | -//| x : Integer random variable | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The cumulative distribution function evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionBinomial(const double x,const double n,double p,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check n - if(n<0 || n!=MathRound(n)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check probability - if(p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- case p==0 - if(p==0.0) - { - if(x>=0) - return TailLog1(tail,log_mode); - else - return TailLog0(tail,log_mode); - } -//--- case p==1 - if(p==1.0) - { - if(x>n) - return TailLog1(tail,log_mode); - else - return TailLog0(tail,log_mode); - } -//--- x must be>=0 - if(x<0) - return TailLog0(tail,log_mode); -//--- check x - if(x>n) - return TailLog1(tail,log_mode); - int err_code=0; -//--- calculate using Beta distribution and correct round-off errors - double result=MathMin(1.0-MathCumulativeDistributionBeta(p,x+1.0,n-x,err_code),1.0); -//--- return result depending on arguments - return TailLogValue(result,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the value of the Binomial cumulative | -//| distribution function with given n and p at the desired x. | -//| | -//| Arguments: | -//| x : Integer random variable | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The cumulative distribution function evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionBinomial(const double x,const double n,double p,int &error_code) - { - return MathCumulativeDistributionBinomial(x,n,p,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the value of the Binomial cumulative | -//| distribution function with given n and p at the desired x. | -//| | -//| Arguments: | -//| x : Array with integer random variables | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) - return false; -//--- check n - if(n<0 || n!=MathRound(n)) - return false; -//--- check probability - if(p<0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - -//--- case p=0 and p==1 - if(p==0.0 || p==1.0) - { - if(p==0.0) - { - for(int i=0; i=0) - result[i]=TailLog1(tail,log_mode); - else - result[i]=TailLog0(tail,log_mode); - } - } - else - //--- p==1.0 - { - for(int i=0; in) - result[i]=TailLog1(tail,log_mode); - else - result[i]=TailLog0(tail,log_mode); - } - } - return true; - } - - int err_code=0; - for(int i=0; in) - result[i]=TailLog1(tail,log_mode); - else - { - double value=MathMin(1.0-MathCumulativeDistributionBeta(p,x_arg+1.0,n-x_arg,err_code),1.0); - //--- calculate result depending on arguments - result[i]=TailLogValue(value,tail,log_mode); - } - } - else - return false; - } - return true; - } -//+------------------------------------------------------------------+ -//| Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the value of the Binomial cumulative | -//| distribution function with given n and p for values | -//| from x[] array. | -//| | -//| Arguments: | -//| x : Array with integer random variables | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,double &result[]) - { - return MathCumulativeDistributionBinomial(x,n,p,true,false,result); - } -//+------------------------------------------------------------------+ -//| Binomial distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the value of the inverse Binomial cumulative| -//| distribution function with parameters n and p for the desired | -//| probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| tail : Lower tail flag (lower tail of probability used) | -//| log_mode : Logarithm mode flag (log probability used) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Binomial distribution with parameters n and p. | -//+------------------------------------------------------------------+ -double MathQuantileBinomial(const double probability,const double n,const double p,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check n - if(n<0 || n!=MathRound(n)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check p range - if(p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - int iterations=0; - const int max_iterations=1000; -//--- direct cdf calculation - double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code); - while(sum1.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - - const int max_iterations=1000; - for(int i=0; i1.0) - return false; - - int iterations=0; - //--- direct cdf calculation - double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code); - while(sum=1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- return binomial random value - return MathRandomBinomial(n,p); - } -//+------------------------------------------------------------------+ -//| Random variate from Binomial distribution | -//+------------------------------------------------------------------+ -//| The function generates random variables from Binomial | -//| distribution with parameters n and p. | -//| | -//| Arguments: | -//| n : Number of trials | -//| p : Probability of success for each trial | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomBinomial(const double n,const double p,const int data_count,double &result[]) - { - if(data_count<=0) - return false; -//--- check NaN - if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) - return false; -//--- check n - if(n<=0 || n!=MathRound(n)) - return false; -//--- check probability - if(p<=0 || p>=1.0) - return false; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i=1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- prepare factors - double np=n*p; - double one_mp=(1.0-p); -//--- calculate moments - mean =np; - variance=np*one_mp; - skewness=(1-2*p)/MathSqrt(variance); - kurtosis=(1-6*p*one_mp)/variance; -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Cauchy.mqh b/Include/Math/Stat/Cauchy.mqh deleted file mode 100644 index 614a105..0000000 --- a/Include/Math/Stat/Cauchy.mqh +++ /dev/null @@ -1,539 +0,0 @@ -//+------------------------------------------------------------------+ -//| Cauchy.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" - -//+------------------------------------------------------------------+ -//| Cauchy density function (PDF) | -//+------------------------------------------------------------------+ -//| Computes the value of the Cauchy probability density function | -//| with parameters a and b at the desired quantile x. | -//| | -//| f(x,a,b)= 1/(pi*b*(1.0+((x-a)/b)^2) | -//| Arguments: | -//| x : Random variable | -//| a : Mean | -//| b : Scale | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityCauchy(const double x,const double a,const double b,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check scale - if(b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- prepare argument - double y=(x-a)/b; -//--- check result - if(!MathIsValidNumber(y)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(log_mode==true) - return -MathLog(M_PI*b*(1.0+y*y)); -//--- return Cauchy density - return 1.0/(M_PI*b*(1.0+y*y)); - } -//+------------------------------------------------------------------+ -//| Cauchy density function (PDF) | -//+------------------------------------------------------------------+ -//| Computes the value of the Cauchy probability density function | -//| with parameters a and b at the desired quantile x. | -//| | -//| f(x,a,b)= 1/(pi*b*(1.0+((x-a)/b)^2) | -//| Arguments: | -//| x : Random variable | -//| a : Mean | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityCauchy(const double x,const double a,const double b,int &error_code) - { - return MathProbabilityDensityCauchy(x,a,b,false,error_code); - } -//+------------------------------------------------------------------+ -//| Cauchy density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| Cauchy distribution with parameters a and b for values | -//| from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Mean | -//| b : Scale | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityCauchy(const double &x[],const double a,const double b,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check scale - if(b<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i-1.0) - cdf=MathMin(0.5+M_1_PI*MathArctan(y),1.0); - else - cdf=MathMin(M_1_PI*MathArctan(-1/y),1.0); - - return TailLogValue(cdf,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Cauchy cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Cauchy distribution with parameters a and b, evaluated at x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Mean | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| The value of the Cauchy cumulative distribution function with | -//| parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionCauchy(const double x,const double a,const double b,int &error_code) - { - return MathCumulativeDistributionCauchy(x,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Cauchy cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Cauchy distribution with parameters a and b for values from | -//| x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Mean | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionCauchy(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check scale - if(b<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i-1.0) - cdf=MathMin(0.5+M_1_PI*MathArctan(y),1.0); - else - cdf=MathMin(M_1_PI*MathArctan(-1/y),1.0); - - result[i]=TailLogValue(cdf,tail,log_mode); - } - - return true; - } -//+------------------------------------------------------------------+ -//| Cauchy cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function | -//| of the Cauchy distribution with parameters a and b for values | -//| from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Mean | -//| b : Scale | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionCauchy(const double &x[],const double a,const double b,double &result[]) - { - return MathCumulativeDistributionCauchy(x,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Cauchy distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Cauchy distribution with parameters a and b | -//| for the desired probability. | -//| Q(p,a,b)=a+b*tan*(pi*(p-1/2)) | -//| Arguments: | -//| probability : The desired probability | -//| a : Mean | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Cauchy distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileCauchy(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check scale - if(b<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- f(1)= + infinity - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } -//--- f(0)= - infinity - if(prob==0.0) - { - error_code=ERR_RESULT_INFINITE; - return QNEGINF; - } - error_code=ERR_OK; -//--- return quantile - return a+b*MathTan(M_PI*(prob-0.5)); - } -//+------------------------------------------------------------------+ -//| Cauchy distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Cauchy distribution with parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Mean | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Cauchy distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileCauchy(const double probability,const double a,const double b,int &error_code) - { - return MathQuantileCauchy(probability,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Cauchy distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Cauchy distribution with parameters a and b | -//| for the probability values from array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Mean | -//| b : Scale | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileCauchy(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check scale - if(b<=0.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- f(1)= + infinity - if(prob==1.0) - result[i]=QPOSINF; - else - //--- f(0)= - infinity - if(prob==0.0) - result[i]=QNEGINF; - else - result[i]=a+b*MathTan(M_PI*(prob-0.5)); - } - return true; - } -//+------------------------------------------------------------------+ -//| Cauchy distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -bool MathQuantileCauchy(const double &probability[],const double a,const double b,double &result[]) - { - return MathQuantileCauchy(probability,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Cauchy distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Cauchy distribution | -//| with parameters a and b. | -//| | -//| Arguments: | -//| a : Mean | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Cauchy distribution. | -//+------------------------------------------------------------------+ -double MathRandomCauchy(const double a,const double b,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check scale - if(b<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check scale=0 - if(b==0.0) - return a; -//--- generate random number - double rnd=MathRandomNonZero(); -//--- return result - return a+b*MathTan(M_PI*(rnd-0.5)); - } -//+------------------------------------------------------------------+ -//| Random variate from the Cauchy distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Cauchy distribution with | -//| parameters a and b. | -//| | -//| Arguments: | -//| a : Mean | -//| b : Scale | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomCauchy(const double a,const double b,const int data_count,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check scale - if(b<0) - return false; - -//--- prepare output array - ArrayResize(result,data_count); - -//--- check scale=0 - if(b==0.0) - { - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(prob==0.0) - return 0.0; - - if(prob==1.0) - return QPOSINF; - -//---- calculate quantile using Gamma distribution - return MathQuantileGamma(prob,nu*0.5,2.0,error_code); - } -//+------------------------------------------------------------------+ -//| Chi-Square distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Chi-Square distribution with parameter nu | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| nu : Degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Chi-Square distribution with parameter nu. | -//+------------------------------------------------------------------+ -double MathQuantileChiSquare(const double probability,const double nu,int &error_code) - { - return MathQuantileChiSquare(probability,nu,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Chi-Square distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Chi-Square distribution with parameter nu | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| nu : Degrees of freedom | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileChiSquare(const double &probability[],const double nu,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu)) - return false; -//--- nu must be positive - if(nu<=0) - return false; -//--- nu must be integer - if(nu!=MathRound(nu)) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=QPOSINF; - else - { - //--- calculate using Gamma distribution - result[i]=MathQuantileGamma(prob,nu*0.5,2.0,error_code); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Chi-Square distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Chi-Square distribution with parameter nu | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| nu : Degrees of freedom | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileChiSquare(const double &probability[],const double nu,double &result[]) - { - return MathQuantileChiSquare(probability,nu,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Chi-Square distribution | -//+------------------------------------------------------------------+ -//| Computes the random variable from the Chi-Square distribution | -//| with parameter nu. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Chi-Square distribution. | -//+------------------------------------------------------------------+ -double MathRandomChiSquare(const double nu,int &error_code) - { -//--- NaN - if(!MathIsValidNumber(nu)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- nu must be integer - if(nu!=MathRound(nu)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- nu must be positive - if(nu<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- return gamma(nu/2,2) - return MathRandomGamma(nu*0.5,2.0,error_code); - } -//+------------------------------------------------------------------+ -//| Random variate from Chi-Square distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Chi-Square distribution | -//| with parameter nu. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomChiSquare(const double nu,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu)) - return false; -//--- nu must be integer - if(nu!=MathRound(nu)) - return false; -//--- nu must be positive - if(nu<=0) - return false; - int error_code=0; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check zero probability case - if(prob==0.0) - return 0.0; - else - if(prob==1.0) - return QPOSINF; -//--- return quantile - return -mu*MathLog(1.0-prob); - } -//+------------------------------------------------------------------+ -//| Exponential distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of Exponential distribution with parameter mu | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| mu : Mean | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Exponential distribution with parameter mu. | -//+------------------------------------------------------------------+ -double MathQuantileExponential(const double probability,const double mu,int &error_code) - { - return MathQuantileExponential(probability,mu,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Exponential distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Exponential distribution with parameter mu | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileExponential(const double &probability[],const double mu,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(mu)) - return false; -//--- mu must be positive - if(mu<=0.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- check zero probability case - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=QPOSINF; - else - result[i]=-mu*MathLog(1.0-prob); - } - return true; - } -//+------------------------------------------------------------------+ -//| Exponential distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Exponential distribution with parameter mu | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileExponential(const double &probability[],const double mu,double &result[]) - { - return MathQuantileExponential(probability,mu,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Exponential distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Exponential distribution | -//| with parameter mu using simple inversion method. | -//| | -//| Arguments: | -//| mu : Mean | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Exponential distribution. | -//| | -//| Reference: | -//| Devroye L. "Non-uniform random variate generation",Springer,1986.| -//+------------------------------------------------------------------+ -double MathRandomExponential(const double mu,int &error_code) - { -//--- check mu - if(!MathIsValidNumber(mu)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- mu must be positive - if(mu<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- generate random number - double rnd=MathRandomNonZero(); -//--- return variate using quantile - return -mu*MathLog(1.0-rnd); - } -//+------------------------------------------------------------------+ -//| Random variate from the Exponential distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Exponential distribution | -//| with parameter mu. | -//| | -//| Arguments: | -//| mu : Mean | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomExponential(const double mu,const int data_count,double &result[]) - { -//--- check mu - if(!MathIsValidNumber(mu)) - return false; -//--- mu must be positive - if(mu<=0.0) - return false; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check case probability==1 - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - - error_code=ERR_OK; - if(prob==0.0) - return 0.0; -//--- calculate quantile using Beta distribution - double qBeta=MathQuantileBeta(1.0-prob,nu2*0.5,nu1*0.5,error_code); -//--- return quantile; - return (nu2/qBeta-nu2)/nu1; - } -//+------------------------------------------------------------------+ -//| F-distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of F-distribution with parameters nu1 and nu2 | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| nu1 : Numerator degrees of freedom | -//| nu2 : Denominator degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of F-distribution with parameters nu1 and nu2. | -//+------------------------------------------------------------------+ -double MathQuantileF(const double probability,const double nu1,const double nu2,int &error_code) - { - return MathQuantileF(probability,nu1,nu2,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| F-distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the F distribution with parameters nu1 and nu2 | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| nu1 : Numerator degrees of freedom | -//| nu2 : Denominator degrees of freedom | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileF(const double &probability[],const double nu1,const double nu2,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2)) - return false; -//--- check arguments - if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- check case probability==1,0 - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=QPOSINF; - else - { - //--- calculate quantile using Beta distribution - double qBeta=MathQuantileBeta(1.0-prob,nu2*0.5,nu1*0.5,error_code); - result[i]=(nu2/qBeta-nu2)/nu1; - } - } - return true; - } -//+------------------------------------------------------------------+ -//| F-distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the F distribution with parameters nu1 and nu2 | -//| for values from probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| nu1 : Numerator degrees of freedom | -//| nu2 : Denominator degrees of freedom | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileF(const double &probability[],const double nu1,const double nu2,double &result[]) - { - return MathQuantileF(probability,nu1,nu2,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the F-distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from F-distribution | -//| with parameters nu1 and nu2. | -//| | -//| Arguments: | -//| nu1 : Numerator degrees of freedom | -//| nu2 : Denominator degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with F-distribution. | -//+------------------------------------------------------------------+ -double MathRandomF(const double nu1,const double nu2,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check arguments - if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- random F=ChiSquare(nu1)*nu2/ChiSquare(nu2)*nu1; - double xnum = MathRandomGamma(nu1*0.5,1.0,error_code)*nu2; - double xden = MathRandomGamma(nu2*0.5,1.0,error_code)*nu1; -//--- - double value=0.0; - if(xden!=0) - value= xnum/xden; - else - { - error_code=ERR_NON_CONVERGENCE; - value=QNaN; - } -//--- return random F - return value; - } -//+------------------------------------------------------------------+ -//| Random variate from the F distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the F distribution with | -//| parameters nu1 and nu2. | -//| | -//| Arguments: | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomF(const double nu1,const double nu2,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2)) - return false; -//--- check arguments - if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0) - return false; - -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i2) - mean=nu2/(nu2-2); - if(nu2>4) - variance=2*nu2*nu2*(nu1+nu2-2)/(nu1*(nu2-2)*(nu2-2)*(nu2-4)); - if(nu2>6) - skewness=2*MathSqrt(2)*MathSqrt(nu2-4)*(2*nu1+nu2-2)/(MathSqrt(nu1*(nu1+nu2-2))*(nu2-6)); - if(nu2>8) - kurtosis=12*(nu1*(5*nu2-22)*(nu1+nu2-2)+(nu2-4)*(nu2-2)*(nu2-2))/(nu1*(nu2-8)*(nu2-6)*(nu1+nu2-2)); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Gamma.mqh b/Include/Math/Stat/Gamma.mqh deleted file mode 100644 index 572ca44..0000000 --- a/Include/Math/Stat/Gamma.mqh +++ /dev/null @@ -1,764 +0,0 @@ -//+------------------------------------------------------------------+ -//| Gamma.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Normal.mqh" - -const double DoubleEpsilon=1.11022302462515654042E-16; -const double LogMax=7.09782712893383996732E2; -//+------------------------------------------------------------------+ -//| Inverse of the incomplete Gamma integral | -//+------------------------------------------------------------------+ -double MathInverseGammaIncomplete(const double a,const double y) - { -//--- bound the solution - double x0 = DBL_MAX; - double yl = 0; - double x1 = 0; - double yh = 1.0; - double dithresh=5.0*DoubleEpsilon; -//--- approximation to inverse function - double d=1.0/(9.0*a); - int err_code=0; - double q_normal=MathQuantileNormal(y,0,1,true,false,err_code); - double yy=(1.0-d-q_normal*MathSqrt(d)); - double x=a*yy*yy*yy; - double lgm=MathGammaLog(a); - for(int i=0; i<10; i++) - { - if(x>x0 || xyh) - break; - if(yy=y) - { - x1 = x; - yh = yy; - if(dir<0) - { - dir=0; - d=0.5; - } - else - if(dir>1) - d=0.5*d+0.5; - else - d=(y-yl)/(yh-yl); - dir+=1; - } - else - { - x0 = x; - yl = yy; - if(dir>0) - { - dir=0; - d=0.5; - } - else - if(dir<-1) - d=0.5*d; - else - d=(y-yl)/(yh-yl); - dir-=1; - } - } - if(x==0.0 || !MathIsValidNumber(x)) - { - Print("Errors in an arithmetic, casting, or conversion operation."); - return(QNaN); - } -//--- - return(x); - } -//+------------------------------------------------------------------+ -//| Gamma probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of | -//| of the Gamma distribution with shape parameters a and b. | -//| | -//| Arguments: | -//| x : Random variable | -//| a : Shape | -//| b : Scale | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityGamma(const double x,const double a,const double b,const bool log_mode,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - error_code=ERR_OK; -//--- check negative x - if(x<=0) - return TailLog0(true,log_mode); -//--- calculate log Gamma density - double log_result=(a-1.0)*MathLog(x)-(x/b)-MathGammaLog(a)-a*MathLog(b); - if(log_mode==true) - return(log_result); -//--- return Gamma density - return MathExp(log_result); - } -//+------------------------------------------------------------------+ -//| Gamma probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of | -//| of the Gamma distribution with shape parameters a and b. | -//| | -//| Arguments: | -//| x : Random variable | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityGamma(const double x,const double a,const double b,int &error_code) - { - return MathProbabilityDensityGamma(x,a,b,false,error_code); - } -//+------------------------------------------------------------------+ -//| Gamma probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the Gamma probability density function | -//| with parameters a and b for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Shape | -//| b : Scale | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| result : Output array for calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityGamma(const double &x[],const double a,const double b,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0) - { - //--- calculate log Gamma density - double log_result=(a-1.0)*MathLog(x_arg)-(x_arg/b)-MathGammaLog(a)-a*MathLog(b); - if(log_mode==true) - result[i]=log_result; - else - result[i]=MathExp(log_result); - } - else - result[i]=TailLog0(true,log_mode); - } - return true; - } -//+------------------------------------------------------------------+ -//| Gamma probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the Gamma probability density function | -//| with parameters a and b for values from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Shape | -//| b : Scale | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityGamma(const double &x[],const double a,const double b,double &result[]) - { - return MathProbabilityDensityGamma(x,a,b,false,result); - } -//+------------------------------------------------------------------+ -//| Gamma cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of the | -//| Gamma distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Shape | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Gamma cumulative distribution function | -//| with parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionGamma(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x - if(x<=0) - return TailLog0(tail,log_mode); -//--- calculate probability using Incomplete Gamma function and take into account round-off errors - double cdf=MathMin(MathGammaIncomplete(x/b,a),1.0); - return TailLogValue(cdf,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Gamma cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of the | -//| Gamma distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Gamma cumulative distribution function | -//| with parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionGamma(const double x,const double a,const double b,int &error_code) - { - return MathCumulativeDistributionGamma(x,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Gamma cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the values of the Gamma cumulative | -//| distribution function with given a and b for values in x[] array.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Shape | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| resut : Output array for calculated values | -//| | -//| Return value: | -//| true if successul, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionGamma(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - error_code=ERR_OK; -//--- case probability==0 - if(prob==0.0) - return 0.0; -//--- case probability==1 - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } -//--- calculate quantile - double quantile=MathInverseGammaIncomplete(a,1.0-prob)*b; - if(!MathIsValidNumber(quantile)) - error_code=ERR_NON_CONVERGENCE; -//--- - return(quantile); - } -//+------------------------------------------------------------------+ -//| Gamma distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Gamma distribution with parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Gamma distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileGamma(const double probability,const double a,const double b,int &error_code) - { - return MathQuantileGamma(probability,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Gamma distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Gamma distribution with parameters a and b | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Shape | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| result : Output array for calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileGamma(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - - const double eps=10E-18; - double max_h=MathSqrt(eps); - const int max_iterations=1000; - - for(int i=0; i1.0) - return false; - - //--- case probability==0 - if(prob==0.0) - result[i]=0.0; - else - //--- case probability==1 - if(prob==1.0) - result[i]=QPOSINF; - else - { - double quantile=MathInverseGammaIncomplete(a,1.0-prob)*b; - if(MathIsValidNumber(quantile)) - result[i]=quantile; - else - return false; - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Gamma distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Gamma distribution with parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileGamma(const double &probability[],const double a,const double b,double &result[]) - { - return MathQuantileGamma(probability,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Gamma distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Gamma distribution | -//| with parameters a and b. | -//| | -//| Arguments: | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Gamma distribution. | -//+------------------------------------------------------------------+ -//| Author: Robert Kern | -//+------------------------------------------------------------------+ -double MathRandomGamma(const double a,const double b) - { - double bb,c,U,V,X=0,Y; -//--- check shape - if(a==1.0) - { - //--- exponential - return -MathLog(1.0-MathRandomNonZero()); - } - else - if(a<1.0) - { - for(;;) - { - U=MathRandomNonZero(); - //--- exponential - V=-MathLog(1.0-MathRandomNonZero()); - - if(U<=1.0-a) - { - X=MathPow(U,1.0/a); - if(X<=V) - return b*X; - } - else - { - Y = -MathLog((1-U)/a); - X = MathPow(1.0 - a + a*Y, 1.0/a); - if(X<=(V+Y)) - return(b*X); - } - } - } - else - { - bb= a-1.0/3.0; - c = 1.0/MathSqrt(9*bb); - for(;;) - { - do - { - //--- generate normal random variate - double f,x1,x2,r2; - do - { - x1=2.0*MathRandomNonZero()-1.0; - x2=2.0*MathRandomNonZero()-1.0; - r2=x1*x1+x2*x2; - } - while(r2>=1.0 || r2==0.0); - //--- Box-Muller transform - f=MathSqrt(-2.0*MathLog(r2)/r2); - X=f*x2; - - V=1.0+c*X; - } - while(V<=0.0); - - V = V*V*V; - U = MathRandomNonZero(); - - if(U<1.0-0.0331*(X*X)*(X*X)) - return(bb*V*b); - - if(MathLog(U)<0.5*X*X+bb*(1.0-V+MathLog(V))) - return(bb*V*b); - } - } - return(X*b); - } -//+------------------------------------------------------------------+ -//| Random variate from the Gamma distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Gamma distribution | -//| with parameters a and b. | -//| | -//| Arguments: | -//| a : Shape | -//| b : Scale | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Gamma distribution. | -//+------------------------------------------------------------------+ -double MathRandomGamma(const double a,const double b,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - return MathRandomGamma(a,b); - } -//+------------------------------------------------------------------+ -//| Random variate from the Gamma distribution | -//+------------------------------------------------------------------+ -//| The function generates random variables from the Gamma | -//| distribution with parameters a and b. | -//| | -//| Arguments: | -//| a : First shape parameter (a>0) | -//| b : Second shape parameter (b>0) | -//| data_count : Number of values needed | -//| result : Output array for random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomGamma(const double a,const double b,const int data_count,double &result[]) - { - if(data_count<=0) - return false; -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; -//--- prepare output array and calculate values - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check x - if(x!=MathRound(x)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<0) - return TailLog0(true,log_mode); - - if(p==1.0) - { - if(x==0.0) - return TailLog1(true,log_mode); - else - return TailLog0(true,log_mode); - } -//--- return geometric density - return TailLogValue(p*MathPow(1.0-p,x),true,log_mode); - } -//+------------------------------------------------------------------+ -//| Geometric mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function of | -//| the Geometric distribution with parameter p. | -//| | -//| Arguments: | -//| x : Random variable | -//| p : Probability parameter | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityGeometric(const double x,const double p,int &error_code) - { - return MathProbabilityDensityGeometric(x,p,false,error_code); - } -//+------------------------------------------------------------------+ -//| Geometric mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability mass function of | -//| the Geometric distribution with parameter p for values in x[]. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| p : Probability parameter | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityGeometric(const double &x[],const double p,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(p)) - return false; -//--- check probability - if(p<=0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - -//--- special case p==1.0 - if(p==1.0) - { - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - error_code=ERR_OK; -//--- check x - if(x<0) - return TailLog0(true,log_mode); -//--- check p - if(p==1.0) - { - if(x==0.0) - return TailLog1(true,log_mode); - else - return TailLog0(true,log_mode); - } -//--- calculate cdf and take into account round-off errors for probability - double cdf=1.0-MathPow(1.0-p,x+1.0); - return TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Geometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Geometric distribution with parameter p. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| p : Probability parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Geometric cumulative distribution function | -//| with parameter p, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionGeometric(const double x,const double p,int &error_code) - { - return MathCumulativeDistributionGeometric(x,p,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Geometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Geometric distribution with parameter p for values in x[]. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| p : Probability parameter | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionGeometric(const double &x[],const double p,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(p)) - return false; -//--- check probability range - if(p<=0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - -//--- special case p==1.0 - if(p==1.0) - { - for(int i=0; i=1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- +infinity - if(prob==1.0) - return QPOSINF; - if(prob==0.0) - return 0.0; - - double res=MathCeil(-1.0+MathLog(1.0-prob)/MathLog(1.0-p)-1e-12); - if(res<0) - res=0; -//--- return quantile - return res; - } -//+------------------------------------------------------------------+ -//| Geometric distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Geometric distribution with parameter p | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| p : Probability parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Geometric quantile function for probability. | -//+------------------------------------------------------------------+ -double MathQuantileGeometric(const double probability,const double p,int &error_code) - { - return MathQuantileGeometric(probability,p,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Geometric distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Geometric distribution with parameter p | -//| for values form the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| p : Probability parameter | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileGeometric(const double &probability[],const double p,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(p)) - return false; -//--- check p range - if(p<=0.0 || p>=1.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- +infinity - if(prob==1.0) - result[i]=QPOSINF; - if(prob==0.0) - result[i]=0.0; - else - { - double res=MathCeil(-1.0+MathLog(1.0-prob)/MathLog(1.0-p)-1e-12); - if(res<0) - res=0; - result[i]=res; - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Geometric distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Geometric distribution with parameter p | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| p : Probability parameter | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileGeometric(const double &probability[],const double p,double &result[]) - { - return MathQuantileGeometric(probability,p,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Geometric distribution | -//+------------------------------------------------------------------+ -//| Computes the random variable from the Geometric distribution | -//| with parameter p. | -//| | -//| Arguments: | -//| p : Probability parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Geometric distribution. | -//+------------------------------------------------------------------+ -double MathRandomGeometric(const double p,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check probability range - if(p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- generate random number - double rnd=MathRandomNonZero(); - double res=MathCeil(-1.0+MathLog(rnd)/MathLog(1.0-p)-1e-12); - if(res<0) - res=0; - return res; - } -//+------------------------------------------------------------------+ -//| Random variate from the Geometric distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Geometric distribution with | -//| parameter p. | -//| | -//| Arguments: | -//| p : Probability parameter | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomGeometric(const double p,const int data_count,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(p)) - return false; -//--- check probability range - if(p<0.0 || p>1.0) - return false; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i=1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return(false); - } - - error_code=ERR_OK; -//--- calculate moments - mean =(1.0/p)-1; - variance=(1.0-p)/(p*p); - skewness=(2.0-p)/MathSqrt(1.0-p); - kurtosis=(p*p-6*p+6)/(1-p); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Hypergeometric.mqh b/Include/Math/Stat/Hypergeometric.mqh deleted file mode 100644 index 25ab318..0000000 --- a/Include/Math/Stat/Hypergeometric.mqh +++ /dev/null @@ -1,754 +0,0 @@ -//+------------------------------------------------------------------+ -//| Hypergeometric.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" - -//+------------------------------------------------------------------+ -//| Hypergeometric probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Hypergeometric distribution with parameters m,n,k. | -//| f(x,m,k,n)=C(k,x)*C(m-k,n-x)/C(m,n) | -//| where binomial coefficient C(n,k)=n!/(k!*(n-k)! | -//| | -//| Arguments: | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass function, evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityHypergeometric(const double x,const double m,const double k,const double n,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n)) - { - error_code=ERR_ARGUMENTS_NAN; - return(QNaN); - } -//--- m,k,n must be integer - if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n)) - { - error_code=ERR_ARGUMENTS_INVALID; - return(QNaN); - } -//--- m,k,n must be positive - if(m<0 || k<0 || n<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return(QNaN); - } -//--- check ranges - if(n>m || k>m) - { - error_code=ERR_ARGUMENTS_INVALID; - return(QNaN); - } - - error_code=ERR_OK; -//--- check ranges - if(x>n) - return TailLog0(true,log_mode); - if(x>k || m-k-n+x+1<=0) - return TailLog0(true,log_mode); -//--- calculate log binomial coefficients - double log_pdf=MathBinomialCoefficientLog(k,x)+MathBinomialCoefficientLog(m-k,n-x)-MathBinomialCoefficientLog(m,n); - if(log_mode==true) - return log_pdf; -//--- return hypergeometric density - return MathExp(log_pdf); - } -//+------------------------------------------------------------------+ -//| Hypergeometric probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Hypergeometric distribution with parameters m,n,k. | -//| f(x,m,k,n)=C(k,x)*C(m-k,n-x)/C(m,n) | -//| where binomial coefficient C(n,k)=n!/(k!*(n-k)! | -//| | -//| Arguments: | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass function, evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityHypergeometric(const double x,const double m,const double k,const double n,int &error_code) - { - return MathProbabilityDensityHypergeometric(x,m,k,n,false,error_code); - } -//+------------------------------------------------------------------+ -//| Hypergeometric probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability mass function of the | -//| Hypergeometric distribution with parameter m,k,n for values in x.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityHypergeometric(const double &x[],const double m,const double k,const double n,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n)) - return false; -//--- m,k,n must be integer - if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n)) - return false; -//--- m,k,n must be positive - if(m<0 || k<0 || n<0) - return false; -//--- check ranges - if(n>m || k>m) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - double m_k=m-k; - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; in) - result[i]=TailLog0(true,log_mode); - else - //--- check ranges - if(x_arg>k || m_k-n+x_arg+1<=0) - result[i]=TailLog0(true,log_mode); - else - { - //--- calculate log binomial coefficients - double log_pdf=MathBinomialCoefficientLog(k,x_arg)+MathBinomialCoefficientLog(m_k,n-x_arg)-MathBinomialCoefficientLog(m,n); - if(log_mode==true) - result[i]=log_pdf; - else - result[i]=MathExp(log_pdf); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Hypergeometric probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability mass function of the | -//| Hypergeometric distribution with parameter m,k,n for values in x.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityHypergeometric(const double &x[],const double m,const double k,const double n,double &result[]) - { - return MathProbabilityDensityHypergeometric(x,m,k,n,false,result); - } -//+------------------------------------------------------------------+ -//| Hypergeometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Hypergeometric distribution with parameters m,n,k | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Hypergeometric cumulative distribution function | -//| with parameters m,n,k, evaluated at x. | -//+------------------------------------------------------------------+ -//| Based on algorithm by John Burkardt | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionHypergeometric(const double x,const double m,const double k,const double n,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- m,k,n,x must be integer - if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n) || x!=MathRound(x)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- m,k,n,x must be positive - if(m<0 || k<0 || n<0 || x<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check ranges - if(n>m || k>m) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x>=n || x>=k) - return TailLog1(tail,log_mode); -//--- calculate cdf - double pdf = MathExp(MathBinomialCoefficientLog(m-k,n)-MathBinomialCoefficientLog(m,n)); - double cdf = pdf; - double coef=m-k-n+1; - for(int j=0; j<=x-1; j++) - { - pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j)); - cdf = cdf + pdf; - } - return TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Hypergeometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Hypergeometric distribution with parameters m,n,k | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired number of objects | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Hypergeometric cumulative distribution function | -//| with parameters m,n,k, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionHypergeometric(const double x,const double m,const double k,const double n,int &error_code) - { - return MathCumulativeDistributionHypergeometric(x,m,k,n,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Hypergeometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Hypergeometric distribution with parameters m,k,n for | -//| the values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -//| Based on algorithm by John Burkardt | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionHypergeometric(const double &x[],const double m,const double k,const double n,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n)) - return false; -//--- m,k,n,x must be integer - if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n)) - return false; -//--- m,k,n must be positive - if(m<0 || k<0 || n<0) - return false; -//--- check ranges - if(n>m || k>m) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - double coef=m-k-n+1; - - ArrayResize(result,data_count); - for(int i=0; i=n || x_arg>=k) - result[i]=TailLog1(tail,log_mode); - else - { - //--- calculate cdf - double pdf = MathExp(MathBinomialCoefficientLog(m-k,n)-MathBinomialCoefficientLog(m,n)); - double cdf = pdf; - for(int j=0; j<=x_arg-1; j++) - { - pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j)); - cdf = cdf + pdf; - } - result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Hypergeometric cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Hypergeometric distribution with parameters m,k,n for | -//| the values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionHypergeometric(const double &x[],const double m,const double k,const double n,double &result[]) - { - return MathCumulativeDistributionHypergeometric(x,m,k,n,true,false,result); - } -//+------------------------------------------------------------------+ -//| Hypergeometric distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| Computes the inverse cumulative distribution function of the | -//| Hypergeometric distribution with parameters m,n,k for the | -//| desired probability. | -//| | -//| Arguments: | -//| probability : The probability | -//| m : Size of the population | -//| k : Number of items with the desired characteristic | -//| in the population | -//| n : Number of samples drawn | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The smallest value x, such that the hypergeometric CDF(x) | -//| equals or exceeds the desired probability. | -//+------------------------------------------------------------------+ -//| Based on algorithm by John Burkardt | -//+------------------------------------------------------------------+ -double MathQuantileHypergeometric(const double probability,const double m,const double k,const double n,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- m,k,n,x must be integer - if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- m,k,n must be positive - if(m<0 || k<0 || n<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check ranges - if(n>m || k>m) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check probability - if(prob==0) - return 0.0; - if(prob==1.0) - return QPOSINF; - - int max_terms=1000; - prob*=1-1000*DBL_EPSILON; - double m_k=m-k; - double pdf = MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n)); - double cdf = pdf; - double coef=m_k-n+1; - int j=0; - while(cdfm || k>m) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int max_terms=1000; - double m_k=m-k; - double pdf0= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n)); - double coef=m_k-n+1; - - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- check probability - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=QPOSINF; - else - { - prob*=1-1000*DBL_EPSILON; - double pdf = pdf0; - double cdf = pdf; - int j=0; - while(cdfm || k>m) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- generate random number - double prob=MathRandomNonZero(); - prob*=1-1000*DBL_EPSILON; - int max_terms=1000; - double m_k=m-k; - double coef=m_k-n+1; - double pdf= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n)); - double cdf= pdf; - int j=0; - while(cdfm || k>m) - return false; -//--- prepare coefficients - int max_terms=1000; - double m_k=m-k; - double coef=m_k-n+1; - double pdf0= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n)); -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; im || k>m) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- calculate moments - mean =n*k/m; - variance=k*n*(1-k/m)*(m-n)/(m*(m-1)); - skewness=MathSqrt(m-1)*(m-2*k)*(m-2*n)/((m-2)*MathSqrt(k*n*(m-k)*(m-n))); - kurtosis=(m-1)*m*m/(k*n*(m-3)*(m-2)*(m-k)*(m-n)); - kurtosis*=3*k*(m-k)*(m*m*(n-2)-m*n*n+6*n*(m-n))/(m*m)-6*n*(m-n)+m*(m+1); - kurtosis-=3; -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Logistic.mqh b/Include/Math/Stat/Logistic.mqh deleted file mode 100644 index 0ead3fc..0000000 --- a/Include/Math/Stat/Logistic.mqh +++ /dev/null @@ -1,592 +0,0 @@ -//+------------------------------------------------------------------+ -//| Logistic.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" - -//+------------------------------------------------------------------+ -//| Logistic distribution density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of | -//| the Logistic distribution with parameters mu and sigma. | -//| f(x,mu,sigma)=exp[-(x-mu)/sigma]/(sigma*(exp[-(x-mu)/sigma])^2) | -//| | -//| Arguments: | -//| x : Random variable | -//| mu : Mean | -//| sigma : Scale parameter | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityLogistic(const double x,const double mu,const double sigma,const bool log_mode,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- prepare argument - double y=(x-mu)/sigma; -//--- check result - if(!MathIsValidNumber(y)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - -//--- calculate exponents - double e=MathExp(-y); - double e1=(1+e); - double pdf=e/(sigma*(e1*e1)); - if(log_mode==true) - return MathLog(pdf); -//--- return logistic density - return pdf; - } -//+------------------------------------------------------------------+ -//| Logistic distribution density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of | -//| the Logistic distribution with parameters mu and sigma. | -//| f(x,mu,sigma)=exp[-(x-mu)/sigma]/(sigma*(exp[-(x-mu)/sigma])^2) | -//| | -//| Arguments: | -//| x : Random variable | -//| mu : Mean | -//| sigma : Scale parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityLogistic(const double x,const double mu,const double sigma,int &error_code) - { - return MathProbabilityDensityLogistic(x,mu,sigma,false,error_code); - } -//+------------------------------------------------------------------+ -//| Logistic distribution density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Logistic distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| sigma : Scale parameter | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityLogistic(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - if(prob==0.0 || prob==1.0) - { - if(sigma==0.0) - { - error_code=ERR_OK; - return mu; - } - else - { - error_code=ERR_RESULT_INFINITE; - if(prob==0.0) - return QNEGINF; - else - return QPOSINF; - } - } - - error_code=ERR_OK; -//--- calculate quantile - double q=MathLog(prob/(1.0-prob)); -//--- return rescaled/shifted quantile - return mu+sigma*q; - } -//+------------------------------------------------------------------+ -//| Logistic distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Logistic distribution with parameters mu | -//| and sigma for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| mu : Mean | -//| sigma : Scale parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Logistic distribution with parameters mu and sigma. | -//+------------------------------------------------------------------+ -double MathQuantileLogistic(const double probability,const double mu,const double sigma,int &error_code) - { - return MathQuantileLogistic(probability,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Logistic distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Logistic distribution with parameters mu and | -//| sigma for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| sigma : Scale parameter | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileLogistic(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - if(prob==0.0 || prob==1.0) - { - if(sigma==0.0) - result[i]=mu; - else - { - if(prob==0.0) - result[i]=QNEGINF; - else - result[i]=QPOSINF; - } - } - else - { - //--- calculate quantile - double q=MathLog(prob/(1.0-prob)); - //--- rescaled/shifted quantile - result[i]=mu+sigma*q; - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Logistic distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Logistic distribution with parameters mu and | -//| sigma for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| sigma : Scale parameter | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileLogistic(const double &probability[],const double mu,const double sigma,double &result[]) - { - return MathQuantileLogistic(probability,mu,sigma,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Logistic distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Logistic distribution | -//| with parameters mu and sigma. | -//| | -//| Arguments: | -//| mu : Mean | -//| sigma : Scale parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Logistic distribution. | -//+------------------------------------------------------------------+ -double MathRandomLogistic(const double mu,const double sigma,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check sigma - if(sigma==0.0) - return mu; -//--- generate random number - double rnd=MathRandomNonZero(); -//--- return value - return mu+sigma*MathLog(rnd/(1.0-rnd)); - } -//+------------------------------------------------------------------+ -//| Random variate from the Logistic distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Logistic distribution | -//| with parameters mu and sigma. | -//| | -//| Arguments: | -//| mu : Mean | -//| sigma : Scale parameter | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomLogistic(const double mu,const double sigma,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0.0) - return false; - -//--- prepare output array - ArrayResize(result,data_count); -//--- check sigma - if(sigma==0.0) - { - for(int i=0; i=2*MathSqrt(DBL_MAX)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- return lognormal density - return TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/(x*sigma),true,log_mode); - } -//+------------------------------------------------------------------+ -//| Lognormal density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Lognormal distribution with parameters mu and sigma | -//| for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityLognormal(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - -//--- check case sigma==0 - if(sigma==0) - { - for(int i=0; i=2*MathSqrt(DBL_MAX)) - return false; - //--- return lognormal density - result[i]=TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/(x_arg*sigma),true,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Lognormal density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Lognormal distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityLognormal(const double &x[],const double mu,const double sigma,double &result[]) - { - return MathProbabilityDensityLognormal(x,mu,sigma,false,result); - } -//+------------------------------------------------------------------+ -//| Lognormal density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Lognormal distribution with parameters mu and sigma. | -//| | -//| f(x,mu,sigma)=[1/(x*sigma*sqrt(2pi)]*exp(-(ln(x)-mu)/(2*sigma^2))| -//| | -//| Arguments: | -//| x : Random variable | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityLognormal(const double x,const double mu,const double sigma,int &error_code) - { - return MathProbabilityDensityLognormal(x,mu,sigma,false,error_code); - } -//+------------------------------------------------------------------+ -//| Lognormal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Lognormal distribution with parameters mu and sigma | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Lognormal cumulative distribution function | -//| with parameters mu and sigma, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionLognormal(const double x,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x - if(x<=0.0) - return TailLog0(tail,log_mode); -//--- return lognormal cdf using Normal cdf - return MathCumulativeDistributionNormal(MathLog(x),mu,sigma,tail,log_mode,error_code); - } -//+------------------------------------------------------------------+ -//| Lognormal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Lognormal distribution with parameters mu and sigma | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Lognormal cumulative distribution function | -//| with parameters mu and sigma, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionLognormal(const double x,const double mu,const double sigma,int &error_code) - { - return MathCumulativeDistributionLognormal(x,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Lognormal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Lognormal distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionLognormal(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- special cases exp(a+b-+infinity) - if(prob==0.0 || prob==1.0) - { - if(sigma==0.0) - { - error_code=ERR_OK; - return MathExp(mu); - } - else - if(prob==0.0) - { - if(sigma>0) - { - error_code=ERR_OK; - return 0.0; - } - else - if(sigma<0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - } - else - { - if(sigma<0) - { - error_code=ERR_OK; - return 0.0; - } - else - if(sigma>0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - } - } -//--- return lognormal quantile using Normal distribution - return MathExp(MathQuantileNormal(prob,mu,sigma,error_code)); - } -//+------------------------------------------------------------------+ -//| Lognormal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of Lognormal distribution with parameters mu and sigma | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The quantile value of the Lognormal distribution. | -//+------------------------------------------------------------------+ -double MathQuantileLognormal(const double probability,const double mu,const double sigma,int &error_code) - { - return MathQuantileLognormal(probability,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Lognormal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Lognormal distribution with parameters mu and | -//| sigma for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileLognormal(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- special cases exp(a+b-+infinity) - if(prob==0.0 || prob==1.0) - { - if(sigma==0.0) - result[i]=MathExp(mu); - else - if(prob==0.0) - { - if(sigma>0) - result[i]=0.0; - else - if(sigma<0) - result[i]=QPOSINF; - } - else - { - if(sigma<0) - result[i]=0.0; - else - if(sigma>0) - result[i]=QPOSINF; - } - } - else - //--- calculate lognormal quantile using Normal distribution - result[i]=MathExp(MathQuantileNormal(prob,mu,sigma,error_code)); - } - return true; - } -//+------------------------------------------------------------------+ -//| Lognormal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Lognormal distribution with parameters mu and | -//| sigma for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileLognormal(const double &probability[],const double mu,const double sigma,double &result[]) - { - return MathQuantileLognormal(probability,mu,sigma,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Lognormal distribution | -//+------------------------------------------------------------------+ -//| Computes the random variable from the Lognormal distribution | -//| with parameters mu and sigma. | -//| | -//| Arguments: | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Lognormal distribution. | -//+------------------------------------------------------------------+ -double MathRandomLognormal(const double mu,const double sigma,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - error_code=ERR_OK; -//--- generate random number - double rnd=MathRandomNonZero(); -//--- - rnd=MathQuantileNormal(rnd,mu,sigma,true,false,error_code); - return MathExp(rnd); - } -//+------------------------------------------------------------------+ -//| Random variate from the Lognormal distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Lognormal distribution | -//| with parameters mu and sigma. | -//| | -//| Arguments: | -//| mu : Log mean | -//| sigma : Log standard deviation | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomLognormal(const double mu,const double sigma,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - int err_code=0; - for(int i=0; i|czU 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 Rkw}eSyk}WAzB(x8{{ewwz?lF5 diff --git a/Include/Math/Stat/NegativeBinomial.mqh b/Include/Math/Stat/NegativeBinomial.mqh deleted file mode 100644 index 165cbe5..0000000 --- a/Include/Math/Stat/NegativeBinomial.mqh +++ /dev/null @@ -1,643 +0,0 @@ -//+------------------------------------------------------------------+ -//| NegativeBinomial.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "Gamma.mqh" -#include "Poisson.mqh" - -//+------------------------------------------------------------------+ -//| Negative Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Negative Binomial distribution with parameters r and p. | -//| | -//| Arguments: | -//| x : Random variable | -//| r : Number of successes | -//| p : Probability of success | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNegativeBinomial(const double x,const double r,const double p,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(r) || !MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check arguments - if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<0.0) - return TailLog0(true,log_mode); -//--- calculate gamma factor for the density - double coef=MathRound(MathExp(MathGammaLog(r+x)-MathGammaLog(x+1.0)-MathGammaLog(r))); -//--- return density - return TailLogValue(coef*MathPow(p,r)*MathPow(1.0-p,x),true,log_mode); - } -//+------------------------------------------------------------------+ -//| Negative Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Negative Binomial distribution with parameters r and p. | -//| | -//| Arguments: | -//| x : Random variable | -//| r : Number of successes | -//| p : Probability of success | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNegativeBinomial(const double x,const double r,const double p,int &error_code) - { - return MathProbabilityDensityNegativeBinomial(x,r,p,false,error_code); - } -//+------------------------------------------------------------------+ -//| Negative Binomial probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability mass function | -//| of the Negative Binomial distribution with parameters r and p | -//| for values from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| r : Number of successes | -//| p : Probability of success | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityNegativeBinomial(const double &x[],const double r,const double p,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(r) || !MathIsValidNumber(p)) - return false; -//--- check arguments - if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - double power_p_r=MathPow(p,r); - double log_gamma_r=MathGammaLog(r); - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0 || x<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<0.0) - return TailLog0(tail,log_mode); - int err_code=0; -//--- calculate max term of the sum - int max_j=(int)MathFloor(x); - double p1=1.0-p; -//--- initial factors - double factor1=MathFactorial((int)r-1); - double factor2=1.0; - double factor_p=1.0; - double factor_r=1.0/factor1; - double power_p_r=MathPowInt(p,int(r))*factor_r; - double cdf=0.0; - for(int j=0; j<=max_j; j++) - { - if(j>0) - { - factor1*=(j+1); - factor2*=j; - factor_p*=p1; - } - double pdf=power_p_r*factor1*factor_p/factor2; - cdf+=pdf; - } -//--- take into account round-off errors for probability - return TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Negative Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Negative Binomial distribution with parameters r and p | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| r : Number of successes | -//| p : Probability of success | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Negative Binomial cumulative distribution | -//| function with parameters r and p, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionNegativeBinomial(const double x,const double r,double p,int error_code) - { - return MathCumulativeDistributionNegativeBinomial(x,r,p,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Negative Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function | -//| of the Negative Binomial distribution with parameters r and p | -//| for values from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| r : Number of successes | -//| p : Probability of success | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNegativeBinomial(const double &x[],const double r,double p,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(r) || !MathIsValidNumber(p)) - return false; -//--- check arguments - if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; -//--- common factors - double fact1=MathFactorial((int)r-1); - double factor_r=1.0/fact1; - double power_p_r=MathPowInt(p,int(r))*factor_r; - double p1=1.0-p; - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0) - { - factor1*=(j+1); - factor2*=j; - factor_p*=p1; - } - double pdf=power_p_r*factor1*factor_p/factor2; - cdf+=pdf; - } - //--- take into account round-off errors for probability - result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Negative Binomial cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function | -//| of the Negative Binomial distribution with parameters r and p | -//| for values from x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| r : Number of successes | -//| p : Probability of success | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNegativeBinomial(const double &x[],const double r,double p,double &result[]) - { - return MathCumulativeDistributionNegativeBinomial(x,r,p,true,false,result); - } -//+------------------------------------------------------------------+ -//| Negative Binomial distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Negative Binomial distribution with parameters | -//| r and p for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| r : Number of successes | -//| p : Probability of success | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Negative Binomial distribution with parameters r and p. | -//+------------------------------------------------------------------+ -double MathQuantileNegativeBinomial(const double probability,const double r,const double p,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(r) || !MathIsValidNumber(p)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check arguments - if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check cases p=0 and p=1 - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - error_code=ERR_OK; - if(prob==0.0) - return 0.0; - - int max_terms=1000; - int err_code=0; -//--- factors - double fact1=MathFactorial((int)r-1); - double factor_r=1.0/fact1; - double power_p_r=MathPowInt(p,int(r))*factor_r; - double p1=1.0-p; -//--- initial factors - double factor1=fact1; - double factor2=1.0; - double factor_p=1.0; - double cdf=0.0; - int j=0; - while(cdf0) - { - factor1*=(j+1); - factor2*=j; - factor_p*=p1; - } - double pdf=power_p_r*factor1*factor_p/factor2; - cdf+=pdf; - j++; - } -//--- check convergence - if(j1.0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; -//--- common factors - double fact1=MathFactorial((int)r-1); - double factor_r=1.0/fact1; - double power_p_r=MathPowInt(p,int(r))*factor_r; - double p1=1.0-p; - int max_terms=500; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - if(prob==0.0) - result[i]=0.0; - else - if(prob==1.0) - result[i]=QPOSINF; - else - { - double factor1=fact1; - double factor2=1.0; - double factor_p=1.0; - double cdf=0.0; - int j=0; - while(cdf0) - { - factor1*=(j+1); - factor2*=j; - factor_p*=p1; - } - double pdf=power_p_r*factor1*factor_p/factor2; - cdf+=pdf; - j++; - } - if(j=1.0) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } - double r_gamma=MathRandomGamma(r,(1-p)/p); - return MathRandomPoisson(r_gamma,error_code); - } -//+------------------------------------------------------------------+ -//| Random variate from the Negative Binomial distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Negative Binomial | -//| distribution with parameters r and p. | -//| | -//| Arguments: | -//| r : Number of successes | -//| p : Probability of success | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomNegativeBinomial(const double r,const double p,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(r) || !MathIsValidNumber(p)) - return false; -//--- check arguments - if(r<=0.0 || p<=0.0 || p>=1.0) - return false; - - double p_coef=(1-p)/p; - int error_code=0; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i=1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- calculate moments - mean =r*(1.0-p)/p; - variance=mean/p; - skewness=(2.0-p)/MathSqrt((r*(1.0-p))); - kurtosis=(p*p-6*p+6)/(r*(1.0-p)); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/NoncentralBeta.mqh b/Include/Math/Stat/NoncentralBeta.mqh deleted file mode 100644 index bf4375d..0000000 --- a/Include/Math/Stat/NoncentralBeta.mqh +++ /dev/null @@ -1,955 +0,0 @@ -//+------------------------------------------------------------------+ -//| NoncentralBeta.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "Beta.mqh" -#include "NoncentralChiSquare.mqh" - -//+------------------------------------------------------------------+ -//| Noncental Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Noncental Beta distribution with parameters a,b,lambda | -//| Infinity | -//| f(x,a,b,lambda)=Sum [p(k)*x^(a+k-1)*(1-x)^(b-1)]/Beta(a+k,b) | -//| k=0 | -//| | -//| where p(k)=(1/k!)*exp(-lambda/2)*(lambda/2)^k, | -//| Beta(a,b)=Gamma(a)*Gamma(b)/Gamma(a+b) | -//| | -//| Arguments: | -//| x : Random variable | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNoncentralBeta(const double x,const double a,const double b,const double lambda,const bool log_mode,int &error_code) - { -//--- if lambda==0, return Beta density - if(lambda==0.0) - return MathProbabilityDensityBeta(x,a,b,error_code); -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a,b,lambda must be positive - if(a<=0.0 || b<=0.0 || lambda<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<=0.0 || x>=1.0) - return TailLog0(true,log_mode); -//--- factors - double lambda_half=lambda*0.5; - double fact_mult=1.0; - double pwr_lambda_half=1.0; - double pwr_x=MathExp((a-1.0)*MathLog(x)); - double r_beta=MathBeta(a,b); - double pdf=0; -//--- direct sum calculation - for(int j=0;; j++) - { - if(j>0) - { - pwr_x*=x; - pwr_lambda_half*=lambda_half; - fact_mult/=j; - double jm1=j-1; - r_beta*=((a+jm1)/(a+b+jm1)); - } - double term=pwr_x*fact_mult*pwr_lambda_half/r_beta; - //--- - if(term<10E-18) - break; - pdf+=term; - } -//--- calculate density coef - pdf*=MathExp((b-1.0)*MathLog(1.0-x))*MathExp(-lambda_half); -//--- return density - return TailLogValue(pdf,true,log_mode); - } -//+------------------------------------------------------------------+ -//| Noncental Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Noncental Beta distribution with parameters a,b,lambda. | -//| | -//| Arguments: | -//| x : Random variable | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNoncentralBeta(const double x,const double a,const double b,const double lambda,int &error_code) - { - return MathProbabilityDensityNoncentralBeta(x,a,b,lambda,false,error_code); - } -//+------------------------------------------------------------------+ -//| Noncental Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Noncentral Beta distribution with parameters a,b,lambda | -//| for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityNoncentralBeta(const double &x[],const double a,const double b,const double lambda,const bool log_mode,double &result[]) - { -//--- if lambda==0, return Beta density - if(lambda==0.0) - return MathProbabilityDensityBeta(x,a,b,log_mode,result); -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a,b,lambda must be positive - if(a<=0.0 || b<=0.0 || lambda<0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; -//--- common factors - double lambda_half=lambda*0.5; - double exp_lambda_half=MathExp(-lambda_half); - double r_beta0=MathBeta(a,b); - ArrayResize(result,data_count); - for(int i=0; i=1.0) - result[i]=TailLog0(true,log_mode); - else - { - double fact_mult=1.0; - double pwr_lambda_half=1.0; - double pwr_x=MathExp((a-1.0)*MathLog(x_arg)); - double r_beta=r_beta0; - double pdf=0; - for(int j=0;; j++) - { - if(j>0) - { - pwr_x*=x_arg; - pwr_lambda_half*=lambda_half; - fact_mult/=j; - double jm1=j-1; - r_beta*=((a+jm1)/(a+b+jm1)); - } - double term=pwr_x*fact_mult*pwr_lambda_half/r_beta; - //--- - if(term<10E-18) - break; - pdf+=term; - } - //--- calculate density coef - pdf*=MathExp((b-1.0)*MathLog(1.0-x_arg))*exp_lambda_half; - result[i]=TailLogValue(pdf,true,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Noncental Beta density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Noncentral Beta distribution with parameters a,b,lambda | -//| for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityNoncentralBeta(const double &x[],const double a,const double b,const double lambda,double &result[]) - { - return MathProbabilityDensityNoncentralBeta(x,a,b,lambda,false,result); - } -//+------------------------------------------------------------------+ -//| Noncental Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Noncental Beta distribution with parameters a,b,lambda | -//| is less than or equal to x. | -//| | -//| Input parameters: | -//| x : The desired quantile | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Noncental Beta cumulative distribution function | -//| with parameters a,b,lambda, evaluated at x. | -//| | -//| Infinity | -//| F(x,a,b,lambda)=Sum p(k)*Ix(a+k,b) | -//| k=0 | -//| | -//| where p(k)=(1/k!)*exp(-lambda/2)*(lambda/2)^k, | -//| Ix(a,b) - incomplete Beta function | -//| | -//| Author: John Burkardt | -//| | -//| Reference: | -//| Harry Posten,"An Effective Algorithm for the Noncentral Beta | -//| Distribution Function", The American Statistician, | -//| Volume 47, Number 2, May 1993, pages 129-131. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionNoncentralBeta(const double x,const double a,const double b,const double lambda,const bool tail,const bool log_mode,int &error_code) - { -//--- if lambda==0, return Beta CDF - if(lambda==0.0) - return MathCumulativeDistributionBeta(x,a,b,error_code); -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a,b,lambda must be positive - if(a<=0.0 || b<=0.0 || lambda<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<=0.0) - return TailLog0(tail,log_mode); - if(x>=1.0) - return TailLog1(tail,log_mode); - - const int max_terms=100; - double c=lambda*0.5; - double x0 = int(MathMax(c - 5*MathSqrt(c), 0)); - double a0 = a + x0; - double beta = MathGammaLog(a0) + MathGammaLog(b) - MathGammaLog(a0+b); - double temp = MathBetaIncomplete(x, a0, b); - double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0)); - - double q=0; - if(a0>a) - q=MathExp(-c+x0*MathLog(c)-MathGammaLog(x0+1)); - else - q=MathExp(-c); - - double sumq=1-q; - double betanc=q*temp; - double ab=a+b; - int j=0; - for(;;) - { - j++; - temp-=gx; - gx*=x*(ab+j-1)/(a+j); - q*=c/j; - sumq-=q; - betanc+=temp*q; - double err=(temp-gx)*sumq; - if(j>max_terms || err<1E-18) - break; - } - double cdf=MathMin(betanc,1.0); - return TailLogValue(cdf,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Noncental Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Noncental Beta distribution with parameters a,b,lambda | -//| is less than or equal to x. | -//| | -//| Input parameters: | -//| x : The desired quantile | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Noncental Beta cumulative distribution function | -//| with parameters a,b,lambda, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionNoncentralBeta(const double x,const double a,const double b,const double lambda,int &error_code) - { - return MathCumulativeDistributionNoncentralBeta(x,a,b,lambda,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Noncental Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Noncentral Beta distribution with parameters a,b,lambda | -//| for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNoncentralBeta(const double &x[],const double a,const double b,const double lambda,const bool tail,const bool log_mode,double &result[]) - { -//--- if lambda==0, return Beta CDF - if(lambda==0.0) - return MathCumulativeDistributionBeta(x,a,b,tail,log_mode,result); -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a,b,lambda must be positive - if(a<=0.0 || b<=0.0 || lambda<0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - const int max_terms=100; - ArrayResize(result,data_count); - for(int i=0; i=1.0) - result[i]=TailLog1(tail,log_mode); - else - { - double c=lambda*0.5; - double x0 = int(MathMax(c - 5*MathSqrt(c), 0)); - double a0 = a + x0; - double beta = MathGammaLog(a0) + MathGammaLog(b) - MathGammaLog(a0+b); - double temp = MathBetaIncomplete(x_arg, a0, b); - double gx=MathExp(a0*MathLog(x_arg)+b*MathLog(1-x_arg)-beta-MathLog(a0)); - - double q=0; - if(a0>a) - q=MathExp(-c+x0*MathLog(c)-MathGammaLog(x0+1)); - else - q=MathExp(-c); - - double sumq=1-q; - double betanc=q*temp; - int j=0; - double ab=a+b; - for(;;) - { - j++; - temp-=gx; - gx*=x_arg*(ab+j-1)/(a+j); - q*=c/j; - sumq-=q; - betanc+=temp*q; - double err=(temp-gx)*sumq; - if(j>max_terms || err<1E-18) - break; - } - double cdf=MathMin(betanc,1.0); - result[i]=TailLogValue(cdf,tail,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Noncental Beta cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Noncentral Beta distribution with parameters a,b,lambda | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNoncentralBeta(const double &x[],const double a,const double b,const double lambda,double &result[]) - { - return MathCumulativeDistributionNoncentralBeta(x,a,b,lambda,true,false,result); - } -//+------------------------------------------------------------------+ -//| Noncental Beta distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Noncental Beta distribution with parameters a,b | -//| and lambda for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : First shape parameter | -//| b : Second shape parameter | -//| lambda : Noncentrality parameter | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function of | -//| of Noncental Beta distribution with parameters a,b and lambda. | -//+------------------------------------------------------------------+ -double MathQuantileNoncentralBeta(const double probability,const double a,const double b,const double lambda,const bool tail,const bool log_mode,int &error_code) - { - if(log_mode==true && probability==QNEGINF) - return 0.0; - if(log_mode==false && probability==0) - return 0.0; -//--- if lambda==0, return beta quantile - if(lambda==0.0) - return MathQuantileBeta(probability,a,b,error_code); -//--- check parameters - if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a,b,lambda must be positive - if(a<=0.0 || b<=0.0 || lambda<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check probabilty - if(prob==0.0) - return 0.0; - if(prob==1.0) - return 1.0; - - double lambda_half=lambda*0.5; - double lambda_half_log=MathLog(lambda_half); - double lambda_half_sqrt=MathSqrt(lambda_half); - double lambda_half_exp=MathExp(-lambda_half); - - double x0=int(MathMax(lambda_half-5*lambda_half_sqrt,0)); - double b_gamma_log=MathGammaLog(b); - double eps=10E-18; - double h_min=MathSqrt(eps); - -//double lambda_half=lambda*0.5; - double r_beta0=MathBeta(a,b); - - int err_code=0; - double x=0.5; - double h=1.0; - const int max_terms=100; -//--- Newton iterations - const int max_iterations=50; - int iterations=0; - while(iterationsh_min*MathAbs(x) && MathAbs(h)>h_min)==false) - break; - - //--- calculate PDF - double pdf=0; - if(x<=0.0 || x>=1.0) - pdf=0; - else - { - double fact_mult=1.0; - double pwr_lambda_half=1.0; - double pwr_x=MathExp((a-1.0)*MathLog(x)); - double r_beta=r_beta0; - //--- direct sum calculation - for(int j=0;; j++) - { - if(j>0) - { - pwr_x*=x; - pwr_lambda_half*=lambda_half; - fact_mult/=j; - double jm1=j-1; - r_beta*=((a+jm1)/(a+b+jm1)); - } - double term=pwr_x*fact_mult*pwr_lambda_half/r_beta; - //--- - if(term<10E-18) - break; - pdf+=term; - } - //--- calculate density coef - pdf*=MathExp((b-1.0)*MathLog(1.0-x))*lambda_half_exp; - } - - //--- calculate CDF - double cdf=0; - if(x<=0.0) - cdf=0; - if(x>=1.0) - cdf=1; - else - { - double a0=a+x0; - double beta = MathGammaLog(a0) + b_gamma_log - MathGammaLog(a0+b); - double temp = MathBetaIncomplete(x, a0, b); - double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0)); - - double q=0; - if(a0>a) - q=MathExp(-lambda_half+x0*lambda_half_log-MathGammaLog(x0+1)); - else - q=lambda_half_exp; - - double sumq=1-q; - double betanc=q*temp; - int j=0; - double ab=a+b; - for(;;) - { - j++; - temp-=gx; - gx*=x*(ab+j-1)/(a+j); - q*=lambda_half/j; - sumq-=q; - betanc+=temp*q; - double err=(temp-gx)*sumq; - if(j>max_terms || err<1E-18) - break; - } - cdf=MathMin(betanc,1.0); - } - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1-x)*0.1; - - if(MathAbs(x_new-x)<10E-16) - break; - x=x_new; - - iterations++; - } -//--- check convergence - if(iterationsh_min*MathAbs(x) && MathAbs(h)>h_min)==false) - break; - - //--- calculate PDF - double pdf=0; - if(x<=0.0 || x>=1.0) - pdf=0; - else - { - double fact_mult=1.0; - double pwr_lambda_half=1.0; - double pwr_x=MathExp((a-1.0)*MathLog(x)); - double r_beta=r_beta0; - //--- direct sum calculation - for(int j=0;; j++) - { - if(j>0) - { - pwr_x*=x; - pwr_lambda_half*=lambda_half; - fact_mult/=j; - double jm1=j-1; - r_beta*=((a+jm1)/(a+b+jm1)); - } - double term=pwr_x*fact_mult*pwr_lambda_half/r_beta; - //--- - if(term<10E-18) - break; - pdf+=term; - } - //--- calculate density coef - pdf*=MathExp((b-1.0)*MathLog(1.0-x))*lambda_half_exp; - } - - //--- calculate CDF - double cdf=0; - if(x<=0.0) - cdf=0; - if(x>=1.0) - cdf=1; - else - { - double a0=a+x0; - double beta = MathGammaLog(a0) + b_gamma_log - MathGammaLog(a0+b); - double temp = MathBetaIncomplete(x, a0, b); - double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0)); - - double q=0; - if(a0>a) - q=MathExp(-lambda_half+x0*lambda_half_log-MathGammaLog(x0+1)); - else - q=lambda_half_exp; - - double sumq=1-q; - double betanc=q*temp; - int j=0; - double ab=a+b; - for(;;) - { - j++; - temp-=gx; - gx*=x*(ab+j-1)/(a+j); - q*=lambda_half/j; - sumq-=q; - betanc+=temp*q; - double err=(temp-gx)*sumq; - if(j>max_terms || err<1E-18) - break; - } - cdf=MathMin(betanc,1.0); - } - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1-x)*0.1; - - if(MathAbs(x_new-x)<10E-16) - break; - x=x_new; - - iterations++; - } - //--- check convergence - if(iterations0) - { - pwr_lambda*=lambda; - pwr_x*=x; - pwr_two*=0.5; - fact_mult*=1.0/j; - inv_factor*=1.0/(j+half_nu-1); - } - double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x; - pdf=pdf+dp; - //--- check stop - if(dp/(pdf+10E-10)<10E-16) - break; - j++; - } -//--- check convergence - if(j0) - { - pwr_lambda*=lambda; - pwr_x*=x_arg; - pwr_two*=0.5; - fact_mult*=1.0/j; - inv_factor*=1.0/(j+half_nu-1); - } - double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x; - pdf=pdf+dp; - //--- check stop - if(dp/(pdf+10E-10)<10E-16) - break; - j++; - } - //--- check convergence - if(j0) - { - pwr_lambda*=lambda; - fact_mult/=j; - } - double coef1=coef_lambda*pwr_lambda*fact_mult; - double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0); - double dp=coef1*coef2; - cdf=cdf+dp; - if((dp/(cdf+10E-10))<10E-16) - break; - j++; - } -//--- - if(j0) - { - pwr_lambda*=lambda; - fact_mult/=j; - } - double coef1=coef_lambda*pwr_lambda*fact_mult; - double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0); - double dp=coef1*coef2; - cdf=cdf+dp; - if((dp/(cdf+10E-10))<10E-16) - break; - j++; - } - //--- - if(j1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(prob==0.0) - return 0.0; - - if(prob==1.0) - return QPOSINF; - - error_code=ERR_OK; -//--- common factors for pdf and cdf calculation - const int max_terms=1000; - double lambda=sigma*0.5; - double half_nu=nu*0.5; - double coef_lambda=MathExp(-lambda); - double half_nu_m1=half_nu-1.0; - double coef_gamma=1.0/MathGamma(half_nu); - double pwr_two2=MathExp(-half_nu*MathLog(2)); - double pwr_half_num1=(half_nu-1.0); -//--- prepare values for initial x estimation - double x=0.5; - double h=1.0; - double h_min=10E-10; -//--- Newton iterations - const int max_iterations=50; - int iterations=0; -// int err_code=0; - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - - //double pdf=MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,err_code); - double half_x=x*0.5; - double pwr_lambda=1.0; - double pwr_two=pwr_two2; - double pwr_x=MathPow(x,pwr_half_num1); - double fact_mult=1.0; - double coef_lambda_x=coef_lambda*MathExp(-half_x); - double inv_factor=1.0; - //--- calculate density using direct summation - int j=0; - double pdf=0; - while(j0) - { - pwr_lambda*=lambda; - pwr_x*=x; - pwr_two*=0.5; - fact_mult*=1.0/j; - inv_factor*=1.0/(j+half_nu-1); - } - double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x; - pdf=pdf+dp; - //--- check stop - if(dp/(pdf+10E-10)<10E-16) - break; - j++; - } - //--- check convergence - if(j>max_terms) - { - error_code=ERR_NON_CONVERGENCE; - return QNaN; - } - - //--- calculate cdf - pwr_lambda=1.0; - fact_mult=1.0; - double cdf=0.0; - j=0; - //--- direct summation - while(j0) - { - pwr_lambda*=lambda; - fact_mult/=j; - } - double coef1=coef_lambda*pwr_lambda*fact_mult; - double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0); - double dp=coef1*coef2; - cdf=cdf+dp; - if((dp/(cdf+10E-10))<10E-16) - break; - j++; - } - //--- - if(j>max_terms) - { - error_code=ERR_NON_CONVERGENCE; - return QNaN; - } - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1-x)*0.1; - x=x_new; - - iterations++; - } -//--- check convergence - if(iterations1.0) - return false; - - //--- prepare values for initial x estimation - int err_code=0; - double x=0.5; - double h=1.0; - //--- Newton iterations - int iterations=0; - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - - //double pdf=MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,err_code); - double half_x=x*0.5; - double pwr_lambda=1.0; - double pwr_two=pwr_two0; - double pwr_x=MathPow(x,half_nu_m1); - double fact_mult=1.0; - double coef_lambda_x=coef_lambda*MathExp(-half_x); - double inv_factor=1.0; - //--- calculate density using direct summation - int j=0; - double pdf=0; - while(j0) - { - pwr_lambda*=lambda; - pwr_x*=x; - pwr_two*=0.5; - fact_mult*=1.0/j; - inv_factor*=1.0/(j+half_nu-1); - } - double dp=pwr_gamma0*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x; - pdf=pdf+dp; - //--- check stop - if(dp/(pdf+10E-10)<10E-16) - break; - j++; - } - //--- check convergence - if(j>max_terms) - return false; - - //--- calculate cdf - pwr_lambda=1.0; - fact_mult=1.0; - pwr_lambda=1.0; - fact_mult=1.0; - double cdf=0.0; - j=0; - //--- direct summation - while(j0) - { - pwr_lambda*=lambda; - fact_mult/=j; - } - double coef1=coef_lambda*pwr_lambda*fact_mult; - double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0); - double dp=coef1*coef2; - cdf=cdf+dp; - if((dp/(cdf+10E-10))<10E-16) - break; - j++; - } - //--- - if(j>max_terms) - return false; - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1-x)*0.1; - x=x_new; - - iterations++; - } - //--- check convergence - if(iterations1.0) - { - double rnd_chisquare=MathRandomGamma((nu-1)*0.5,2.0,err_code); - double rnd_normal=MathSqrt(sigma)+MathRandomNormal(0,1,err_code); - return rnd_chisquare+rnd_normal*rnd_normal; - } - else - { - int rnd_poisson=(int)MathRandomPoisson(sigma*0.5); - return MathRandomChiSquare(nu+2*rnd_poisson,err_code); - } - } -//+------------------------------------------------------------------+ -//| Random variate from the Noncentral Chi-Square distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Noncentral Chi-Square | -//| distribution with parameters nu and sigma. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| sigma : Noncentrality parameter | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -//| Author: Robert Kern | -//+------------------------------------------------------------------+ -bool MathRandomNoncentralChiSquare(const double nu,const double sigma,const int data_count,double &result[]) - { -//--- return ChiSquare if sigma==0 - if(sigma==0.0) - return MathRandomChiSquare(nu,data_count,result); -//--- check NaN - if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma)) - return false; -//--- check nu - if(nu!=MathRound(nu) || nu<=0) - return false; -//--- check sigma - if(sigma<0.0) - return false; - - int err_code=0; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - double rnd_chisquare=MathRandomGamma((nu-1)*0.5,2.0,err_code); - double rnd_normal=MathSqrt(sigma)+MathRandomNormal(0,1,err_code); - result[i]=rnd_chisquare+rnd_normal*rnd_normal; - } - else - { - int rnd_poisson=(int)MathRandomPoisson(sigma*0.5); - result[i]=MathRandomChiSquare(nu+2*rnd_poisson,err_code); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Noncentral Chi-Square distribution moments | -//+------------------------------------------------------------------+ -//| The function calculates 4 first moments of Noncental Chi-Square | -//| distribution with parameters nu and sigma. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| sigma : Noncentrality parameter | -//| mean : Variable for mean value (1st moment) | -//| variance : Variable for variance value (2nd moment) | -//| skewness : Variable for skewness value (3rd moment) | -//| kurtosis : Variable for kurtosis value (4th moment) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if moments calculated successfully, otherwise false. | -//+------------------------------------------------------------------+ -bool MathMomentsNoncentralChiSquare(const double nu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) - { -//--- default values - mean =QNaN; - variance=QNaN; - skewness=QNaN; - kurtosis=QNaN; -//--- check NaN - if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return false; - } -//--- check nu - if(nu!=MathRound(nu) || nu<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- calculate moments - mean =nu+sigma; - variance=2*nu+4*sigma; - skewness=2*M_SQRT2*(nu+3*sigma)*MathPow(nu+2*sigma,-1.5); - kurtosis=12*(nu+4*sigma)*MathPow(nu+2*sigma,-2); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/NoncentralF.mqh b/Include/Math/Stat/NoncentralF.mqh deleted file mode 100644 index beba9b1..0000000 --- a/Include/Math/Stat/NoncentralF.mqh +++ /dev/null @@ -1,790 +0,0 @@ -//+------------------------------------------------------------------+ -//| NoncentralF.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "F.mqh" -#include "Gamma.mqh" -#include "NoncentralBeta.mqh" - -//+------------------------------------------------------------------+ -//| Noncentral-F probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Noncentral-F distribution with parameters nu1,nu2,sigma. | -//| | -//| Arguments: | -//| x : Random variable | -//| nu1 : Numerator degrees of freedom | -//| nu2 : Denominator degrees of freedom | -//| sigma : Noncentrality parameter | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNoncentralF(const double x,const double nu1,const double nu2,const double sigma,const bool log_mode,int &error_code) - { -//--- return F if sigma==0 - if(sigma==0.0) - return MathProbabilityDensityF(x,nu1,nu2,error_code); -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check arguments - if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - if(x<=0.0) - return TailLog0(true,log_mode); -//--- factors - double nu1_half=nu1*0.5; - double nu2_half=nu2*0.5; - double nu12_half=nu1_half+nu2_half; - double lambda=sigma*0.5; - double coef_lambda=MathExp(-lambda); - double nu_coef=nu1/nu2; - double g=x*nu_coef; - double pwr_g=MathExp((nu1_half-1)*MathLog(g)); - double g1=g+1.0; - double pwr_g1=MathExp(-nu12_half*MathLog(g1)); - double pwr_lambda=1.0; - double fact_mult=1.0; -//--- initial value for recurrent calculation - double r_beta=MathBeta(nu1_half,nu2_half); -//--- direct calculation of the sum - int max_terms=100; - int j=0; - double pdf=0; - while(j0) - { - pwr_g*=g; - pwr_lambda*=lambda; - fact_mult/=j; - pwr_g1/=g1; - double jm1=j-1; - r_beta*=((nu1_half+jm1)/(nu12_half+jm1)); - } - double dp=pwr_g*pwr_g1*coef_lambda*pwr_lambda*fact_mult/r_beta; - pdf+=dp; - if(dp/(pdf+10E-10)<10E-14) - break; - j++; - } -//--- check convergence - if(j0) - { - pwr_g*=g; - pwr_lambda*=lambda; - fact_mult/=j; - pwr_g1/=g1; - double jm1=j-1; - r_beta*=((nu1_half+jm1)/(nu12_half+jm1)); - } - double dp=pwr_g*pwr_g1*coef_lambda*pwr_lambda*fact_mult/r_beta; - pdf+=dp; - if(dp/(pdf+10E-10)<10E-14) - break; - j++; - } - //--- check convergence - if(j1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - error_code=ERR_OK; - if(prob==0.0) - return 0.0; -//--- - int max_iterations=50; - int iterations=0; -//--- initial values - double h=1.0; - double h_min=10E-10; - double x=0.5; - int err_code=0; -//--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,err_code); - double cdf=MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - //--- - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - x=x_new; - - iterations++; - } -//--- check convergence - if(iterations1.0) - return false; - - if(prob==1.0) - result[i]=QPOSINF; - else - if(prob==0.0) - result[i]=0.0; - else - { - int max_iterations=50; - int iterations=0; - //--- initial values - double h=1.0; - double h_min=10E-10; - double x=0.5; - int err_code=0; - //--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,err_code); - double cdf=MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - //--- - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - x=x_new; - - iterations++; - } - //--- check convergence - if(iterations2) - mean=nu2*(nu1+sigma)/(nu1*(nu2-2)); -//--- variance - if(nu2>4) - variance=2*MathPow(nu2/nu1,2)*((nu2-2)*(nu1+2*sigma)+MathPow(nu1+sigma,2))/((nu2-4)*MathPow(nu2-2,2)); -//--- factors - double sigma_sqr=MathPow(sigma,2); - double sigma_cube=sigma_sqr*sigma; - double nu12m2=(nu1+nu2-2); - double nu2p10=(nu2+10); -//--- skewness - if(nu2>6) - { - skewness=2*M_SQRT2*MathSqrt(nu2-4); - skewness*=(nu12m2*(6*sigma_sqr+(2*nu1+nu2-2)*(3*sigma+nu1))+2*sigma_cube); - skewness/=(nu2-6); - skewness/=MathPow(nu12m2*(2*sigma+nu1)+sigma_sqr,1.5); - } -//--- kurtosis - if(nu2>8) - { - double coef=nu2p10*(MathPow(nu1,2)+nu1*(nu2-2))+4*MathPow(nu2-2,2); - kurtosis=1; - kurtosis=3*(nu2-4); - kurtosis*=(nu12m2*(coef*(4*sigma+nu1)+nu2p10*(4*sigma_cube+2*sigma_sqr*(3*nu1+2*nu2-4)))+nu2p10*MathPow(sigma,4)); - kurtosis/=(nu2-8)*(nu2-6); - kurtosis/=MathPow((nu12m2*(2*sigma+nu1)+sigma_sqr),2); - kurtosis-=3; - } -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/NoncentralT.mqh b/Include/Math/Stat/NoncentralT.mqh deleted file mode 100644 index 1cbdad7..0000000 --- a/Include/Math/Stat/NoncentralT.mqh +++ /dev/null @@ -1,1192 +0,0 @@ -//+------------------------------------------------------------------+ -//| NoncentralT.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "T.mqh" -#include "Normal.mqh" - -//+------------------------------------------------------------------+ -//| Noncentral T probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Noncentral T distribution with parameters nu and delta. | -//| | -//| Arguments: | -//| x : Random variable | -//| nu : Degrees of freedom | -//| delta : Noncentrality parameter | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNoncentralT(const double x,const double nu,const double delta,const bool log_mode,int &error_code) - { -//--- return T - if(delta==0.0) - return MathProbabilityDensityT(x,nu,error_code); -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(nu) || !MathIsValidNumber(delta)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check nu - if(nu!=MathRound(nu) || nu<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- - double nu_1=nu+1.0; - double nu_1_half=nu_1*0.5; - double log_nu=MathLog(nu); - double factor1=MathExp(-0.5*(MathLog(M_PI)+log_nu)-(delta*delta)*0.5-MathGammaLog(nu*0.5)+nu_1_half*log_nu); - - double nu_xx=nu+x*x; - double log_nu_xx=MathLog(nu_xx); - double factor2=MathExp(-nu_1_half*log_nu_xx); -//--- - const int max_terms=500; - double pwr=1.0; - double pwr_factor=x*delta*M_SQRT2; - double pwr_nuxx=1.0; - double pwr_nuxx_factor=1.0/MathSqrt(nu_xx); - double pwr_gamma=1.0; - int j=0; - double pdf=0.0; - while(j0) - { - pwr_nuxx*=pwr_nuxx_factor; - pwr_gamma/=j; - pwr*=pwr_factor; - } - double t=pwr*pwr_gamma*pwr_nuxx*MathGamma((nu_1+j)*0.5); - pdf+=t; - //--- check precision - if((t/(pdf+10E-10))<10E-20) - break; - j++; - } -//--- check convergence - if(j0) - { - pwr_nuxx*=pwr_nuxx_factor; - pwr_gamma/=j; - pwr*=pwr_factor; - } - double t=pwr*pwr_gamma*pwr_nuxx*MathGamma((nu_1+j)*0.5); - pdf+=t; - //--- check precision - if((t/(pdf+10E-10))<10E-20) - break; - j++; - } - //--- check convergence - if(j=max_iterations) - break; - } - else - { - if(error<=errtol || j>=max_iterations) - break; - } - } -//--- check convergence - if(j=max_iterations) - break; - } - else - { - if(error<=errtol || j>=max_iterations) - break; - } - } - //--- check convergence - if(j1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - if(prob==0.0 || prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - if(prob==0.0) - return QNEGINF; - else - return QPOSINF; - } -//--- coefficients for pdf and cdf - double sqr_delta_half=delta*delta*0.5; - double nu_half=nu*0.5; - double log_sqr_delta_half=MathLog(sqr_delta_half); - double exp_sqr_delta_half=MathExp(-sqr_delta_half); - double sqrt_sqr_delta_half=MathSqrt(sqr_delta_half); - double nu_1=nu+1.0; - double nu_1_half=nu_1*0.5; - double log_nu=MathLog(nu); - double factor1=MathExp(-0.5*(MathLog(M_PI)+log_nu)-sqr_delta_half-MathGammaLog(nu*0.5)+nu_1_half*log_nu); - -//--- probability for -delta - int err_code=0; - double p0=MathCumulativeDistributionNormal(-delta,0.0,1.0,err_code); -//--- - error_code=ERR_OK; - double precision=10E-20; - const int max_iterations=150; - int iterations=0; - double x=0.5; - double h=1.0; - double h_min=precision; - const int max_terms=500; -//--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - - //--- calculate pdf - double x_arg_sqr=x*x; - double nu_xx=nu+x_arg_sqr; - double log_nu_xx=MathLog(nu_xx); - double factor2=MathExp(-nu_1_half*log_nu_xx); - double pwr=1.0; - double pwr_factor=x*delta*M_SQRT2; - double pwr_nuxx=1.0; - double pwr_nuxx_factor=1.0/MathSqrt(nu_xx); - double pwr_gamma=1.0; - int j=0; - double pdf=0.0; - while(j0) - { - pwr_nuxx*=pwr_nuxx_factor; - pwr_gamma/=j; - pwr*=pwr_factor; - } - double t=pwr*pwr_gamma*pwr_nuxx*MathGamma((nu_1+j)*0.5); - pdf+=t; - //--- check precision - if((t/(pdf+10E-10))<10E-20) - break; - j++; - } - //--- check convergence - if(j>max_terms) - return false; - pdf=factor1*factor2*pdf; - - //--- calculate cdf - double t=(x*x)/(nu+x*x); - double sum1 = 0.0; - double sum2 = 0.0; - //--- - double pwr_coef1=1.0; - double pwr_coef2=1.0; - double fact=1.0; - j=0; - if(x!=0) - { - while(j0) - { - pwr_coef1*=sqrt_sqr_delta_half; - pwr_coef2*=sqr_delta_half; - fact/=j; - } - double coef=1.0/MathGamma(j*0.5+1.0); - //--- term1: t between 0 and x - double t1=pwr_coef1*coef*MathBetaIncomplete(t,(j+1.0)*0.5,nu_half); - sum1+=t1; - //--- term2: t between x and -x - double t2=pwr_coef2*fact*MathBetaIncomplete(t,(j+0.5),nu_half); - sum2+=t2; - //--- check precision - if((MathAbs(t1/(sum1+10E-10))max_terms) - return false; - - //--- compute probability for positive x - double cdf=p0+exp_sqr_delta_half*sum1*0.5; - //--- compute probability for negative x - if(x<0) - cdf=cdf-exp_sqr_delta_half*sum2; - //--- take into account round-off errors for probability - cdf=MathMin(cdf,1.0); - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - if(MathAbs(x_new-x)<10E-15) - break; - - x=x_new; - iterations++; - } -//--- check convergence - if(iterations1.0) - return false; - - if(prob==0.0 || prob==1.0) - { - if(prob==0.0) - result[i]=QNEGINF; - else - result[i]=QPOSINF; - } - else - { - double x=0.5; - double h=1.0; - int iterations=0; - //--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - - //--- calculate pdf and cdf - //double cdf=MathCumulativeDistributionNoncentralT(x,nu,delta,err_code); - //double pdf=MathProbabilityDensityNoncentralT(x,nu,delta,err_code); - - //--- calculate pdf - double x_arg_sqr=x*x; - double nu_xx=nu+x_arg_sqr; - double log_nu_xx=MathLog(nu_xx); - double factor2=MathExp(-nu_1_half*log_nu_xx); - double pwr=1.0; - double pwr_factor=x*delta*M_SQRT2; - double pwr_nuxx=1.0; - double pwr_nuxx_factor=1.0/MathSqrt(nu_xx); - double pwr_gamma=1.0; - int j=0; - double pdf=0.0; - while(j0) - { - pwr_nuxx*=pwr_nuxx_factor; - pwr_gamma/=j; - pwr*=pwr_factor; - } - double t=pwr*pwr_gamma*pwr_nuxx*MathGamma((nu_1+j)*0.5); - pdf+=t; - //--- check precision - if((t/(pdf+10E-10))<10E-20) - break; - j++; - } - //--- check convergence - if(j>max_terms) - return false; - - pdf=factor1*factor2*pdf; - - //--- calculate cdf - double t=(x*x)/(nu+x*x); - double sum1 = 0.0; - double sum2 = 0.0; - //--- - double pwr_coef1=1.0; - double pwr_coef2=1.0; - double fact=1.0; - j=0; - if(x!=0) - { - while(j0) - { - pwr_coef1*=sqrt_sqr_delta_half; - pwr_coef2*=sqr_delta_half; - fact/=j; - } - double coef=1.0/MathGamma(j*0.5+1.0); - //--- term1: t between 0 and x - double t1=pwr_coef1*coef*MathBetaIncomplete(t,(j+1.0)*0.5,nu_half); - sum1+=t1; - //--- term2: t between x and -x - double t2=pwr_coef2*fact*MathBetaIncomplete(t,(j+0.5),nu_half); - sum2+=t2; - //--- check precision - if((MathAbs(t1/(sum1+10E-10))max_terms) - return false; - - //--- compute probability for positive x - double cdf=p0+exp_sqr_delta_half*sum1*0.5; - //--- compute probability for negative x - if(x<0) - cdf=cdf-exp_sqr_delta_half*sum2; - //--- take into account round-off errors for probability - cdf=MathMin(cdf,1.0); - - //--- calculate ratio - h=(cdf-prob)/pdf; - - double x_new=x-h; - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - if(MathAbs(x_new-x)<10E-15) - break; - - x=x_new; - iterations++; - } - //--- check convergence - if(iterations1) - mean=delta*MathSqrt(nu)*MathGamma((nu-1)*0.5)/(MathSqrt(2)*MathGamma(nu*0.5)); -//--- delta^2 - double delta_sqr=delta*delta; -//--- 1/((nu-3)*(nu-2)) - double nu32=1/((nu-3)*(nu-2)); - if(nu>2) - variance=((delta_sqr+1)*nu)/(nu-2)-MathPow(mean,2); -//--- skewness - if(nu>3) - { - skewness=-2*variance; - skewness+= nu*(delta_sqr+2*nu-3)*nu32; - skewness*= mean*MathPow(variance,-1.5); - } -//--- kurtosis - if(nu>4) - { - kurtosis=-3*variance; - kurtosis+= nu*(delta_sqr*(nu+1)+3*(3*nu-5))*nu32; - kurtosis*= -MathPow(mean,2); - kurtosis+= MathPow(nu,2)*(MathPow(delta,4)+6*delta_sqr+3)/((nu-4)*(nu-2)); - kurtosis*= MathPow(variance,-2); - kurtosis-=3; - } -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Normal.mqh b/Include/Math/Stat/Normal.mqh deleted file mode 100644 index 65fd836..0000000 --- a/Include/Math/Stat/Normal.mqh +++ /dev/null @@ -1,914 +0,0 @@ -//+------------------------------------------------------------------+ -//| Normal.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" - -const static double normal_cdf_a[5]= - { - 2.2352520354606839287E00,1.6102823106855587881E02, - 1.0676894854603709582E03,1.8154981253343561249E04, - 6.5682337918207449113E-2 - }; -const static double normal_cdf_b[4]= - { - 4.7202581904688241870E01,9.7609855173777669322E02, - 1.0260932208618978205E04,4.5507789335026729956E04 - }; -//--- coefficients for approximation in second interval -const static double normal_cdf_c[9]= - { - 3.9894151208813466764E-1,8.8831497943883759412E00, - 9.3506656132177855979E01,5.9727027639480026226E02, - 2.4945375852903726711E03,6.8481904505362823326E03, - 1.1602651437647350124E04,9.8427148383839780218E03, - 1.0765576773720192317E-8 - }; -const static double normal_cdf_d[8]= - { - 2.2266688044328115691E01,2.3538790178262499861E02, - 1.5193775994075548050E03,6.4855582982667607550E03, - 1.8615571640885098091E04,3.4900952721145977266E04, - 3.8912003286093271411E04,1.9685429676859990727E04 - }; -//--- coefficients for approximation in third interval -const static double normal_cdf_p[6]= - { - 2.1589853405795699E-1,1.274011611602473639E-1, - 2.2235277870649807E-2,1.421619193227893466E-3, - 2.9112874951168792E-5,2.307344176494017303E-2 - }; -const static double normal_cdf_q[5]= - { - 1.28426009614491121E00,4.68238212480865118E-1, - 6.59881378689285515E-2,3.78239633202758244E-3, - 7.29751555083966205E-5 - }; - -//--- coefficients for p close to 0.5 -const double normal_q_a0 = 3.3871328727963666080; -const double normal_q_a1 = 1.3314166789178437745E+2; -const double normal_q_a2 = 1.9715909503065514427E+3; -const double normal_q_a3 = 1.3731693765509461125E+4; -const double normal_q_a4 = 4.5921953931549871457E+4; -const double normal_q_a5 = 6.7265770927008700853E+4; -const double normal_q_a6 = 3.3430575583588128105E+4; -const double normal_q_a7 = 2.5090809287301226727E+3; -const double normal_q_b1 = 4.2313330701600911252E+1; -const double normal_q_b2 = 6.8718700749205790830E+2; -const double normal_q_b3 = 5.3941960214247511077E+3; -const double normal_q_b4 = 2.1213794301586595867E+4; -const double normal_q_b5 = 3.9307895800092710610E+4; -const double normal_q_b6 = 2.8729085735721942674E+4; -const double normal_q_b7 = 5.2264952788528545610E+3; -//--- coefficients for p not close to 0, 0.5 or 1 -const double normal_q_c0 = 1.42343711074968357734; -const double normal_q_c1 = 4.63033784615654529590; -const double normal_q_c2 = 5.76949722146069140550; -const double normal_q_c3 = 3.64784832476320460504; -const double normal_q_c4 = 1.27045825245236838258; -const double normal_q_c5 = 2.41780725177450611770E-1; -const double normal_q_c6 = 2.27238449892691845833E-2; -const double normal_q_c7 = 7.74545014278341407640E-4; -const double normal_q_d1 = 2.05319162663775882187; -const double normal_q_d2 = 1.67638483018380384940; -const double normal_q_d3 = 6.89767334985100004550E-1; -const double normal_q_d4 = 1.48103976427480074590E-1; -const double normal_q_d5 = 1.51986665636164571966E-2; -const double normal_q_d6 = 5.47593808499534494600E-4; -const double normal_q_d7 = 1.05075007164441684324E-9; -//--- coefficients for p near 0 or 1. -const double normal_q_e0 = 6.65790464350110377720E0; -const double normal_q_e1 = 5.46378491116411436990E0; -const double normal_q_e2 = 1.78482653991729133580E0; -const double normal_q_e3 = 2.96560571828504891230E-1; -const double normal_q_e4 = 2.65321895265761230930E-2; -const double normal_q_e5 = 1.24266094738807843860E-3; -const double normal_q_e6 = 2.71155556874348757815E-5; -const double normal_q_e7 = 2.01033439929228813265E-7; -const double normal_q_f1 = 5.99832206555887937690E-1; -const double normal_q_f2 = 1.36929880922735805310E-1; -const double normal_q_f3 = 1.48753612908506148525E-2; -const double normal_q_f4 = 7.86869131145613259100E-4; -const double normal_q_f5 = 1.84631831751005468180E-5; -const double normal_q_f6 = 1.42151175831644588870E-7; -const double normal_q_f7 = 2.04426310338993978564E-15; -//+------------------------------------------------------------------+ -//| Normal probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Normal distribution with parameters mu and sigma. | -//| | -//| Arguments: | -//| x : Random variable | -//| mu : Mean | -//| sigma : Standard deviation (sigma>0) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - -//--- prepare argument - double y=(x-mu)/sigma; -//--- check it - if(!MathIsValidNumber(y)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check overflow - y=MathAbs(y); - if(y>=2*MathSqrt(DBL_MAX)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- return density - return TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode); - } -//+------------------------------------------------------------------+ -//| Normal probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Normal distribution with parameters mu and sigma. | -//| | -//| Arguments: | -//| x : Random variable | -//| mu : Mean | -//| sigma : Standard deviation (sigma>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,int &error_code) - { - return MathProbabilityDensityNormal(x,mu,sigma,false,error_code); - } -//+------------------------------------------------------------------+ -//| Normal probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Normal distribution with parameters mu and sigma | -//| for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| sigma : Standard deviation (sigma>0) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - - for(int i=0; i=2*MathSqrt(DBL_MAX)) - return false; - - //--- calculate density - result[i]=TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode); - } - return true; - } -//+------------------------------------------------------------------+ -//| Normal probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Normal distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| sigma : Standard deviation (sigma>0) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,double &result[]) - { - return MathProbabilityDensityNormal(x,mu,sigma,false,result); - } -//+------------------------------------------------------------------+ -//| Normal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Normal distribution with parameters mu and sigma | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Normal cumulative distribution function with | -//| parameters mu and sigma, evaluated at x. | -//+------------------------------------------------------------------+ -//| Comment from original FORTRAN code | -//| http://www.netlib.org/toms-2014-06-10/639 | -//| http://www.netlib.org/toms-2014-06-10/715 | -//| | -//| This function evaluates the normal distribution function: | -//| | -//| / x | -//| 1 | -t*t/2 | -//| P(x) = ----------- | e dt | -//| sqrt(2 pi) | | -//| /-oo | -//| | -//| The main computation evaluates near-minimax approximations | -//| derived from those in "Rational Chebyshev approximations for | -//| the error function" by W. J. Cody, Math. Comp., 1969, 631-637. | -//| This transportable program uses rational functions that | -//| theoretically approximate the normal distribution function to | -//| at least 18 significant decimal digits. The accuracy achieved | -//| depends on the arithmetic system, the compiler, the intrinsic | -//| functions, and proper selection of the machine-dependent | -//| constants. | -//| | -//| Author: | -//| W. J. Cody, Mathematics and Computer Science Division | -//| Argonne National Laboratory, Argonne, IL 60439 | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- prepare argument - double xx=(x-mu)/sigma; -//--- mathematical constants -//--- sqrpi = 1 / sqrt(2*pi), root32 = sqrt(32), and -//--- thrsh is the argument for which anorm = 0.75. - const double sqrpi=1.0/MathSqrt(2*M_PI); - const double thrsh = 0.66291e0; - const double root32= MathSqrt(32); -//--- machine-dependent constants -//--- data eps/5.96e-8/,xlow/-12.949e0/,xuppr/5.768e0/ - const double eps=1.11e-16; - const double xlow=-37.519; - const double xuppr=8.572; - int k; -//--- - double xsq=0.0; - double y=MathAbs(xx); - double xnum=0.0; - double xden=0.0; - double cdf=0.0; - double del=0.0; -//--- - if(y<=thrsh) - { - //--- evaluate for |x| <= 0.66291 - if(y>eps) - xsq=xx*xx; - - xnum = normal_cdf_a[4] * xsq; - xden = xsq; - for(k=0; k<3; k++) - { - xnum=(xnum+normal_cdf_a[k])*xsq; - xden=(xden+normal_cdf_b[k])*xsq; - } - cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]); - cdf = 0.5 + cdf; - } - else - if(y<=root32) - { - //--- evaluate for 0.66291 <= |x| <= sqrt(32) - xnum = normal_cdf_c[8]*y; - xden = y; - for(k=0; k<7; k++) - { - xnum=(xnum+normal_cdf_c[k])*y; - xden=(xden+normal_cdf_d[k])*y; - } - cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]); - xsq=int(y*16)/16; - del=(y-xsq)*(y+xsq); - cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf; - if(xx>0.0) cdf=1.0-cdf; - } -//--- evaluate for |x| > sqrt(32) - else - { - cdf=0.0; - if((xx>=xlow) && (xx0.0) cdf=1.0-cdf; - } -//--- take into account round-off errors for probability - return TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Normal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Normal distribution with parameters mu and sigma | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Normal cumulative distribution function with | -//| parameters mu and sigma, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,int &error_code) - { - return MathCumulativeDistributionNormal(x,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Normal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Normal distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; ieps) - xsq=xx*xx; - - xnum = normal_cdf_a[4] * xsq; - xden = xsq; - for(k=0; k<3; k++) - { - xnum=(xnum+normal_cdf_a[k])*xsq; - xden=(xden+normal_cdf_b[k])*xsq; - } - cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]); - cdf = 0.5 + cdf; - } - else - if(y<=root32) - { - //--- evaluate for 0.66291 <= |x| <= sqrt(32) - xnum = normal_cdf_c[8]*y; - xden = y; - for(k=0; k<7; k++) - { - xnum=(xnum+normal_cdf_c[k])*y; - xden=(xden+normal_cdf_d[k])*y; - } - cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]); - xsq=int(y*16)/16; - del=(y-xsq)*(y+xsq); - cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf; - if(xx>0.0) cdf=1.0-cdf; - } - //--- evaluate for |x| > sqrt(32) - else - { - cdf=0.0; - if((xx>=xlow) && (xx0.0) cdf=1.0-cdf; - } - //--- take into account round-off errors for probability - result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } - return true; - } -//+------------------------------------------------------------------+ -//| Normal cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Normal distribution with parameters mu and sigma | -//| for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,double &result[]) - { - return MathCumulativeDistributionNormal(x,mu,sigma,true,false,result); - } -//+------------------------------------------------------------------+ -//| Normal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Normal distribution with parameters mu and sigma | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Normal distribution with parameters mu and sigma. | -//+------------------------------------------------------------------+ -//| Comment from original FORTRAN code | -//| http://www1.fpl.fs.fed.us/ni241.f | -//| Produces the normal deviate Z corresponding to a given lower | -//| tail area of P; Z is accurate to about 1 part in 10**16. | -//| Wichura, M.J. (1988). Algorithm AS 241: The Percentage Points of | -//| the Normal Distribution. Applied Statistics, v.37, N3, 477-484. | -//+------------------------------------------------------------------+ -double MathQuantileNormal(const double probability,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- f(0)=-infinity - if(prob==0.0) - { - error_code=ERR_RESULT_INFINITE; - return QNEGINF; - } -//--- f(1)=+infinity - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - - error_code=ERR_OK; - - double q=prob-0.5; - double r=0; - double ppnd16=0.0; -//--- - if(MathAbs(q)<=0.425) - { - r=0.180625-q*q; - ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/ - (((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0); - //--- - error_code=ERR_OK; - return mu+sigma*ppnd16; - } - else - { - if(q<0.0) - r=prob; - else - r=1.0-prob; - //--- - r=MathSqrt(-MathLog(r)); - //--- - if(r<=5.0) - { - r=r-1.6; - ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/ - (((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0); - } - else - { - r=r-5.0; - ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/ - (((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0); - } - //--- - if(q<0.0) - ppnd16=-ppnd16; - } -//--- return rescaled/shifted value - return mu+sigma*ppnd16; - } -//+------------------------------------------------------------------+ -//| Normal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of Normal distribution with parameters mu and sigma | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Normal distribution with parameters mu and sigma. | -//+------------------------------------------------------------------+ -double MathQuantileNormal(const double probability,const double mu,const double sigma,int &error_code) - { - return MathQuantileNormal(probability,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Normal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Normal distribution with parameters mu and sigma | -//| for the probability values from array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - -//--- case sigma==0 - if(sigma==0.0) - { - for(int i=0; i1.0) - return false; - - //--- f(0)=-infinity, f(1)=+infinity - if(prob==0.0 || prob==1.0) - { - if(prob==0.0) - result[i]=QNEGINF; - else - result[i]=QPOSINF; - } - else - { - double q=prob-0.5; - double r=0; - double ppnd16=0.0; - //--- - if(MathAbs(q)<=0.425) - { - r=0.180625-q*q; - ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/ - (((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0); - //--- set rescaled/shifted value - result[i]=mu+sigma*ppnd16; - } - else - { - if(q<0.0) - r=prob; - else - r=1.0-prob; - //--- - r=MathSqrt(-MathLog(r)); - //--- - if(r<=5.0) - { - r=r-1.6; - ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/ - (((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0); - } - else - { - r=r-5.0; - ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/ - (((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0); - } - //--- - if(q<0.0) - ppnd16=-ppnd16; - } - //--- set rescaled/shifted value - result[i]=mu+sigma*ppnd16; - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Normal distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Normal distribution with parameters mu and sigma | -//| for the probability values from array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,double &result[]) - { - return MathQuantileNormal(probability,mu,sigma,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Normal distribution | -//+------------------------------------------------------------------+ -//| Compute the random variable from the Normal distribution | -//| with given mean mu and standard deviation sigma. | -//| | -//| Arguments: | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Normal distribution. | -//+------------------------------------------------------------------+ -double MathRandomNormal(const double mu,const double sigma,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check sigma - if(sigma<0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- - if(sigma==0.0) - return mu; -//--- generate random number - double rnd=MathRandomNonZero(); -//--- return normal random using quantile - return MathQuantileNormal(rnd,mu,sigma,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Random variate from the Normal distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Normal distribution with | -//| parameters mu and sigma. | -//| | -//| Arguments: | -//| mu : Mean | -//| sigma : Standard deviation (must be positive) | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomNormal(const double mu,const double sigma,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - return false; -//--- check sigma - if(sigma<0) - return false; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - if(sigma==0.0) - { - for(int i=0; i0) | -//| mean : Variable for mean value (1st moment) | -//| variance : Variable for variance value (2nd moment) | -//| skewness : Variable for skewness value (3rd moment) | -//| kurtosis : Variable for kurtosis value (4th moment) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if moments calculated successfully, otherwise false. | -//+------------------------------------------------------------------+ -bool MathMomentsNormal(const double mu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) - { -//--- default values - mean =QNaN; - variance=QNaN; - skewness=QNaN; - kurtosis=QNaN; -//--- check NaN - if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) - { - error_code=ERR_ARGUMENTS_NAN; - return false; - } -//--- check sigma - if(sigma<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- calculate moments - mean =mu; - variance=MathPow(sigma,2); - skewness=0; - kurtosis=0; -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Poisson.mqh b/Include/Math/Stat/Poisson.mqh deleted file mode 100644 index fc22b5f..0000000 --- a/Include/Math/Stat/Poisson.mqh +++ /dev/null @@ -1,791 +0,0 @@ -//+------------------------------------------------------------------+ -//| Poisson.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "Gamma.mqh" - -//+------------------------------------------------------------------+ -//| Poisson probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Poisson distribution with parameter lambda. | -//| | -//| Arguments: | -//| x : Random variable | -//| lambda : Mean | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityPoisson(const double x,const double lambda,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(lambda)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- lambda must be positive, x must be integer - if(lambda<=0.0 || x!=MathRound(x)) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x - if(x<0.0) - return TailLog0(true,log_mode); - -//--- calculate log pdf using LogGamma - double log_pdf=-lambda+x*MathLog(lambda)-MathGammaLog(x+1.0); - if(log_mode) - return log_pdf; -//--- return density - return MathExp(log_pdf); - } -//+------------------------------------------------------------------+ -//| Poisson probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability mass function | -//| of the Poisson distribution with parameter lambda. | -//| | -//| Arguments: | -//| x : Random variable | -//| lambda : Mean | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability mass evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityPoisson(const double x,const double lambda,int &error_code) - { - return MathProbabilityDensityPoisson(x,lambda,false,error_code); - } -//+------------------------------------------------------------------+ -//| Poisson probability mass function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the Poisson distribution with parameter lambda for values in x[].| -//| | -//| Arguments: | -//| x : Array with random variables | -//| lambda : Mean | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityPoisson(const double &x[],const double lambda,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(lambda)) - return false; -//--- lambda must be positive - if(lambda<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - ArrayResize(result,data_count); - for(int i=0; i1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- check - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - error_code=ERR_OK; - if(prob==0.0) - return 0.0; - - prob*=1-1000*DBL_EPSILON; - int err_code=0; - int j=0; - const int max_terms=500; - double coef_lambda=MathExp(-lambda); - double pwr_lambda=1.0; - double inverse_fact=1.0; - double sum=0; -//--- direct calculation of the quantile - while(sum0) - { - pwr_lambda*=lambda; - inverse_fact/=j; - } - sum+=coef_lambda*pwr_lambda*inverse_fact; - j++; - } -//--- check convergence - if(j1.0) - return false; - else - if(prob==1.0) - result[i]=QPOSINF; - if(prob==0.0) - result[i]=0; - else - { - prob*=1-1000*DBL_EPSILON; - int err_code=0; - int j=0; - double sum=0.0; - const int max_terms=500; - double pwr_lambda=1.0; - double inverse_fact=1.0; - //--- direct calculation - while(sum0) - { - pwr_lambda*=lambda; - inverse_fact/=j; - } - sum+=coef_lambda*pwr_lambda*inverse_fact; - j++; - } - //--- check convergence - if(j=1.0 || r2==0.0); - //--- Box-Muller transform - f=MathSqrt(-2.0*MathLog(r2)/r2); - double snorm=f*x2; - //--- normal sample - g=lambda+s*snorm; - - if(0.0<=g) - { - value=(int)(g); - //--- immediate acceptance if large enough - if(l<=value) - return value; - //--- squeeze acceptance - fk=(double)(value); - difmuk=lambda-fk; - u=MathRandomNonZero(); - //--- - if(difmuk*difmuk*difmuk<=d*u) - return value; - } - //--- preparation for steps P and Q - double omega=0.3989423/s; - double b1 = 0.04166667/lambda; - double b2 = 0.3*b1*b1; - double c3 = 0.1428571*b1*b2; - double c2 = b2 - 15.0*c3; - double c1 = b1 - 6.0*b2 + 45.0*c3; - double c0 = 1.0 - b1 + 3.0*b2 - 15.0*c3; - double c=0.1069/lambda; - double del=0; - - if(0.0<=g) - { - kflag=0; - - if(value<10) - { - px = -lambda; - py = MathPow(lambda,value)/MathFactorial(value); - } - else - { - del = 0.8333333E-01/fk; - del = del - 4.8*del*del*del; - v=difmuk/fk; - - if(0.25 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/Include/Math/Stat/T.mqh b/Include/Math/Stat/T.mqh deleted file mode 100644 index e8d4569..0000000 --- a/Include/Math/Stat/T.mqh +++ /dev/null @@ -1,654 +0,0 @@ -//+------------------------------------------------------------------+ -//| T.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" -#include "Gamma.mqh" - -//+------------------------------------------------------------------+ -//| T probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the T-distribution with parameter nu. | -//| | -//| Arguments: | -//| x : Random variable | -//| nu : Degrees of freedom | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityT(const double x,const double nu,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(nu)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check nu - if(nu!=MathRound(nu) || nu<=0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- calculate T density - double pdf=MathExp(MathGammaLog((nu+1.0)*0.5)-MathGammaLog(nu*0.5)); - pdf=pdf/(MathSqrt(nu*M_PI)*MathPow(1+x*x/nu,(nu+1.0)*0.5)); -//--- return density - return TailLogValue(pdf,true,log_mode); - } -//+------------------------------------------------------------------+ -//| T probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the T-distribution with parameter nu. | -//| | -//| Arguments: | -//| x : Random variable | -//| nu : Degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityT(const double x,const double nu,int &error_code) - { - return MathProbabilityDensityT(x,nu,false,error_code); - } -//+------------------------------------------------------------------+ -//| T probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of | -//| the T distribution with parameter nu for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| nu : Degrees of freedom | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityT(const double &x[],const double nu,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu)) - return false; -//--- check nu - if(nu!=MathRound(nu) || nu<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0.0) - cdf=1.0-cdf; -//--- take into account round-off errors for probability - return TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } -//+------------------------------------------------------------------+ -//| T cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation from | -//| T-distribution with parameter nu is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| nu : Degrees of freedom | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of T cumulative distribution function with parameter | -//| nu, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionT(const double x,const double nu,int &error_code) - { - return MathCumulativeDistributionT(x,nu,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| T cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the T distribution with parameter nu for values in x. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| nu : Degrees of freedom | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionT(const double &x[],const double nu,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu)) - return false; -//--- check nu (must be positive integer) - if(nu!=MathRound(nu) || nu<=0.0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0.0) - cdf=1.0-cdf; - //--- take into account round-off errors for probability - result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| T cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the T distribution with parameter nu for values in x[] array. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| nu : Degrees of freedom | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionT(const double &x[],const double nu,double &result[]) - { - return MathCumulativeDistributionT(x,nu,true,false,result); - } -//+------------------------------------------------------------------+ -//| T distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the T distribution with parameter nu for the desired | -//| probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| nu : Degrees of freedom | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the T-distribution with parameter nu. | -//+------------------------------------------------------------------+ -double MathQuantileT(const double probability,const double nu,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(probability) || !MathIsValidNumber(nu)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check nu - if(nu!=MathRound(nu) || nu<0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- check cases when probability==0 or 1 - if(prob==0.0 || prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - //--- - if(prob==0.0) - return(QNEGINF); - else - return(QPOSINF); - } - - error_code=ERR_OK; -//--- special case nu=1 - if(nu==1.0) - return MathTan(M_PI*(prob-0.5)); -//--- special case - if(prob==0.5) - return 0.0; -//--- - int max_iterations=50; - int iterations=0; -//--- initial values - double h=1.0; - double h_min=10E-20; - double x=0.5; - int err_code=0; -//--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityT(x,nu,err_code); - double cdf=MathCumulativeDistributionT(x,nu,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - //--- - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - x=x_new; - - iterations++; - } -//--- check convergence - if(iterations1.0) - return false; - - //--- special case p=0.5 - if(prob==0.5) - result[i]=0.0; - else - if(prob==0.0) - result[i]=QNEGINF; - else - if(prob==1.0) - result[i]=QPOSINF; - else - { - //--- special case nu=1 - if(nu==1.0) - result[i]=MathTan(M_PI*(prob-0.5)); - else - { - int max_iterations=50; - int iterations=0; - //--- initial values - double h=1.0; - double h_min=10E-18; - double x=0.5; - int err_code=0; - //--- Newton iterations - while(iterationsh_min && MathAbs(h)>MathAbs(h_min*x))==false) - break; - //--- calculate pdf and cdf - double pdf=MathProbabilityDensityT(x,nu,err_code); - double cdf=MathCumulativeDistributionT(x,nu,err_code); - //--- calculate ratio - h=(cdf-prob)/pdf; - //--- - double x_new=x-h; - //--- check x - if(x_new<0.0) - x_new=x*0.1; - else - if(x_new>1.0) - x_new=1.0-(1.0-x)*0.1; - - if (MathAbs(x_new-x)<10E-15) - break; - - x=x_new; - - iterations++; - } - //--- check convergence - if(iterations=1.0 || r2==0.0); -//--- generate normal and gamma random variables - double rnd_normal=x2*MathSqrt(-2.0*MathLog(r2)/r2); - double rnd_gamma=MathRandomGamma(nu*0.5,1,error_code); -//--- calculate ratio - double result=0; - if(rnd_gamma!=0) - result=MathSqrt(nu*0.5)*rnd_normal/MathSqrt(rnd_gamma); - return(result); - } -//+------------------------------------------------------------------+ -//| Random variate from the T distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the T distribution with | -//| parameter nu. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomT(const double nu,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(nu)) - return false; -//--- check arguments - if(nu!=MathRound(nu) || nu<=0.0) - return false; - - int error_code=0; -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i=1.0 || r2==0.0); - //--- generate normal and gamma random variables - double rnd_normal=x2*MathSqrt(-2.0*MathLog(r2)/r2); - double rnd_gamma=MathRandomGamma(nu*0.5,1,error_code); - //--- calculate ratio - double rnd=0; - if(rnd_gamma!=0) - rnd=MathSqrt(nu*0.5)*rnd_normal/MathSqrt(rnd_gamma); - result[i]=rnd; - } - return true; - } -//+------------------------------------------------------------------+ -//| T distribution moments | -//+------------------------------------------------------------------+ -//| The function calculates 4 first moments of the T distribution | -//| with parameter nu. | -//| | -//| Arguments: | -//| nu : Degrees of freedom | -//| mean : Variable for mean value (1st moment) | -//| variance : Variable for variance value (2nd moment) | -//| skewness : Variable for skewness value (3rd moment) | -//| kurtosis : Variable for kurtosis value (4th moment) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if moments calculated successfully, otherwise false. | -//+------------------------------------------------------------------+ -double MathMomentsT(const double nu,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) - { -//--- default values - mean =QNaN; - variance=QNaN; - skewness=QNaN; - kurtosis=QNaN; -//--- check NaN - if(!MathIsValidNumber(nu)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check nu - if(nu!=MathRound(nu) || nu<0.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- calculate moments - mean=0; - if(nu>2) - variance=nu/(nu-2); - skewness=0; - if(nu>4) - kurtosis=6/(nu-4); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/Math/Stat/Uniform.mqh b/Include/Math/Stat/Uniform.mqh deleted file mode 100644 index 98d1a17..0000000 --- a/Include/Math/Stat/Uniform.mqh +++ /dev/null @@ -1,539 +0,0 @@ -//+------------------------------------------------------------------+ -//| Uniform.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Math.mqh" - -//+------------------------------------------------------------------+ -//| Uniform probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of the | -//| Uniform distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : Random variable | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityUniform(const double x,const double a,const double b,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check range - if(b<=a) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check ranges - if(x>=a && x<=b) - return TailLogValue(1.0/(b-a),true,log_mode); -//--- otherwise 0 - return TailLog0(true,log_mode); - } -//+------------------------------------------------------------------+ -//| Uniform probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function of the | -//| Uniform distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : Random variable | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityUniform(const double x,const double a,const double b,int &error_code) - { - return MathProbabilityDensityUniform(x,a,b,false,error_code); - } -//+------------------------------------------------------------------+ -//| Uniform probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of the | -//| Uniform distribution with parameters a and b for values in x[]. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityUniform(const double &x[],const double a,const double b,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check range - if(b<=a) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i=a && x_arg<=b) - result[i]=TailLogValue(1.0/(b-a),true,log_mode); - else - result[i]=TailLog0(true,log_mode); - } - return true; - } -//+------------------------------------------------------------------+ -//| Uniform probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of the | -//| Uniform distribution with parameters a and b for values in x[]. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| mu : Mean | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityUniform(const double &x[],const double a,const double b,double &result[]) - { - return MathProbabilityDensityUniform(x,a,b,false,result); - } -//+------------------------------------------------------------------+ -//| Uniform cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function | -//| of the Uniform distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Uniform cumulative distribution function with | -//| parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionUniform(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check ranges - if(b=a && x<=b) - return TailLogValue(MathMin((x-a)/(b-a),1.0),tail,log_mode); - - if(x>b) - return TailLog1(tail,log_mode); - return TailLog0(tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Uniform cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the cumulative distribution function of | -//| the Uniform distribution with parameters a and b. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Uniform cumulative distribution function with | -//| parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionUniform(const double x,const double a,const double b,int &error_code) - { - return MathCumulativeDistributionUniform(x,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Uniform cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Uniform distribution with parameters a and b for values in x.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Mean | -//| b : Scale | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode flag,if true it calculates Log values| -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionUniform(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check ranges - if(b=a && x_arg<=b) - result[i]=TailLogValue(MathMin((x_arg-a)/(b-a),1.0),tail,log_mode); - else - { - if(x_arg>b) - result[i]=TailLog1(tail,log_mode); - else - result[i]=TailLog0(tail,log_mode); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Uniform cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Uniform distribution with parameters a and b for values in x.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Mean | -//| b : Scale | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionUniform(const double &x[],const double a,const double b,double &result[]) - { - return MathCumulativeDistributionUniform(x,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Uniform distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Uniform distribution with parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of Uniform distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileUniform(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { - if(log_mode==true) - { - if(probability==QNEGINF) - return 0.0; - } -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check bounds - if(b1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; - - if(prob==0.0) - return a; - else - if(prob==1.0) - return b; - -//--- return quantile - return a+prob*(b-a); - } -//+------------------------------------------------------------------+ -//| Uniform distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Uniform distribution with parameters a and b | -//| for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of Uniform distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileUniform(const double probability,const double a,const double b,int &error_code) - { - return MathQuantileUniform(probability,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Uniform distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of Uniform distribution with parameters a and b | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileUniform(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check parameters - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- check ranges - if(b1.0) - return false; - - //--- check bounds - if(b==a) - result[i]=a; - else - if(prob==0.0) - result[i]=a; - else - if(prob==1.0) - result[i]=b; - else - //--- quantile - result[i]=(a+prob*(b-a)); - } - } - return true; - } -//+------------------------------------------------------------------+ -//| Uniform distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of Uniform distribution with parameters a and b | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileUniform(const double &probability[],const double a,const double b,double &result[]) - { - return MathQuantileUniform(probability,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Uniform distribution | -//+------------------------------------------------------------------+ -//| Computes the random variable from the Uniform distribution | -//| with parameters a and b. | -//| | -//| Arguments: | -//| a : Lower endpoint (minimum) | -//| b : Upper endpoint (maximum) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with uniform distribution. | -//+------------------------------------------------------------------+ -double MathRandomUniform(const double a,const double b,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- check upper bound - if(b0) | -//| b : Scale parameter of the distribution (b>0) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityWeibull(const double x,const double a,const double b,const bool log_mode,int &error_code) - { -//--- f(-infinity)=f(infinity)=0 - if(x==QPOSINF || x==QNEGINF) - { - error_code=ERR_OK; - return TailLog0(true,log_mode); - } -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x - if(x<=0) - return TailLog0(true,log_mode); -//--- calculate factor - double pwr=MathPow(x/b,a-1); - double pdf=(a/b)*pwr*MathExp(-(x/b)*pwr); - if(log_mode==true) - return MathLog(pdf); -//--- return density - return pdf; - } -//+------------------------------------------------------------------+ -//| Weibull probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability density function | -//| of the Weibull distribution with parameters a and b. | -//| f(x,a,b)=[(a/b)*(x/b)^(a-1)]*exp(-(x/b)^a) | -//| Arguments: | -//| x : Random variable | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The probability density evaluated at x. | -//+------------------------------------------------------------------+ -double MathProbabilityDensityWeibull(const double x,const double a,const double b,int &error_code) - { - return MathProbabilityDensityWeibull(x,a,b,false,error_code); - } -//+------------------------------------------------------------------+ -//| Weibull probability density function (PDF) | -//+------------------------------------------------------------------+ -//| The function calculates the probability density function of the | -//| Weibull distribution with parameters a and b for values in x[]. | -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| log_mode : Logarithm mode flag, if true it returns Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityWeibull(const double &x[],const double a,const double b,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0) | -//| b : Scale parameter of the distribution (b>0) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathProbabilityDensityWeibull(const double &x[],const double a,const double b,double &result[]) - { - return MathProbabilityDensityWeibull(x,a,b,false,result); - } -//+------------------------------------------------------------------+ -//| Weibull cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Weibull distribution with parameters a and b | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Weibull cumulative distribution function | -//| F(a,b)=1-exp(-(x/b)^a) | -//| with parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionWeibull(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- f(-infinity)=0 - if(x==QNEGINF) - { - error_code=ERR_OK; - return TailLog0(tail,log_mode); - } -//--- f(+infinity)=1 - if(x==QPOSINF) - { - error_code=ERR_OK; - return TailLog1(tail,log_mode); - } -//--- check parameters - if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- check x - if(x<=0) - return TailLog0(tail,log_mode); -//--- calculate probability and take into account round-off errors - double cdf=MathMin(1.0-MathExp(-MathPow(x/b,a)),1.0); - return TailLogValue(cdf,tail,log_mode); - } -//+------------------------------------------------------------------+ -//| Weibull cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function returns the probability that an observation | -//| from the Weibull distribution with parameters a and b | -//| is less than or equal to x. | -//| | -//| Arguments: | -//| x : The desired quantile | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the Weibull cumulative distribution function | -//| F(a,b)=1-exp(-(x/b)^a) | -//| with parameters a and b, evaluated at x. | -//+------------------------------------------------------------------+ -double MathCumulativeDistributionWeibull(const double x,const double a,const double b,int &error_code) - { - return MathCumulativeDistributionWeibull(x,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Weibull cumulative distribution function (CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the cumulative distribution function of | -//| the Weibull distribution with parameters a and b for values in x.| -//| | -//| Arguments: | -//| x : Array with random variables | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionWeibull(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(x); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i0) | -//| b : Scale parameter of the distribution (b>0) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathCumulativeDistributionWeibull(const double &x[],const double a,const double b,double &result[]) - { - return MathCumulativeDistributionWeibull(x,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Weibull distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of Weibull distribution | -//| Q(p,a,b)=b*((-ln(1-p)))^(1/a) | -//| with parameters a and b for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| tail : Flag to calculate for lower tail | -//| log_mode : Logarithm mode,if true it calculates for Log values| -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Weibull distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileWeibull(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - -//--- calculate real probability - double prob=TailLogProbability(probability,tail,log_mode); -//--- check probability range - if(prob<0.0 || prob>1.0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } -//--- f(1)=+infinity - if(prob==1.0) - { - error_code=ERR_RESULT_INFINITE; - return QPOSINF; - } - - error_code=ERR_OK; -//--- f(0)=0 - if(prob==0.0) - return 0.0; -//--- return quantile - return b*MathPow(-MathLog(1.0-prob),1.0/a); - } -//+------------------------------------------------------------------+ -//| Weibull distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function returns the inverse cumulative distribution | -//| function of the Weibull distribution | -//| Q(p,a,b)=b*((-ln(1-p)))^(1/a) | -//| with parameters a and b for the desired probability. | -//| | -//| Arguments: | -//| probability : The desired probability | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The value of the inverse cumulative distribution function | -//| of the Weibull distribution with parameters a and b. | -//+------------------------------------------------------------------+ -double MathQuantileWeibull(const double probability,const double a,const double b,int &error_code) - { - return MathQuantileWeibull(probability,a,b,true,false,error_code); - } -//+------------------------------------------------------------------+ -//| Weibull distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Weibull distribution with parameters a and b | -//| for the probability values from array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| tail : Flag to calculate lower tail | -//| log_mode : Logarithm mode, if true it calculates Log values | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileWeibull(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - - int data_count=ArraySize(probability); - if(data_count==0) - return false; - - int error_code=0; - ArrayResize(result,data_count); - for(int i=0; i1.0) - return false; - - //--- f(1)=+infinity - if(prob==1.0) - result[i]=QPOSINF; - //--- f(0)=0 - if(prob==0.0) - result[i]=0.0; - else - //--- calc quantile - result[i]=b*MathPow(-MathLog(1.0-prob),1.0/a); - } - return true; - } -//+------------------------------------------------------------------+ -//| Weibull distribution quantile function (inverse CDF) | -//+------------------------------------------------------------------+ -//| The function calculates the inverse cumulative distribution | -//| function of the Weibull distribution with parameters a and b | -//| for values from the probability[] array. | -//| | -//| Arguments: | -//| probability : Array with probabilities | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| result : Array with calculated values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathQuantileWeibull(const double &probability[],const double a,const double b,double &result[]) - { - return MathQuantileWeibull(probability,a,b,true,false,result); - } -//+------------------------------------------------------------------+ -//| Random variate from the Weibull distribution | -//+------------------------------------------------------------------+ -//| Computes the random variable from the Weibull distribution | -//| with shape a and scale b. | -//| | -//| Arguments: | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| The random value with Weibull distribution. | -//+------------------------------------------------------------------+ -double MathRandomWeibull(const double a,const double b,int &error_code) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return QNaN; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return QNaN; - } - - error_code=ERR_OK; -//--- generate random number - double rnd=MathRandomNonZero(); - return b*MathPow(-MathLog(rnd),1.0/a); - } -//+------------------------------------------------------------------+ -//| Random variate from the Weibull distribution | -//+------------------------------------------------------------------+ -//| Generates random variables from the Weibull distribution with | -//| parameters a and b. | -//| | -//| Arguments: | -//| a : Shape parameter of the distribution (a>0) | -//| b : Scale parameter of the distribution (b>0) | -//| data_count : Number of values needed | -//| result : Output array with random values | -//| | -//| Return value: | -//| true if successful, otherwise false. | -//+------------------------------------------------------------------+ -bool MathRandomWeibull(const double a,const double b,const int data_count,double &result[]) - { -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - return false; -//--- a and b must be positive - if(a<=0 || b<=0) - return false; - -//--- prepare output array and calculate random values - ArrayResize(result,data_count); - for(int i=0; i0) | -//| b : Scale parameter of the distribution (b>0) | -//| mean : Variable for mean value (1st moment) | -//| variance : Variable for variance value (2nd moment) | -//| skewness : Variable for skewness value (3rd moment) | -//| kurtosis : Variable for kurtosis value (4th moment) | -//| error_code : Variable for error code | -//| | -//| Return value: | -//| true if moments calculated successfully, otherwise false. | -//+------------------------------------------------------------------+ -bool MathMomentsWeibull(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) - { -//--- default values - mean =QNaN; - variance=QNaN; - skewness=QNaN; - kurtosis=QNaN; -//--- check NaN - if(!MathIsValidNumber(a) || !MathIsValidNumber(b)) - { - error_code=ERR_ARGUMENTS_NAN; - return false; - } -//--- a and b must be positive - if(a<=0 || b<=0) - { - error_code=ERR_ARGUMENTS_INVALID; - return false; - } - - error_code=ERR_OK; -//--- Gamma function values - double g1 = MathGamma(1+1.0/a); - double g2 = MathGamma(1+2.0/a); - double g3 = MathGamma(1+3.0/a); - double g4 = MathGamma(1+4.0/a); -//--- calculate moments - mean =b*g1; - variance=b*b*g2-MathPow(g1,2); - skewness=(2*g1*g1*g1-3*g1*g2+g3)*MathPow(g2-g1*g1,-1.5); - kurtosis=(-6*MathPow(g1,4)+12*MathPow(g1,2)*g2-3*MathPow(g2,2)-4*g1*g3+g4)*MathPow(g2-g1*g1,-2); -//--- successful - return true; - } -//+------------------------------------------------------------------+ diff --git a/Include/MovingAverages.mqh b/Include/MovingAverages.mqh deleted file mode 100644 index a58bc02..0000000 --- a/Include/MovingAverages.mqh +++ /dev/null @@ -1,317 +0,0 @@ -//+------------------------------------------------------------------+ -//| MovingAverages.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| Simple Moving Average | -//+------------------------------------------------------------------+ -double SimpleMA(const int position,const int period,const double &price[]) - { - double result=0.0; -//--- check period - if(period>0 && period<=(position+1)) - { - for(int i=0; i0) - { - double pr=2.0/(period+1.0); - result=price[position]*pr+prev_value*(1-pr); - } - - return(result); - } -//+------------------------------------------------------------------+ -//| Smoothed Moving Average | -//+------------------------------------------------------------------+ -double SmoothedMA(const int position,const int period,const double prev_value,const double &price[]) - { - double result=0.0; -//--- check period - if(period>0 && period<=(position+1)) - { - if(position==period-1) - { - for(int i=0; i0 && period<=(position+1)) - { - double sum =0.0; - int wsum=0; - - for(int i=period; i>0; i--) - { - wsum+=i; - sum +=price[position-i+1]*(period-i+1); - } - - result=sum/wsum; - } - - return(result); - } -//+------------------------------------------------------------------+ -//| Simple moving average on price array | -//+------------------------------------------------------------------+ -int SimpleMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[]) - { -//--- check period - if(period<=1 || period>(rates_total-begin)) - return(0); -//--- save as_series flags - bool as_series_price=ArrayGetAsSeries(price); - bool as_series_buffer=ArrayGetAsSeries(buffer); - - ArraySetAsSeries(price,false); - ArraySetAsSeries(buffer,false); -//--- calculate start position - int start_position; - - if(prev_calculated==0) // first calculation or number of bars was changed - { - //--- set empty value for first bars - start_position=period+begin; - - for(int i=0; i(rates_total-begin)) - return(0); -//--- save and clear 'as_series' flags - bool as_series_price=ArrayGetAsSeries(price); - bool as_series_buffer=ArrayGetAsSeries(buffer); - - ArraySetAsSeries(price,false); - ArraySetAsSeries(buffer,false); -//--- calculate start position - int start_position; - double smooth_factor=2.0/(1.0+period); - - if(prev_calculated==0) // first calculation or number of bars was changed - { - //--- set empty value for first bars - for(int i=0; i(rates_total-begin)) - return(0); -//--- save as_series flags - bool as_series_price=ArrayGetAsSeries(price); - bool as_series_buffer=ArrayGetAsSeries(buffer); - - ArraySetAsSeries(price,false); - ArraySetAsSeries(buffer,false); -//--- calculate start position - int i,start_position; - - if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed - { - //--- set empty value for first bars - start_position=period+begin; - - for(i=0; i(rates_total-begin)) - return(0); -//--- save as_series flags - bool as_series_price=ArrayGetAsSeries(price); - bool as_series_buffer=ArrayGetAsSeries(buffer); - - ArraySetAsSeries(price,false); - ArraySetAsSeries(buffer,false); -//--- calculate start position - int start_position; - - if(prev_calculated==0) // first calculation or number of bars was changed - { - //--- set empty value for first bars - start_position=period+begin; - - for(int i=0; i(rates_total-begin)) - return(0); -//--- save as_series flags - bool as_series_price=ArrayGetAsSeries(price); - bool as_series_buffer=ArrayGetAsSeries(buffer); - - ArraySetAsSeries(price,false); - ArraySetAsSeries(buffer,false); -//--- calculate start position - int start_position; - - if(prev_calculated==0) // first calculation or number of bars was changed - { - //--- set empty value for first bars - start_position=period+begin; - - for(int i=0; i 0) + { + //Count the opened positions by type + int cntP = PositionsTotal(); + for(int i = cntP-1; i>=0; i--) + { + ticket = PositionGetTicket(i); + if(PositionSelectByTicket(ticket)) + { + if(PositionGetString(POSITION_SYMBOL)==mSymbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY + && PositionGetInteger(POSITION_MAGIC)==m_magic) + { + openedBuyPositionPrice = PositionGetDouble(POSITION_PRICE_OPEN); + pCountBuy += 1; + } + + Print("POSITION_SYMBOL ", PositionGetString(POSITION_SYMBOL), " = ", mSymbol, " POSITION_TYPE ",PositionGetInteger(POSITION_TYPE), " = ", POSITION_TYPE_SELL, " Magic ", PositionGetInteger(POSITION_MAGIC), " = ",m_magic); + if(PositionGetString(POSITION_SYMBOL)==mSymbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL + && PositionGetInteger(POSITION_MAGIC)==m_magic) + { + openedSellPositionPrice = PositionGetDouble(POSITION_PRICE_OPEN); + pCountSell += 1; + } + } + else + { + Print(GetLastError()); + } + } + } +//Count the orders by type + + int cntO = OrdersTotal(); + Print("Total pending orders ", cntO); + for(int i = cntO-1; i>=0; i--) + { + ticket = OrderGetTicket(i); + if(OrderSelect(ticket)) + { + if(OrderGetString(ORDER_SYMBOL)==mSymbol && OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP + && OrderGetInteger(ORDER_MAGIC)==m_magic) + { + oCountBuy += 1; + lastBuyOrderPrice = OrderGetDouble(ORDER_PRICE_OPEN); + } + + Print("ORDER_SYMBOL ", OrderGetString(ORDER_SYMBOL), " Real symbol ", mSymbol, " ORDER_TYPE ", OrderGetInteger(ORDER_TYPE), " Real type ", ORDER_TYPE_SELL_STOP, " Magic ", OrderGetInteger(ORDER_MAGIC), " Real magic ", m_magic); + if(OrderGetString(ORDER_SYMBOL)==mSymbol && OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP + && OrderGetInteger(ORDER_MAGIC)==m_magic) + { + oCountSell += 1; + lastSellOrderPrice = OrderGetDouble(ORDER_PRICE_OPEN); + } + } + else + { + Print(GetLastError()); + } + } + Print("openedBuyPositionPrice ", openedBuyPositionPrice, " openedSellPositionPrice ", openedSellPositionPrice); + + Print("lastBuyOrderPrice ", lastBuyOrderPrice, " lastSellOrderPrice ", lastSellOrderPrice); + + double floatingProfitPercent = ((AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE))*100)/AccountInfoDouble(ACCOUNT_BALANCE); +// Check if profit is at least the mMaxRiskPerTrade + + Print(" MaxRiskPerTrade ",mMaxRiskPerTrade, " Floating profit percent ", floatingProfitPercent, " Account equity ", AccountInfoDouble(ACCOUNT_EQUITY), " Account balance ", AccountInfoDouble(ACCOUNT_BALANCE)); + +//The number of buy pending order should be twice the opened sell positions; and vice versa + realOCountBuy = pCountSell+1; + realOCountSell = pCountBuy*2; + totalBuy = pCountBuy+oCountBuy; + totalSell = pCountSell+oCountSell; + realTotalBuy = pCountSell+1; + realTotalSell = pCountBuy+1; + + Print("Sell order (", oCountSell, ") Real (", realOCountSell, ")"); + Print("Buy order (", oCountBuy, ") Real (", realOCountBuy, ")", " Opened sell ", pCountSell); + + + Print("oCountSell ", oCountSell, " < ", " realOCountSell ", realOCountSell, " && ", " pCountBuy ", pCountBuy," > 0"); + + if(OrdersTotal() == 0 && PositionsTotal() == 0) + { + SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BOTH); + } + else + { + //If there's only one pending order left, close it. + if(OrdersTotal() >= 1 && PositionsTotal() == 0) + { + SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_ALL); + Print("Exit if no opened position"); + } + else + { + //When there are multiple positions, check is the account is making enough profit + if(floatingProfitPercent > mMaxRiskPerTrade) + { + SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_ALL); + Print("Exit on profit target"); + } + else + { + Print("realTotalSell ", realTotalSell, " <= ", " totalSell ", totalSell ," && ", " pCountBuy ",pCountBuy ," > 0"); + if(realTotalSell > totalSell && pCountBuy > 0) + { + SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_SELL); + Print("Sell order (", oCountSell, ") is less than it should be (", realOCountSell, ")"); + } + else + { + if(realTotalBuy > totalBuy && pCountSell > 0) + { + SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); + //mEntrySignals[0].SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); + Print("Buy order (", oCountBuy, ") is less than it should be (", realOCountBuy, ")"); + } + } + } + } + } } //+------------------------------------------------------------------+ diff --git a/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh b/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh index 55c8d6a..1934a16 100644 --- a/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh +++ b/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh @@ -32,19 +32,11 @@ protected: double mMinLotSize; double mMaxRiskPerTrade; - - - double lastBuyOrderPrice; - double lastSellOrderPrice; - double openedBuyPositionPrice; - double openedSellPositionPrice; - - ENUM_TRADING_SESSION mUseTradingSession; ENUM_RISK_DEFAULT_SIZE mRiskDefaultSize; ENUM_RISK_BASE mRiskBase; - enum ENUM_NAV_SIGNAL_TYPE + /*enum ENUM_NAV_SIGNAL_TYPE { NAV_ENTRY_SIGNAL, NAV_EXIT_SIGNAL @@ -59,9 +51,9 @@ protected: NAV_SIGNAL_SELL = 2, NAV_SIGNAL_BOTH = 3, NAV_SIGNAL_ALL = 4 - }; + };*/ - ENUM_NAV_SIGNAL_DIRECTION signalDirection; + //ENUM_NAV_SIGNAL_DIRECTION signalDirection; datetime mLastBarTime; datetime mBarTime; @@ -163,11 +155,6 @@ public: // Setup virtual bool IsTradingTime(); virtual bool CheckTradingSession(); - virtual double getLastBuyOrderPrice() {return lastBuyOrderPrice;} - virtual double getLastSellOrderPrice() {return lastSellOrderPrice;} - virtual double getOpenedBuyPositionPrice() {return openedBuyPositionPrice;} - virtual double getOpenedSellPositionPrice() {return openedSellPositionPrice;} - ////virtual void AddEntrySignal(CSignalBase *signal) { mEntrySignal=signal; } ////virtual void AddExitSignal(CSignalBase *signal) { mExitSignal=signal; } @@ -279,8 +266,7 @@ void CExpertBase::OnTick(void) bool firstTime = (mLastBarTime==0); bool newBar = (mBarTime!=mLastBarTime); - TradeWatcher(); -Print("signalDirection after TradeWatcher ", signalDirection); + //TradeWatcher(); if(LoopMain(newBar, firstTime)) { mLastBarTime = mBarTime; @@ -311,6 +297,9 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) ////Changed ENUM_OFX_SIGNAL_DIRECTION entrySignal = GetCurrentSignal(mEntrySignals, OFX_ENTRY_SIGNAL); ENUM_OFX_SIGNAL_DIRECTION exitSignal = GetCurrentSignal(mExitSignals, OFX_EXIT_SIGNAL); + + + Print("entrySignal ", entrySignal); /*if(mEntrySignals[0]!=NULL) mEntrySignals[0].UpdateSignal(); if(mEntrySignals[0]!=mExitSignals[0]) @@ -370,9 +359,9 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) LotSize(GripPips); ////Changed - Print("Entry signal for Both ", NAV_SIGNAL_BOTH, " Entry for OFX_SIGNAL_BUY ", NAV_SIGNAL_BUY, " Actual ", signalDirection); - Print("signalDirection ", signalDirection); - if(signalDirection==NAV_SIGNAL_BOTH) + Print("Entry signal for Both ", OFX_SIGNAL_BOTH, " Entry for OFX_SIGNAL_BUY ", OFX_SIGNAL_BUY, " Actual ", entrySignal); + + if(entrySignal==OFX_SIGNAL_BOTH) { double AskPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK); double BidPrice = SymbolInfoDouble(Symbol(),SYMBOL_BID); @@ -399,11 +388,11 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) } else - if(signalDirection==NAV_SIGNAL_BUY) + if(entrySignal==OFX_SIGNAL_BUY) { //If there's a pending order, get the last order's price else get the position price Print("Trying to open a buy"); - buyPrice = getLastBuyOrderPrice()?getLastBuyOrderPrice():getOpenedBuyPositionPrice(); + buyPrice = mEntrySignals[0].getLastBuyOrderPrice()?mEntrySignals[0].getLastBuyOrderPrice():mEntrySignals[0].getOpenedBuyPositionPrice(); request.price = buyPrice+TakeProfitPoint; request.sl = 0.0; request.tp = NormalizeDouble(buyPrice + TakeProfitPoint, mDigits); @@ -412,10 +401,11 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) } else - if(signalDirection==NAV_SIGNAL_SELL) + if(entrySignal==OFX_SIGNAL_SELL) { Print("Trying to open a sell"); - sellPrice = getLastSellOrderPrice()?getLastSellOrderPrice():getOpenedSellPositionPrice(); + + sellPrice = mEntrySignals[0].getLastSellOrderPrice()?mEntrySignals[0].getLastSellOrderPrice():mEntrySignals[0].getOpenedSellPositionPrice(); request.price = sellPrice-TakeProfitPoint; request.sl = 0.0; request.tp = NormalizeDouble(sellPrice - TakeProfitPoint, mDigits); @@ -423,7 +413,7 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) Trade.SellStop(mVolume, request.price, mSymbol, request.sl); } - if(signalDirection==NAV_SIGNAL_ALL) + if(exitSignal==OFX_SIGNAL_ALL) { Trade.OrderCloseAll(); Trade.PositionCloseAll(); @@ -671,6 +661,7 @@ void CExpertBase::LotSize(double SL=0) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ +/* void CExpertBase::TradeWatcher(void) { @@ -679,7 +670,7 @@ void CExpertBase::TradeWatcher(void) int pCountBuy = 0, pCountSell = 0, oCountBuy = 0, oCountSell = 0, totalBuy = 0, totalSell = 0, realTotalBuy = 0, realTotalSell = 0; int realOCountBuy, realOCountSell; ulong ticket; - signalDirection = NAV_SIGNAL_NONE; + entrySignal = OFX_SIGNAL_NONE; //If there're many positions and account balance is negative @@ -715,7 +706,7 @@ void CExpertBase::TradeWatcher(void) } } //Count the orders by type - +/* int cntO = OrdersTotal(); Print("Total pending orders ", cntO); for(int i = cntO-1; i>=0; i--) @@ -768,14 +759,14 @@ void CExpertBase::TradeWatcher(void) if(OrdersTotal() == 0 && PositionsTotal() == 0) { - signalDirection = NAV_SIGNAL_BOTH; + signalDirection = OFX_SIGNAL_BOTH; } else { //If there's only one pending order left, close it. if(OrdersTotal() >= 1 && PositionsTotal() == 0) { - signalDirection = NAV_SIGNAL_ALL; + signalDirection = OFX_SIGNAL_ALL; Print("Exit if no opened position"); } else @@ -783,7 +774,7 @@ void CExpertBase::TradeWatcher(void) //When there are multiple positions, check is the account is making enough profit if(floatingProfitPercent > mMaxRiskPerTrade) { - signalDirection = NAV_SIGNAL_ALL; + signalDirection = OFX_SIGNAL_ALL; Print("Exit on profit target"); } else @@ -791,16 +782,16 @@ void CExpertBase::TradeWatcher(void) Print("realTotalSell ", realTotalSell, " <= ", " totalSell ", totalSell ," && ", " pCountBuy ",pCountBuy ," > 0"); if(realTotalSell > totalSell && pCountBuy > 0) { - signalType = NAV_ENTRY_SIGNAL; - signalDirection = NAV_SIGNAL_SELL; + signalType = OFX_ENTRY_SIGNAL; + signalDirection = OFX_SIGNAL_SELL; Print("Sell order (", oCountSell, ") is less than it should be (", realOCountSell, ")"); } else { if(realTotalBuy > totalBuy && pCountSell > 0) { - signalType = NAV_ENTRY_SIGNAL; - signalDirection = NAV_SIGNAL_BUY; + signalType = OFX_ENTRY_SIGNAL; + signalDirection = OFX_SIGNAL_BUY; //mEntrySignals[0].SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); Print("Buy order (", oCountBuy, ") is less than it should be (", realOCountBuy, ")"); } @@ -808,5 +799,5 @@ void CExpertBase::TradeWatcher(void) } } } - } + }*/ //+------------------------------------------------------------------+ diff --git a/Include/Object.mqh b/Include/Object.mqh deleted file mode 100644 index bc2fbd0..0000000 --- a/Include/Object.mqh +++ /dev/null @@ -1,33 +0,0 @@ -//+------------------------------------------------------------------+ -//| Object.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "StdLibErr.mqh" -//+------------------------------------------------------------------+ -//| Class CObject. | -//| Purpose: Base class for storing elements. | -//+------------------------------------------------------------------+ -class CObject - { -private: - CObject *m_prev; // previous item of list - CObject *m_next; // next item of list - -public: - CObject(void): m_prev(NULL),m_next(NULL) { } - ~CObject(void) { } - //--- methods to access protected data - CObject *Prev(void) const { return(m_prev); } - void Prev(CObject *node) { m_prev=node; } - CObject *Next(void) const { return(m_next); } - void Next(CObject *node) { m_next=node; } - //--- methods for working with files - virtual bool Save(const int file_handle) { return(true); } - virtual bool Load(const int file_handle) { return(true); } - //--- method of identifying the object - virtual int Type(void) const { return(0); } - //--- method of comparing the objects - virtual int Compare(const CObject *node,const int mode=0) const { return(0); } - }; -//+------------------------------------------------------------------+ diff --git a/Include/OpenCL/OpenCL.mqh b/Include/OpenCL/OpenCL.mqh deleted file mode 100644 index 840c1df..0000000 --- a/Include/OpenCL/OpenCL.mqh +++ /dev/null @@ -1,453 +0,0 @@ -//+------------------------------------------------------------------+ -//| OpenCL.mqh | -//| Copyright 2016-2017, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| Class for working with OpenCL | -//+------------------------------------------------------------------+ -class COpenCL - { -protected: - int m_context; - int m_program; - //--- kernel - string m_kernel_names[]; - int m_kernels[]; - int m_kernels_total; - //--- buffers - int m_buffers[]; - int m_buffers_total; - string m_device_extensions; - bool m_support_cl_khr_fp64; -public: - //--- constructor/destructor - COpenCL(); - ~COpenCL(); - //--- get handles - int GetContext(void) const { return(m_context); } - int GetProgram(void) const { return(m_program); } - int GetKernel(const int kernel_index) const; - string GetKernelName(const int kernel_index) const; - //--- global memory size - bool GetGlobalMemorySize(long &global_memory_size); - //--- check support working with double - bool SupportDouble(void) const { return(m_support_cl_khr_fp64); } - //--- initialization and shutdown - bool Initialize(const string program,const bool show_log=true); - void Shutdown(); - //--- set buffers/kernels count - bool SetBuffersCount(const int total_buffers); - bool SetKernelsCount(const int total_kernels); - //--- kernel operations - bool KernelCreate(const int kernel_index,const string kernel_name); - bool KernelFree(const int kernel_index); - //--- buffer operations - bool BufferCreate(const int buffer_index,const uint size_in_bytes,const uint flags); - bool BufferFree(const int buffer_index); - template - bool BufferFromArray(const int buffer_index,T &data[],const uint data_array_offset,const uint data_array_count,const uint flags); - template - bool BufferRead(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count); - template - bool BufferWrite(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count); - //--- set kernel arguments - template - bool SetArgument(const int kernel_index,const int arg_index,T value); - bool SetArgumentBuffer(const int kernel_index,const int arg_index,const int buffer_index); - bool SetArgumentLocalMemory(const int kernel_index,const int arg_index,const int local_memory_size); - //--- kernel execution - bool Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[]); - bool Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[],const uint &local_work_size[]); - }; -//+------------------------------------------------------------------+ -//| COpenCL class constructor | -//+------------------------------------------------------------------+ -COpenCL::COpenCL() - { - m_context=INVALID_HANDLE; - m_program=INVALID_HANDLE; - m_buffers_total=0; - m_kernels_total=0; - m_device_extensions=""; - m_support_cl_khr_fp64=false; - } -//+------------------------------------------------------------------+ -//| COpenCL class destructor | -//+------------------------------------------------------------------+ -COpenCL::~COpenCL() - { - Shutdown(); - } -//+------------------------------------------------------------------+ -//| GetKernel | -//+------------------------------------------------------------------+ -int COpenCL::GetKernel(const int kernel_index) const - { - if(m_kernels_total<=0 || kernel_index<0 || kernel_index>=m_kernels_total) - return(INVALID_HANDLE); -//--- - return m_kernels[kernel_index]; - } -//+------------------------------------------------------------------+ -//| GetKernelName | -//+------------------------------------------------------------------+ -string COpenCL::GetKernelName(const int kernel_index) const - { - if(m_kernels_total<=0 || kernel_index<0 || kernel_index>=m_kernels_total) - return(""); -//--- - return m_kernel_names[kernel_index]; - } -//+------------------------------------------------------------------+ -//| GetGlobalMemorySize | -//+------------------------------------------------------------------+ -bool COpenCL::GetGlobalMemorySize(long &global_memory_size) - { - if(m_context==INVALID_HANDLE) - return(false); - -//--- get global memory size - global_memory_size=CLGetInfoInteger(m_context,CL_DEVICE_GLOBAL_MEM_SIZE); - if(global_memory_size==-1) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Initialize | -//+------------------------------------------------------------------+ -bool COpenCL::Initialize(const string program,const bool show_log=true) - { - if((m_context=CLContextCreate(CL_USE_ANY))==INVALID_HANDLE) - { - Print("OpenCL not found. Error code=",GetLastError()); - return(false); - } -//--- check support working with doubles (cl_khr_fp64) - if(CLGetInfoString(m_context,CL_DEVICE_EXTENSIONS,m_device_extensions)) - { - string extenstions[]; - StringSplit(m_device_extensions,' ',extenstions); - m_support_cl_khr_fp64=false; - int size=ArraySize(extenstions); - for(int i=0; i=m_kernels_total) - return(false); -//--- - int kernel_handle=m_kernels[kernel_index]; - if(kernel_handle==INVALID_HANDLE || m_kernel_names[kernel_index]!=kernel_name) - { - //--- create kernel - if((kernel_handle=CLKernelCreate(m_program,kernel_name))==INVALID_HANDLE) - { - CLProgramFree(m_program); - CLContextFree(m_context); - Print("OpenCL kernel create failed. Error code=",GetLastError()); - return(false); - } - else - { - m_kernels[kernel_index]=kernel_handle; - m_kernel_names[kernel_index]=kernel_name; - } - } - return(true); - } -//+------------------------------------------------------------------+ -//| KernelFree | -//+------------------------------------------------------------------+ -bool COpenCL::KernelFree(const int kernel_index) - { -//--- check kernel index - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); - if(m_kernels[kernel_index]==INVALID_HANDLE) - return(false); -//--- free kernel handle - CLKernelFree(m_kernels[kernel_index]); - m_kernels[kernel_index]=INVALID_HANDLE; -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| BufferCreate | -//+------------------------------------------------------------------+ -bool COpenCL::BufferCreate(const int buffer_index,const uint size_in_bytes,const uint flags) - { -//--- check parameters - if(buffer_index<0 || buffer_index>=m_buffers_total) - return(false); - - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); -//--- - int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); - if(buffer_handle!=INVALID_HANDLE) - { - m_buffers[buffer_index]=buffer_handle; - return(true); - } - else - return(false); - } -//+------------------------------------------------------------------+ -//| BufferFree | -//+------------------------------------------------------------------+ -bool COpenCL::BufferFree(const int buffer_index) - { -//--- check buffer index - if(buffer_index<0 || buffer_index>=m_buffers_total) - return(false); - if(m_buffers[buffer_index]==INVALID_HANDLE) - return(false); -//--- free buffer handle - CLBufferFree(m_buffers[buffer_index]); - m_buffers[buffer_index]=INVALID_HANDLE; -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| BufferFromArray | -//+------------------------------------------------------------------+ -template -bool COpenCL::BufferFromArray(const int buffer_index,T &data[],const uint data_array_offset,const uint data_array_count,const uint flags) - { -//--- check parameters - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); - if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) - return(false); - -//--- buffer does not exists, create it - if(m_buffers[buffer_index]==INVALID_HANDLE) - { - uint size_in_bytes=data_array_count*sizeof(T); - int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); - if(buffer_handle!=INVALID_HANDLE) - { - m_buffers[buffer_index]=buffer_handle; - } - else - return(false); - } -//--- write data to OpenCL buffer - uint data_written=CLBufferWrite(m_buffers[buffer_index],data,0,data_array_offset,data_array_count); - if(data_written!=data_array_count) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| BufferRead | -//+------------------------------------------------------------------+ -template -bool COpenCL::BufferRead(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count) - { -//--- check parameters - if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) - return(false); - if(m_buffers[buffer_index]==INVALID_HANDLE) - return(false); - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); -//--- read data from OpenCL buffer - uint data_read=CLBufferRead(m_buffers[buffer_index],data,cl_buffer_offset,data_array_offset,data_array_count); - if(data_read!=data_array_count) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| BufferWrite | -//+------------------------------------------------------------------+ -template -bool COpenCL::BufferWrite(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count) - { -//--- check parameters - if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) - return(false); - if(m_buffers[buffer_index]==INVALID_HANDLE) - return(false); - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); -//--- write data to OpenCL buffer - uint data_written=CLBufferWrite(m_buffers[buffer_index],data,cl_buffer_offset,data_array_offset,data_array_count); - if(data_written!=data_array_count) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| SetArgument | -//+------------------------------------------------------------------+ -template -bool COpenCL::SetArgument(const int kernel_index,const int arg_index,T value) - { - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); - - int kernel_handle=m_kernels[kernel_index]; - if(kernel_handle==INVALID_HANDLE) - return(false); -//--- - return CLSetKernelArg(kernel_handle,arg_index,value); - } -//+------------------------------------------------------------------+ -//| SetArgumentBuffer | -//+------------------------------------------------------------------+ -bool COpenCL::SetArgumentBuffer(const int kernel_index,const int arg_index,const int buffer_index) - { - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); - if(buffer_index<0 || buffer_index>=m_buffers_total) - return(false); - if(m_buffers[buffer_index]==INVALID_HANDLE) - return(false); -//--- - return CLSetKernelArgMem(m_kernels[kernel_index],arg_index,m_buffers[buffer_index]); - } -//+------------------------------------------------------------------+ -//| SetArgumentLocalMemory | -//+------------------------------------------------------------------+ -bool COpenCL::SetArgumentLocalMemory(const int kernel_index,const int arg_index,const int local_memory_size) - { - if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) - return(false); - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); -//--- check device local memory size - long device_local_memory_size=CLGetInfoInteger(m_context,CL_DEVICE_LOCAL_MEM_SIZE); - if(local_memory_size>device_local_memory_size) - return(false); -//--- - return CLSetKernelArgMemLocal(m_kernels[kernel_index],arg_index,local_memory_size); - } -//+------------------------------------------------------------------+ -//| Execute | -//+------------------------------------------------------------------+ -bool COpenCL::Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[]) - { - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); - int kernel_handle=m_kernels[kernel_index]; - if(kernel_handle==INVALID_HANDLE) - return(false); -//--- - return CLExecute(kernel_handle,work_dim,work_offset,work_size); - } -//+------------------------------------------------------------------+ -//| Execute | -//+------------------------------------------------------------------+ -bool COpenCL::Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[],const uint &local_work_size[]) - { - if(kernel_index<0 || kernel_index>=m_kernels_total) - return(false); -//--- - return CLExecute(m_kernels[kernel_index],work_dim,work_offset,work_size,local_work_size); - } -//+------------------------------------------------------------------+ diff --git a/Include/StdLibErr.mqh b/Include/StdLibErr.mqh deleted file mode 100644 index 355bead..0000000 --- a/Include/StdLibErr.mqh +++ /dev/null @@ -1,10 +0,0 @@ -//+------------------------------------------------------------------+ -//| StdLibErr.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#define ERR_USER_INVALID_HANDLE 1 -#define ERR_USER_INVALID_BUFF_NUM 2 -#define ERR_USER_ITEM_NOT_FOUND 3 -#define ERR_USER_ARRAY_IS_EMPTY 1000 -//+------------------------------------------------------------------+ diff --git a/Include/Strings/String.mqh b/Include/Strings/String.mqh deleted file mode 100644 index adcb3d0..0000000 --- a/Include/Strings/String.mqh +++ /dev/null @@ -1,377 +0,0 @@ -//+------------------------------------------------------------------+ -//| String.mqh | -//| Copyright 2009-2013, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CString. | -//| Appointment: Class-string. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CString : public CObject - { -protected: - string m_string; - -public: - CString(void); - ~CString(void); - //--- methods access - string Str(void) const { return(m_string); }; - uint Len(void) const { return(StringLen(m_string)); }; - void Copy(string ©) const; - void Copy(CString *copy) const; - //--- methods fill - bool Fill(const short character) { return(StringFill(m_string,character)); }; - void Assign(const string str) { m_string=str; }; - void Assign(const CString *str) { m_string=str.Str(); }; - void Append(const string str); - void Append(const CString *str); - uint Insert(const uint pos,const string substring); - uint Insert(const uint pos,const CString *substring); - //--- methods compare - int Compare(const string str) const; - int Compare(const CString *str) const; - int CompareNoCase(const string str) const; - int CompareNoCase(const CString *str) const; - //--- methods prepare - string Left(const uint count) const; - string Right(const uint count) const; - string Mid(const uint pos,const uint count) const; - //--- methods truncation/deletion - int Trim(const string targets); - int TrimLeft(const string targets); - int TrimRight(const string targets); - bool Clear(void) { return(StringInit(m_string)); }; - //--- methods conversion - bool ToUpper(void) { return(StringToUpper(m_string)); }; - bool ToLower(void) { return(StringToLower(m_string)); }; - void Reverse(void); - //--- methods find - int Find(const uint start,const string substring) const; - int FindRev(const string substring) const; - uint Remove(const string substring); - uint Replace(const string substring,const string newstring); - -protected: - virtual int Compare(const CObject *node,const int mode=0) const; - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CString::CString(void) : m_string("") - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CString::~CString(void) - { - } -//+------------------------------------------------------------------+ -//| Copy the string value member to copy | -//+------------------------------------------------------------------+ -void CString::Copy(string ©) const - { - copy=m_string; - } -//+------------------------------------------------------------------+ -//| Copy the string value member to copy | -//+------------------------------------------------------------------+ -void CString::Copy(CString *copy) const - { - copy.Assign(m_string); - } -//+------------------------------------------------------------------+ -//| Add a string to the end | -//+------------------------------------------------------------------+ -void CString::Append(const string str) - { - m_string+=str; - } -//+------------------------------------------------------------------+ -//| Add a string to the end | -//+------------------------------------------------------------------+ -void CString::Append(const CString *str) - { -//--- check - if(!CheckPointer(str)) - return; -//--- - m_string+=str.Str(); - } -//+------------------------------------------------------------------+ -//| Insert a string in specified position | -//+------------------------------------------------------------------+ -uint CString::Insert(const uint pos,const string substring) - { - string tmp=StringSubstr(m_string,0,pos); -//--- - tmp+=substring; - m_string=tmp+StringSubstr(m_string,pos); -//--- result - return(StringLen(m_string)); - } -//+------------------------------------------------------------------+ -//| Insert a string in specified position | -//+------------------------------------------------------------------+ -uint CString::Insert(const uint pos,const CString *substring) - { -//--- check - if(!CheckPointer(substring)) - return(0); -//--- - string tmp=StringSubstr(m_string,0,pos); -//--- - tmp+=substring.Str(); - m_string=tmp+StringSubstr(m_string,pos); -//--- result - return(StringLen(m_string)); - } -//+------------------------------------------------------------------+ -//| Comparison with the string | -//+------------------------------------------------------------------+ -int CString::Compare(const string str) const - { - if(m_stringstr) - return(1); -//--- equal - return(0); - } -//+------------------------------------------------------------------+ -//| Comparison with the string | -//+------------------------------------------------------------------+ -int CString::Compare(const CString *str) const - { -//--- check - if(!CheckPointer(str)) - return(0); -//--- - if(m_stringstr.Str()) - return(1); -//--- equal - return(0); - } -//+------------------------------------------------------------------+ -//| Comparison with the string without case | -//+------------------------------------------------------------------+ -int CString::CompareNoCase(const string str) const - { - string tmp1,tmp2; -//--- - tmp1=m_string; - tmp2=str; - StringToLower(tmp1); - StringToLower(tmp2); -//--- - if(tmp1tmp2) - return(1); -//--- equal - return(0); - } -//+------------------------------------------------------------------+ -//| Comparison with the string without case | -//+------------------------------------------------------------------+ -int CString::CompareNoCase(const CString *str) const - { - string tmp1,tmp2; -//--- check - if(!CheckPointer(str)) - return(0); -//--- - tmp1=m_string; - tmp2=str.Str(); - StringToLower(tmp1); - StringToLower(tmp2); -//--- - if(tmp1tmp2) - return(1); -//--- equal - return(0); - } -//+------------------------------------------------------------------+ -//| Find occurrences of substring from the specified position | -//+------------------------------------------------------------------+ -int CString::Find(const uint start,const string substring) const - { - return(StringFind(m_string,substring,start)); - } -//+------------------------------------------------------------------+ -//| Find last occurrence of substring | -//+------------------------------------------------------------------+ -int CString::FindRev(const string substring) const - { - int result,pos=-1; -//--- - do - { - result=pos; - } - while((pos=StringFind(m_string,substring,pos+1))>=0); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Get a substring consisting of count elements of the left string | -//+------------------------------------------------------------------+ -string CString::Left(const uint count) const - { - return(StringSubstr(m_string,0,count)); - } -//+------------------------------------------------------------------+ -//| Get a substring consisting of count elements of the right string.| -//+------------------------------------------------------------------+ -string CString::Right(const uint count) const - { - return(StringSubstr(m_string,StringLen(m_string)-count,count)); - } -//+------------------------------------------------------------------+ -//| Get a substring consisting of count elements of the pos string | -//+------------------------------------------------------------------+ -string CString::Mid(const uint pos,const uint count) const - { - return(StringSubstr(m_string,pos,count)); - } -//+------------------------------------------------------------------+ -//| Remove from the string, all characters in the begin and | -//| in the end if they arein targets, or space, \t,\n or \r | -//+------------------------------------------------------------------+ -int CString::Trim(const string targets) - { - return(TrimLeft(targets)+TrimRight(targets)); - } -//+------------------------------------------------------------------+ -//| Remove from the string, all characters in the begin if they are | -//| in targets, or space, \t,\n or \r | -//+------------------------------------------------------------------+ -int CString::TrimLeft(const string targets) - { - ushort ch; -//--- - for(int i=0;i=0;i--) - { - ch=StringGetCharacter(m_string,i); - if(ch<=' ') - continue; - for(int j=0;jj;i--,j++) - { - ch=StringGetCharacter(m_string,i); - StringSetCharacter(m_string,i,StringGetCharacter(m_string,j)); - StringSetCharacter(m_string,j,ch); - } - } -//+------------------------------------------------------------------+ -//| Remove all occurrences of the substring | -//+------------------------------------------------------------------+ -uint CString::Remove(const string substring) - { - int result=0,len,pos=-1; - string tmp; -//--- - len=StringLen(substring); - while((pos=StringFind(m_string,substring,pos))>=0) - { - tmp=StringSubstr(m_string,0,pos); - m_string=tmp+StringSubstr(m_string,pos+len); - result++; - } -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Replace all occurrences of a substring in the specified string | -//+------------------------------------------------------------------+ -uint CString::Replace(const string substring,const string newstring) - { - int result=0,len,pos=-1; - string tmp; -//--- - len=StringLen(substring); - while((pos=StringFind(m_string,substring,pos))>=0) - { - tmp=StringSubstr(m_string,0,pos)+newstring; - m_string=tmp+StringSubstr(m_string,pos+len); - // to eliminate possible loops - pos+=StringLen(newstring); - result++; - } -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Comparison with the string by algorithm | -//+------------------------------------------------------------------+ -int CString::Compare(const CObject *node,const int mode=0) const - { - CString *str=(CString*)node; -//--- check - if(str==NULL) - return(0); -//--- - switch(mode) - { - case 0: return(Compare(str)); - case 1: return(CompareNoCase(str)); - } -//--- equal - return(0); - } -//+------------------------------------------------------------------+ diff --git a/Include/Tools/DateTime.mqh b/Include/Tools/DateTime.mqh deleted file mode 100644 index 94d405b..0000000 --- a/Include/Tools/DateTime.mqh +++ /dev/null @@ -1,581 +0,0 @@ -//+------------------------------------------------------------------+ -//| DateTime.mqh | -//| Copyright 2009-2015, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Structure CDateTime. | -//| Purpose: Working with dates and time. | -//| Extends the MqlDateTime structure. | -//+------------------------------------------------------------------+ -struct CDateTime : public MqlDateTime - { - //--- additional information - string MonthName(const int num) const; - string ShortMonthName(const int num) const; - string DayName(const int num) const; - string ShortDayName(const int num) const; - string MonthName(void) const { return(MonthName(mon)); } - string ShortMonthName(void) const { return(ShortMonthName(mon)); } - string DayName(void) const { return(DayName(day_of_week)); } - string ShortDayName(void) const { return(ShortDayName(day_of_week)); } - int DaysInMonth(void) const; - //--- data access - datetime DateTime(void) { return(StructToTime(this)); } - void DateTime(const datetime value) { TimeToStruct(value,this); } - void DateTime(const MqlDateTime& value) { this=value; } - void Date(const datetime value); - void Date(const MqlDateTime &value); - void Time(const datetime value); - void Time(const MqlDateTime &value); - //--- settings - void Sec(const int value); - void Min(const int value); - void Hour(const int value); - void Day(const int value); - void Mon(const int value); - void Year(const int value); - //--- increments - void SecDec(int delta=1); - void SecInc(int delta=1); - void MinDec(int delta=1); - void MinInc(int delta=1); - void HourDec(int delta=1); - void HourInc(int delta=1); - void DayDec(int delta=1); - void DayInc(int delta=1); - void MonDec(int delta=1); - void MonInc(int delta=1); - void YearDec(int delta=1); - void YearInc(int delta=1); - //--- check - void DayCheck(void); - }; -//+------------------------------------------------------------------+ -//| Gets month name | -//+------------------------------------------------------------------+ -string CDateTime::MonthName(const int num) const - { - switch(num) - { - case 1: return("January"); - case 2: return("February"); - case 3: return("March"); - case 4: return("April"); - case 5: return("May"); - case 6: return("June"); - case 7: return("July"); - case 8: return("August"); - case 9: return("September"); - case 10: return("October"); - case 11: return("November"); - case 12: return("December"); - } -//--- - return("Bad month"); - } -//+------------------------------------------------------------------+ -//| Gets short name of month | -//+------------------------------------------------------------------+ -string CDateTime::ShortMonthName(const int num) const - { - switch(num) - { - case 1: return("jan"); - case 2: return("feb"); - case 3: return("mar"); - case 4: return("apr"); - case 5: return("may"); - case 6: return("jun"); - case 7: return("jul"); - case 8: return("aug"); - case 9: return("sep"); - case 10: return("oct"); - case 11: return("nov"); - case 12: return("dec"); - } -//--- - return("Bad month"); - } -//+------------------------------------------------------------------+ -//| Gets name of week day | -//+------------------------------------------------------------------+ -string CDateTime::DayName(const int num) const - { - switch(num) - { - case 0: return("Sunday"); - case 1: return("Monday"); - case 2: return("Tuesday"); - case 3: return("Wednesday"); - case 4: return("Thursday"); - case 5: return("Friday"); - case 6: return("Saturday"); - } -//--- - return("Bad day of week"); - } -//+------------------------------------------------------------------+ -//| Gets short name of week day | -//+------------------------------------------------------------------+ -string CDateTime::ShortDayName(const int num) const - { - switch(num) - { - case 0: return("Su"); - case 1: return("Mo"); - case 2: return("Tu"); - case 3: return("We"); - case 4: return("Th"); - case 5: return("Fr"); - case 6: return("Sa"); - } -//--- - return("Bad day of week"); - } -//+------------------------------------------------------------------+ -//| Gets number of days in month | -//+------------------------------------------------------------------+ -int CDateTime::DaysInMonth(void) const - { - int leap_year; -//--- - switch(mon) - { - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - return(31); - case 2: - leap_year=year; - if(year%100==0) - leap_year/=100; - return((leap_year%4==0)? 29 : 28); - case 4: - case 6: - case 9: - case 11: - return(30); - } -//--- - return(0); - } -//+------------------------------------------------------------------+ -//| Sets date | -//+------------------------------------------------------------------+ -void CDateTime::Date(const datetime value) - { - MqlDateTime dt; -//--- convert to structure - TimeToStruct(value,dt); -//--- set - Date(dt); - } -//+------------------------------------------------------------------+ -//| Sets date | -//+------------------------------------------------------------------+ -void CDateTime::Date(const MqlDateTime &value) - { - day =value.day; - mon =value.mon; - year=value.year; -//--- check if day is correct - DayCheck(); - } -//+------------------------------------------------------------------+ -//| Sets time | -//+------------------------------------------------------------------+ -void CDateTime::Time(const datetime value) - { - MqlDateTime dt; -//--- convert to structure - TimeToStruct(value,dt); -//--- set - Time(dt); - } -//+------------------------------------------------------------------+ -//| Sets time | -//+------------------------------------------------------------------+ -void CDateTime::Time(const MqlDateTime &value) - { - hour=value.hour; - min =value.min; - sec =value.sec; - } -//+------------------------------------------------------------------+ -//| Sets seconds | -//+------------------------------------------------------------------+ -void CDateTime::Sec(const int value) - { -//--- check and set - if(value>=0 && value<60) - sec=value; - } -//+------------------------------------------------------------------+ -//| Sets minutes | -//+------------------------------------------------------------------+ -void CDateTime::Min(const int value) - { -//--- check and set - if(value>=0 && value<60) - min=value; - } -//+------------------------------------------------------------------+ -//| Sets hours | -//+------------------------------------------------------------------+ -void CDateTime::Hour(const int value) - { -//--- check and set - if(value>=0 && value<24) - hour=value; - } -//+------------------------------------------------------------------+ -//| Sets day of month | -//+------------------------------------------------------------------+ -void CDateTime::Day(const int value) - { -//--- check and set - if(value>0 && value<=DaysInMonth()) - { - day=value; - //--- check if day is correct - DayCheck(); - } - } -//+------------------------------------------------------------------+ -//| Sets month | -//+------------------------------------------------------------------+ -void CDateTime::Mon(const int value) - { -//--- check and set - if(value>0 && value<=12) - { - mon=value; - //--- check if day is correct - DayCheck(); - } - } -//+------------------------------------------------------------------+ -//| Sets year | -//+------------------------------------------------------------------+ -void CDateTime::Year(const int value) - { -//--- check and set - if(value>=1970) - { - year=value; - //--- check if day is correct - DayCheck(); - } - } -//+------------------------------------------------------------------+ -//| Subtracts specified number of seconds | -//+------------------------------------------------------------------+ -void CDateTime::SecDec(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - SecInc(-delta); - return; - } -//--- check if subtract from upper number positions - if(delta>60) - { - MinDec(delta/60); - delta%=60; - } - sec-=delta; - if(sec<0) - { - sec+=60; - MinDec(); - } - } -//+------------------------------------------------------------------+ -//| Adds specified number of seconds | -//+------------------------------------------------------------------+ -void CDateTime::SecInc(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - SecDec(-delta); - return; - } -//--- check if add to upper number positions - if(delta>60) - { - MinInc(delta/60); - delta%=60; - } - sec+=delta; - if(sec>=60) - { - sec-=60; - MinInc(); - } - } -//+------------------------------------------------------------------+ -//| Subtracts specified number of minutes | -//+------------------------------------------------------------------+ -void CDateTime::MinDec(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - MinInc(-delta); - return; - } -//--- check if subtract from upper number positions - if(delta>60) - { - HourDec(delta/60); - delta%=60; - } - min-=delta; - if(min<0) - { - min+=60; - HourDec(); - } - } -//+------------------------------------------------------------------+ -//| Adds specified number of minutes | -//+------------------------------------------------------------------+ -void CDateTime::MinInc(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - MinDec(-delta); - return; - } -//--- check if add to upper number positions - if(delta>60) - { - HourInc(delta/60); - delta%=60; - } - min+=delta; - if(min>=60) - { - min-=60; - HourInc(); - } - } -//+------------------------------------------------------------------+ -//| Subtracts specified number of hours | -//+------------------------------------------------------------------+ -void CDateTime::HourDec(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - HourInc(-delta); - return; - } -//--- check if subtract from upper number positions - if(delta>24) - { - DayDec(delta/24); - delta%=24; - } - hour-=delta; - if(hour<0) - { - hour+=24; - DayDec(); - } - } -//+------------------------------------------------------------------+ -//| Adds specified number of hours | -//+------------------------------------------------------------------+ -void CDateTime::HourInc(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - HourDec(-delta); - return; - } -//--- check if add to upper number positions - if(delta>24) - { - DayInc(delta/24); - delta%=24; - } - hour+=delta; - if(hour>=24) - { - hour-=24; - DayInc(); - } - } -//+------------------------------------------------------------------+ -//| Subtracts specified number of days | -//+------------------------------------------------------------------+ -void CDateTime::DayDec(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - DayInc(-delta); - return; - } -//--- uncertain condition, as the number of days in month can differ - while(day<=delta) - { - delta-=day; - MonDec(); - day=DaysInMonth(); - } - day-=delta; -//--- check if day is correct - DayCheck(); - } -//+------------------------------------------------------------------+ -//| Adds specified number of days | -//+------------------------------------------------------------------+ -void CDateTime::DayInc(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - DayDec(-delta); - return; - } -//--- uncertain condition, as the number of days in month can differ - while(DaysInMonth()-day12) - { - YearDec(delta/12); - delta%=12; - } - mon-=delta; - if(mon<=0) - { - mon+=12; - YearDec(); - } -//--- check if day is correct - DayCheck(); - } -//+------------------------------------------------------------------+ -//| Adds specified number of months | -//+------------------------------------------------------------------+ -void CDateTime::MonInc(int delta) - { -//--- if increment is 0 - exit - if(delta==0) - return; -//--- if increment is negative - inverse the operation - if(delta<0) - { - MonDec(-delta); - return; - } -//--- check if add to upper number positions - if(delta>12) - { - YearInc(delta/12); - delta%=12; - } - mon+=delta; - if(mon>12) - { - mon-=12; - YearInc(); - } -//--- check if day is correct - DayCheck(); - } -//+------------------------------------------------------------------+ -//| Subtracts specified number of years | -//+------------------------------------------------------------------+ -void CDateTime::YearDec(int delta) - { -//--- if increment is 0 - exit - if(delta!=0) - { - year-=delta; - //--- check if day is correct - DayCheck(); - } - } -//+------------------------------------------------------------------+ -//| Adds specified number of years | -//+------------------------------------------------------------------+ -void CDateTime::YearInc(int delta) - { -//--- if increment is 0 - exit - if(delta!=0) - { - year+=delta; - //--- check if day is correct - DayCheck(); - } - } -//+------------------------------------------------------------------+ -//| Checks if day number is correct | -//+------------------------------------------------------------------+ -void CDateTime::DayCheck(void) - { - if(day>DaysInMonth()) - day=DaysInMonth(); -//--- this is required to get day of week and day of year - TimeToStruct(StructToTime(this),this); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/AccountInfo.mqh b/Include/Trade/AccountInfo.mqh deleted file mode 100644 index 5181e2e..0000000 --- a/Include/Trade/AccountInfo.mqh +++ /dev/null @@ -1,397 +0,0 @@ -//+------------------------------------------------------------------+ -//| AccountInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CAccountInfo. | -//| Appointment: Class for access to account info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CAccountInfo : public CObject - { -public: - CAccountInfo(void); - ~CAccountInfo(void); - //--- fast access methods to the integer account propertyes - long Login(void) const; - ENUM_ACCOUNT_TRADE_MODE TradeMode(void) const; - string TradeModeDescription(void) const; - long Leverage(void) const; - ENUM_ACCOUNT_STOPOUT_MODE StopoutMode(void) const; - string StopoutModeDescription(void) const; - ENUM_ACCOUNT_MARGIN_MODE MarginMode(void) const; - string MarginModeDescription(void) const; - bool TradeAllowed(void) const; - bool TradeExpert(void) const; - int LimitOrders(void) const; - //--- fast access methods to the double account propertyes - double Balance(void) const; - double Credit(void) const; - double Profit(void) const; - double Equity(void) const; - double Margin(void) const; - double FreeMargin(void) const; - double MarginLevel(void) const; - double MarginCall(void) const; - double MarginStopOut(void) const; - //--- fast access methods to the string account propertyes - string Name(void) const; - string Server(void) const; - string Currency(void) const; - string Company(void) const; - //--- access methods to the API MQL5 functions - long InfoInteger(const ENUM_ACCOUNT_INFO_INTEGER prop_id) const; - double InfoDouble(const ENUM_ACCOUNT_INFO_DOUBLE prop_id) const; - string InfoString(const ENUM_ACCOUNT_INFO_STRING prop_id) const; - //--- checks - double OrderProfitCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price_open,const double price_close) const; - double MarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price) const; - double FreeMarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price) const; - double MaxLotCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double price,const double percent=100) const; - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CAccountInfo::CAccountInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CAccountInfo::~CAccountInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_LOGIN" | -//+------------------------------------------------------------------+ -long CAccountInfo::Login(void) const - { - return(AccountInfoInteger(ACCOUNT_LOGIN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_TRADE_MODE" | -//+------------------------------------------------------------------+ -ENUM_ACCOUNT_TRADE_MODE CAccountInfo::TradeMode(void) const - { - return((ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_TRADE_MODE" as string | -//+------------------------------------------------------------------+ -string CAccountInfo::TradeModeDescription(void) const - { - string str; -//--- - switch(TradeMode()) - { - case ACCOUNT_TRADE_MODE_DEMO: - str="Demo trading account"; - break; - case ACCOUNT_TRADE_MODE_CONTEST: - str="Contest trading account"; - break; - case ACCOUNT_TRADE_MODE_REAL: - str="Real trading account"; - break; - default: - str="Unknown trade account"; - } -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_LEVERAGE" | -//+------------------------------------------------------------------+ -long CAccountInfo::Leverage(void) const - { - return(AccountInfoInteger(ACCOUNT_LEVERAGE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_SO_MODE" | -//+------------------------------------------------------------------+ -ENUM_ACCOUNT_STOPOUT_MODE CAccountInfo::StopoutMode(void) const - { - return((ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_SO_MODE" as string | -//+------------------------------------------------------------------+ -string CAccountInfo::StopoutModeDescription(void) const - { - string str; -//--- - switch(StopoutMode()) - { - case ACCOUNT_STOPOUT_MODE_PERCENT: - str="Level is specified in percentage"; - break; - case ACCOUNT_STOPOUT_MODE_MONEY: - str="Level is specified in money"; - break; - default: - str="Unknown stopout mode"; - } -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_MODE" | -//+------------------------------------------------------------------+ -ENUM_ACCOUNT_MARGIN_MODE CAccountInfo::MarginMode(void) const - { - return((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_MODE" as string | -//+------------------------------------------------------------------+ -string CAccountInfo::MarginModeDescription(void) const - { - string str; -//--- - switch(MarginMode()) - { - case ACCOUNT_MARGIN_MODE_RETAIL_NETTING: - str="Netting"; - break; - case ACCOUNT_MARGIN_MODE_EXCHANGE: - str="Exchange"; - break; - case ACCOUNT_MARGIN_MODE_RETAIL_HEDGING: - str="Hedging"; - break; - default: - str="Unknown margin mode"; - } -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_TRADE_ALLOWED" | -//+------------------------------------------------------------------+ -bool CAccountInfo::TradeAllowed(void) const - { - return((bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_TRADE_EXPERT" | -//+------------------------------------------------------------------+ -bool CAccountInfo::TradeExpert(void) const - { - return((bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_LIMIT_ORDERS" | -//+------------------------------------------------------------------+ -int CAccountInfo::LimitOrders(void) const - { - return((int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_BALANCE" | -//+------------------------------------------------------------------+ -double CAccountInfo::Balance(void) const - { - return(AccountInfoDouble(ACCOUNT_BALANCE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_CREDIT" | -//+------------------------------------------------------------------+ -double CAccountInfo::Credit(void) const - { - return(AccountInfoDouble(ACCOUNT_CREDIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_PROFIT" | -//+------------------------------------------------------------------+ -double CAccountInfo::Profit(void) const - { - return(AccountInfoDouble(ACCOUNT_PROFIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_EQUITY" | -//+------------------------------------------------------------------+ -double CAccountInfo::Equity(void) const - { - return(AccountInfoDouble(ACCOUNT_EQUITY)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN" | -//+------------------------------------------------------------------+ -double CAccountInfo::Margin(void) const - { - return(AccountInfoDouble(ACCOUNT_MARGIN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_FREEMARGIN" | -//+------------------------------------------------------------------+ -double CAccountInfo::FreeMargin(void) const - { - return(AccountInfoDouble(ACCOUNT_FREEMARGIN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_LEVEL" | -//+------------------------------------------------------------------+ -double CAccountInfo::MarginLevel(void) const - { - return(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_SO_CALL" | -//+------------------------------------------------------------------+ -double CAccountInfo::MarginCall(void) const - { - return(AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_MARGIN_SO_SO" | -//+------------------------------------------------------------------+ -double CAccountInfo::MarginStopOut(void) const - { - return(AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_NAME" | -//+------------------------------------------------------------------+ -string CAccountInfo::Name(void) const - { - return(AccountInfoString(ACCOUNT_NAME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_SERVER" | -//+------------------------------------------------------------------+ -string CAccountInfo::Server(void) const - { - return(AccountInfoString(ACCOUNT_SERVER)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_CURRENCY" | -//+------------------------------------------------------------------+ -string CAccountInfo::Currency(void) const - { - return(AccountInfoString(ACCOUNT_CURRENCY)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ACCOUNT_COMPANY" | -//+------------------------------------------------------------------+ -string CAccountInfo::Company(void) const - { - return(AccountInfoString(ACCOUNT_COMPANY)); - } -//+------------------------------------------------------------------+ -//| Access functions AccountInfoInteger(...) | -//+------------------------------------------------------------------+ -long CAccountInfo::InfoInteger(const ENUM_ACCOUNT_INFO_INTEGER prop_id) const - { - return(AccountInfoInteger(prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions AccountInfoDouble(...) | -//+------------------------------------------------------------------+ -double CAccountInfo::InfoDouble(const ENUM_ACCOUNT_INFO_DOUBLE prop_id) const - { - return(AccountInfoDouble(prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions AccountInfoString(...) | -//+------------------------------------------------------------------+ -string CAccountInfo::InfoString(const ENUM_ACCOUNT_INFO_STRING prop_id) const - { - return(AccountInfoString(prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderCalcProfit(...). | -//| INPUT: name - symbol name, | -//| trade_operation - trade operation, | -//| volume - volume of the opening position, | -//| price_open - price of the opening position, | -//| price_close - price of the closing position. | -//+------------------------------------------------------------------+ -double CAccountInfo::OrderProfitCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price_open,const double price_close) const - { - double profit=EMPTY_VALUE; -//--- - if(!OrderCalcProfit(trade_operation,symbol,volume,price_open,price_close,profit)) - return(EMPTY_VALUE); -//--- - return(profit); - } -//+------------------------------------------------------------------+ -//| Access functions OrderCalcMargin(...). | -//| INPUT: name - symbol name, | -//| trade_operation - trade operation, | -//| volume - volume of the opening position, | -//| price - price of the opening position. | -//+------------------------------------------------------------------+ -double CAccountInfo::MarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price) const - { - double margin=EMPTY_VALUE; -//--- - if(!OrderCalcMargin(trade_operation,symbol,volume,price,margin)) - return(EMPTY_VALUE); -//--- - return(margin); - } -//+------------------------------------------------------------------+ -//| Access functions OrderCalcMargin(...). | -//| INPUT: name - symbol name, | -//| trade_operation - trade operation, | -//| volume - volume of the opening position, | -//| price - price of the opening position. | -//+------------------------------------------------------------------+ -double CAccountInfo::FreeMarginCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double volume,const double price) const - { - return(FreeMargin()-MarginCheck(symbol,trade_operation,volume,price)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderCalcMargin(...). | -//| INPUT: name - symbol name, | -//| trade_operation - trade operation, | -//| price - price of the opening position, | -//| percent - percent of available margin [1-100%]. | -//+------------------------------------------------------------------+ -double CAccountInfo::MaxLotCheck(const string symbol,const ENUM_ORDER_TYPE trade_operation, - const double price,const double percent) const - { - double margin=0.0; -//--- checks - if(symbol=="" || price<=0.0 || percent<1 || percent>100) - { - Print("CAccountInfo::MaxLotCheck invalid parameters"); - return(0.0); - } -//--- calculate margin requirements for 1 lot - if(!OrderCalcMargin(trade_operation,symbol,1.0,price,margin) || margin<0.0) - { - Print("CAccountInfo::MaxLotCheck margin calculation failed"); - return(0.0); - } -//--- - if(margin==0.0) // for pending orders - return(SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX)); -//--- calculate maximum volume - double volume=NormalizeDouble(FreeMargin()*percent/100.0/margin,2); -//--- normalize and check limits - double stepvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP); - if(stepvol>0.0) - volume=stepvol*MathFloor(volume/stepvol); -//--- - double minvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); - if(volumemaxvol) - volume=maxvol; -//--- return volume - return(volume); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/DealInfo.mqh b/Include/Trade/DealInfo.mqh deleted file mode 100644 index 0f12b47..0000000 --- a/Include/Trade/DealInfo.mqh +++ /dev/null @@ -1,430 +0,0 @@ -//+------------------------------------------------------------------+ -//| DealInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CDealInfo. | -//| Appointment: Class for access to history deal info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CDealInfo : public CObject - { -protected: - ulong m_ticket; // ticket of history order - -public: - CDealInfo(void); - ~CDealInfo(void); - //--- methods of access to protected data - void Ticket(const ulong ticket) { m_ticket=ticket; } - ulong Ticket(void) const { return(m_ticket); } - //--- fast access methods to the integer position propertyes - long Order(void) const; - datetime Time(void) const; - ulong TimeMsc(void) const; - ENUM_DEAL_TYPE DealType(void) const; - string TypeDescription(void) const; - ENUM_DEAL_ENTRY Entry(void) const; - string EntryDescription(void) const; - long Magic(void) const; - long PositionId(void) const; - //--- fast access methods to the double position propertyes - double Volume(void) const; - double Price(void) const; - double Commission(void) const; - double Swap(void) const; - double Profit(void) const; - //--- fast access methods to the string position propertyes - string Symbol(void) const; - string Comment(void) const; - string ExternalId(void) const; - //--- access methods to the API MQL5 functions - bool InfoInteger(ENUM_DEAL_PROPERTY_INTEGER prop_id,long &var) const; - bool InfoDouble(ENUM_DEAL_PROPERTY_DOUBLE prop_id,double &var) const; - bool InfoString(ENUM_DEAL_PROPERTY_STRING prop_id,string &var) const; - //--- info methods - string FormatAction(string &str,const uint action) const; - string FormatEntry(string &str,const uint entry) const; - string FormatDeal(string &str) const; - //--- method for select deal - bool SelectByIndex(const int index); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CDealInfo::CDealInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDealInfo::~CDealInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_ORDER" | -//+------------------------------------------------------------------+ -long CDealInfo::Order(void) const - { - return(HistoryDealGetInteger(m_ticket,DEAL_ORDER)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_TIME" | -//+------------------------------------------------------------------+ -datetime CDealInfo::Time(void) const - { - return((datetime)HistoryDealGetInteger(m_ticket,DEAL_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_TIME_MSC" | -//+------------------------------------------------------------------+ -ulong CDealInfo::TimeMsc(void) const - { - return(HistoryDealGetInteger(m_ticket,DEAL_TIME_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_TYPE" | -//+------------------------------------------------------------------+ -ENUM_DEAL_TYPE CDealInfo::DealType(void) const - { - return((ENUM_DEAL_TYPE)HistoryDealGetInteger(m_ticket,DEAL_TYPE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_TYPE" as string | -//+------------------------------------------------------------------+ -string CDealInfo::TypeDescription(void) const - { - string str; -//--- - switch(DealType()) - { - case DEAL_TYPE_BUY: - str="Buy type"; - break; - case DEAL_TYPE_SELL: - str="Sell type"; - break; - case DEAL_TYPE_BALANCE: - str="Balance type"; - break; - case DEAL_TYPE_CREDIT: - str="Credit type"; - break; - case DEAL_TYPE_CHARGE: - str="Charge type"; - break; - case DEAL_TYPE_CORRECTION: - str="Correction type"; - break; - case DEAL_TYPE_BONUS: - str="Bonus type"; - break; - case DEAL_TYPE_COMMISSION: - str="Commission type"; - break; - case DEAL_TYPE_COMMISSION_DAILY: - str="Daily Commission type"; - break; - case DEAL_TYPE_COMMISSION_MONTHLY: - str="Monthly Commission type"; - break; - case DEAL_TYPE_COMMISSION_AGENT_DAILY: - str="Daily Agent Commission type"; - break; - case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: - str="Monthly Agent Commission type"; - break; - case DEAL_TYPE_INTEREST: - str="Interest Rate type"; - break; - case DEAL_TYPE_BUY_CANCELED: - str="Canceled Buy type"; - break; - case DEAL_TYPE_SELL_CANCELED: - str="Canceled Sell type"; - break; - default: - str="Unknown type"; - } -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_ENTRY" | -//+------------------------------------------------------------------+ -ENUM_DEAL_ENTRY CDealInfo::Entry(void) const - { - return((ENUM_DEAL_ENTRY)HistoryDealGetInteger(m_ticket,DEAL_ENTRY)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_ENTRY" as string | -//+------------------------------------------------------------------+ -string CDealInfo::EntryDescription(void) const - { - string str; -//--- - switch(CDealInfo::Entry()) - { - case DEAL_ENTRY_IN: - str="In entry"; - break; - case DEAL_ENTRY_OUT: - str="Out entry"; - break; - case DEAL_ENTRY_INOUT: - str="InOut entry"; - break; - case DEAL_ENTRY_STATE: - str="Status record"; - break; - case DEAL_ENTRY_OUT_BY: - str="Out By entry"; - break; - default: - str="Unknown entry"; - } -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_MAGIC" | -//+------------------------------------------------------------------+ -long CDealInfo::Magic(void) const - { - return(HistoryDealGetInteger(m_ticket,DEAL_MAGIC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_POSITION_ID" | -//+------------------------------------------------------------------+ -long CDealInfo::PositionId(void) const - { - return(HistoryDealGetInteger(m_ticket,DEAL_POSITION_ID)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_VOLUME" | -//+------------------------------------------------------------------+ -double CDealInfo::Volume(void) const - { - return(HistoryDealGetDouble(m_ticket,DEAL_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_PRICE_OPEN" | -//+------------------------------------------------------------------+ -double CDealInfo::Price(void) const - { - return(HistoryDealGetDouble(m_ticket,DEAL_PRICE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_COMMISSION" | -//+------------------------------------------------------------------+ -double CDealInfo::Commission(void) const - { - return(HistoryDealGetDouble(m_ticket,DEAL_COMMISSION)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_SWAP" | -//+------------------------------------------------------------------+ -double CDealInfo::Swap(void) const - { - return(HistoryDealGetDouble(m_ticket,DEAL_SWAP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_PROFIT" | -//+------------------------------------------------------------------+ -double CDealInfo::Profit(void) const - { - return(HistoryDealGetDouble(m_ticket,DEAL_PROFIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_SYMBOL" | -//+------------------------------------------------------------------+ -string CDealInfo::Symbol(void) const - { - return(HistoryDealGetString(m_ticket,DEAL_SYMBOL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_COMMENT" | -//+------------------------------------------------------------------+ -string CDealInfo::Comment(void) const - { - return(HistoryDealGetString(m_ticket,DEAL_COMMENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "DEAL_EXTERNAL_ID" | -//+------------------------------------------------------------------+ -string CDealInfo::ExternalId(void) const - { - return(HistoryDealGetString(m_ticket,DEAL_EXTERNAL_ID)); - } -//+------------------------------------------------------------------+ -//| Access functions HistoryDealGetInteger(...) | -//+------------------------------------------------------------------+ -bool CDealInfo::InfoInteger(ENUM_DEAL_PROPERTY_INTEGER prop_id,long &var) const - { - return(HistoryDealGetInteger(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions HistoryDealGetDouble(...) | -//+------------------------------------------------------------------+ -bool CDealInfo::InfoDouble(ENUM_DEAL_PROPERTY_DOUBLE prop_id,double &var) const - { - return(HistoryDealGetDouble(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions HistoryDealGetString(...) | -//+------------------------------------------------------------------+ -bool CDealInfo::InfoString(ENUM_DEAL_PROPERTY_STRING prop_id,string &var) const - { - return(HistoryDealGetString(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Converths the type of a deal to text | -//+------------------------------------------------------------------+ -string CDealInfo::FormatAction(string &str,const uint action) const - { -//--- see the type - switch(action) - { - case DEAL_TYPE_BUY: - str="buy"; - break; - case DEAL_TYPE_SELL: - str="sell"; - break; - case DEAL_TYPE_BALANCE: - str="balance"; - break; - case DEAL_TYPE_CREDIT: - str="credit"; - break; - case DEAL_TYPE_CHARGE: - str="charge"; - break; - case DEAL_TYPE_CORRECTION: - str="correction"; - break; - case DEAL_TYPE_BONUS: - str="bonus"; - break; - case DEAL_TYPE_COMMISSION: - str="commission"; - break; - case DEAL_TYPE_COMMISSION_DAILY: - str="daily commission"; - break; - case DEAL_TYPE_COMMISSION_MONTHLY: - str="monthly commission"; - break; - case DEAL_TYPE_COMMISSION_AGENT_DAILY: - str="daily agent commission"; - break; - case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: - str="monthly agent commission"; - break; - case DEAL_TYPE_INTEREST: - str="interest rate"; - break; - case DEAL_TYPE_BUY_CANCELED: - str="canceled buy"; - break; - case DEAL_TYPE_SELL_CANCELED: - str="canceled sell"; - break; - default: - str="unknown deal type "+(string)action; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the deal direction to text | -//+------------------------------------------------------------------+ -string CDealInfo::FormatEntry(string &str,const uint entry) const - { -//--- see the type - switch(entry) - { - case DEAL_ENTRY_IN: - str="in"; - break; - case DEAL_ENTRY_OUT: - str="out"; - break; - case DEAL_ENTRY_INOUT: - str="in/out"; - break; - case DEAL_ENTRY_OUT_BY: - str="out by"; - break; - default: - str="unknown deal entry "+(string)entry; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the deal parameters to text | -//+------------------------------------------------------------------+ -string CDealInfo::FormatDeal(string &str) const - { - string type; - long tmp_long; -//--- set up - string symbol_name=this.Symbol(); - int digits=_Digits; - if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long)) - digits=(int)tmp_long; -//--- form the description of the deal - switch(DealType()) - { - //--- Buy-Sell - case DEAL_TYPE_BUY: - case DEAL_TYPE_SELL: - str=StringFormat("#%I64u %s %s %s at %s", - Ticket(), - FormatAction(type,DealType()), - DoubleToString(Volume(),2), - symbol_name, - DoubleToString(Price(),digits)); - break; - - //--- balance operations - case DEAL_TYPE_BALANCE: - case DEAL_TYPE_CREDIT: - case DEAL_TYPE_CHARGE: - case DEAL_TYPE_CORRECTION: - case DEAL_TYPE_BONUS: - case DEAL_TYPE_COMMISSION: - case DEAL_TYPE_COMMISSION_DAILY: - case DEAL_TYPE_COMMISSION_MONTHLY: - case DEAL_TYPE_COMMISSION_AGENT_DAILY: - case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: - case DEAL_TYPE_INTEREST: - str=StringFormat("#%I64u %s %s [%s]", - Ticket(), - FormatAction(type,DealType()), - DoubleToString(Profit(),2), - this.Comment()); - break; - - default: - str="unknown deal type "+(string)DealType(); - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Select a deal on the index | -//+------------------------------------------------------------------+ -bool CDealInfo::SelectByIndex(const int index) - { - ulong ticket=HistoryDealGetTicket(index); - if(ticket==0) - return(false); - Ticket(ticket); -//--- - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/HistoryOrderInfo.mqh b/Include/Trade/HistoryOrderInfo.mqh deleted file mode 100644 index 735033d..0000000 --- a/Include/Trade/HistoryOrderInfo.mqh +++ /dev/null @@ -1,472 +0,0 @@ -//+------------------------------------------------------------------+ -//| HistoryOrderInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CHistoryOrderInfo. | -//| Appointment: Class for access to history order info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CHistoryOrderInfo : public CObject - { -protected: - ulong m_ticket; // ticket of history order -public: - CHistoryOrderInfo(void); - ~CHistoryOrderInfo(void); - //--- methods of access to protected data - void Ticket(const ulong ticket) { m_ticket=ticket; } - ulong Ticket(void) const { return(m_ticket); } - //--- fast access methods to the integer order propertyes - datetime TimeSetup(void) const; - ulong TimeSetupMsc(void) const; - datetime TimeDone(void) const; - ulong TimeDoneMsc(void) const; - ENUM_ORDER_TYPE OrderType(void) const; - string TypeDescription(void) const; - ENUM_ORDER_STATE State(void) const; - string StateDescription(void) const; - datetime TimeExpiration(void) const; - ENUM_ORDER_TYPE_FILLING TypeFilling(void) const; - string TypeFillingDescription(void) const; - ENUM_ORDER_TYPE_TIME TypeTime(void) const; - string TypeTimeDescription(void) const; - long Magic(void) const; - long PositionId(void) const; - long PositionById(void) const; - //--- fast access methods to the double order propertyes - double VolumeInitial(void) const; - double VolumeCurrent(void) const; - double PriceOpen(void) const; - double StopLoss(void) const; - double TakeProfit(void) const; - double PriceCurrent(void) const; - double PriceStopLimit(void) const; - //--- fast access methods to the string order propertyes - string Symbol(void) const; - string Comment(void) const; - string ExternalId(void) const; - //--- access methods to the API MQL5 functions - bool InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const; - bool InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const; - bool InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const; - //--- info methods - string FormatType(string &str,const uint type) const; - string FormatStatus(string &str,const uint status) const; - string FormatTypeFilling(string &str,const uint type) const; - string FormatTypeTime(string &str,const uint type) const; - string FormatOrder(string &str) const; - string FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const; - //--- method for select history order - bool SelectByIndex(const int index); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CHistoryOrderInfo::CHistoryOrderInfo(void) : m_ticket(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CHistoryOrderInfo::~CHistoryOrderInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_SETUP" | -//+------------------------------------------------------------------+ -datetime CHistoryOrderInfo::TimeSetup(void) const - { - return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_SETUP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_SETUP_MSC" | -//+------------------------------------------------------------------+ -ulong CHistoryOrderInfo::TimeSetupMsc(void) const - { - return(HistoryOrderGetInteger(m_ticket,ORDER_TIME_SETUP_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_DONE" | -//+------------------------------------------------------------------+ -datetime CHistoryOrderInfo::TimeDone(void) const - { - return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_DONE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_DONE_MSC" | -//+------------------------------------------------------------------+ -ulong CHistoryOrderInfo::TimeDoneMsc(void) const - { - return(HistoryOrderGetInteger(m_ticket,ORDER_TIME_DONE_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE CHistoryOrderInfo::OrderType(void) const - { - return((ENUM_ORDER_TYPE)HistoryOrderGetInteger(m_ticket,ORDER_TYPE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE" as string | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::TypeDescription(void) const - { - string str; -//--- - return(FormatType(str,OrderType())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_STATE" | -//+------------------------------------------------------------------+ -ENUM_ORDER_STATE CHistoryOrderInfo::State(void) const - { - return((ENUM_ORDER_STATE)HistoryOrderGetInteger(m_ticket,ORDER_STATE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_STATE" as string | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::StateDescription(void) const - { - string str; -//--- - return(FormatStatus(str,State())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_EXPIRATION" | -//+------------------------------------------------------------------+ -datetime CHistoryOrderInfo::TimeExpiration(void) const - { - return((datetime)HistoryOrderGetInteger(m_ticket,ORDER_TIME_EXPIRATION)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_FILLING" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE_FILLING CHistoryOrderInfo::TypeFilling(void) const - { - return((ENUM_ORDER_TYPE_FILLING)HistoryOrderGetInteger(m_ticket,ORDER_TYPE_FILLING)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_FILLING" as string | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::TypeFillingDescription(void) const - { - string str; -//--- - return(FormatTypeFilling(str,TypeFilling())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_TIME" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE_TIME CHistoryOrderInfo::TypeTime(void) const - { - return((ENUM_ORDER_TYPE_TIME)HistoryOrderGetInteger(m_ticket,ORDER_TYPE_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_TIME" as string | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::TypeTimeDescription(void) const - { - string str; -//--- - return(FormatTypeTime(str,TypeTime())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_EXPERT" | -//+------------------------------------------------------------------+ -long CHistoryOrderInfo::Magic(void) const - { - return(HistoryOrderGetInteger(m_ticket,ORDER_MAGIC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_POSITION_ID" | -//+------------------------------------------------------------------+ -long CHistoryOrderInfo::PositionId(void) const - { - return(HistoryOrderGetInteger(m_ticket,ORDER_POSITION_ID)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_POSITION_BY_ID" | -//+------------------------------------------------------------------+ -long CHistoryOrderInfo::PositionById(void) const - { - return(HistoryOrderGetInteger(m_ticket,ORDER_POSITION_BY_ID)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_VOLUME_INITIAL" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::VolumeInitial(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_VOLUME_INITIAL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_VOLUME_CURRENT" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::VolumeCurrent(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_VOLUME_CURRENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_OPEN" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::PriceOpen(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_OPEN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_SL" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::StopLoss(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_SL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TP" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::TakeProfit(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_TP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_CURRENT" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::PriceCurrent(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_CURRENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_STOPLIMIT" | -//+------------------------------------------------------------------+ -double CHistoryOrderInfo::PriceStopLimit(void) const - { - return(HistoryOrderGetDouble(m_ticket,ORDER_PRICE_STOPLIMIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_SYMBOL" | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::Symbol(void) const - { - return(HistoryOrderGetString(m_ticket,ORDER_SYMBOL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_COMMENT" | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::Comment(void) const - { - return(HistoryOrderGetString(m_ticket,ORDER_COMMENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_EXTERNAL_ID" | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::ExternalId(void) const - { - return(HistoryOrderGetString(m_ticket,ORDER_EXTERNAL_ID)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetInteger(...) | -//+------------------------------------------------------------------+ -bool CHistoryOrderInfo::InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const - { - return(HistoryOrderGetInteger(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetDouble(...) | -//+------------------------------------------------------------------+ -bool CHistoryOrderInfo::InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const - { - return(HistoryOrderGetDouble(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetString(...) | -//+------------------------------------------------------------------+ -bool CHistoryOrderInfo::InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const - { - return(HistoryOrderGetString(m_ticket,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Converts the order type to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatType(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_TYPE_BUY: - str="buy"; - break; - case ORDER_TYPE_SELL: - str="sell"; - break; - case ORDER_TYPE_BUY_LIMIT: - str="buy limit"; - break; - case ORDER_TYPE_SELL_LIMIT: - str="sell limit"; - break; - case ORDER_TYPE_BUY_STOP: - str="buy stop"; - break; - case ORDER_TYPE_SELL_STOP: - str="sell stop"; - break; - case ORDER_TYPE_BUY_STOP_LIMIT: - str="buy stop limit"; - break; - case ORDER_TYPE_SELL_STOP_LIMIT: - str="sell stop limit"; - break; - case ORDER_TYPE_CLOSE_BY: - str="close by"; - break; - default: - str="unknown order type "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order status to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatStatus(string &str,const uint status) const - { -//--- see the type - switch(status) - { - case ORDER_STATE_STARTED: - str="started"; - break; - case ORDER_STATE_PLACED: - str="placed"; - break; - case ORDER_STATE_CANCELED: - str="canceled"; - break; - case ORDER_STATE_PARTIAL: - str="partial"; - break; - case ORDER_STATE_FILLED: - str="filled"; - break; - case ORDER_STATE_REJECTED: - str="rejected"; - break; - case ORDER_STATE_EXPIRED: - str="expired"; - break; - default: - str="unknown order status "+(string)status; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order filling type to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatTypeFilling(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_FILLING_RETURN: - str="return remainder"; - break; - case ORDER_FILLING_IOC: - str="cancel remainder"; - break; - case ORDER_FILLING_FOK: - str="fill or kill"; - break; - default: - str="unknown type filling "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the type of order by expiration to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatTypeTime(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_TIME_GTC: - str="gtc"; - break; - case ORDER_TIME_DAY: - str="day"; - break; - case ORDER_TIME_SPECIFIED: - str="specified"; - break; - case ORDER_TIME_SPECIFIED_DAY: - str="specified day"; - break; - default: - str="unknown type time "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order parameters to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatOrder(string &str) const - { - string type,price; - long tmp_long; -//--- set up - string symbol_name=this.Symbol(); - int digits=_Digits; - if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long)) - digits=(int)tmp_long; -//--- form the order description - str=StringFormat("#%I64u %s %s %s", - Ticket(), - FormatType(type,OrderType()), - DoubleToString(VolumeInitial(),2), - symbol_name); -//--- receive the price of the order - FormatPrice(price,PriceOpen(),PriceStopLimit(),digits); -//--- if there is price, write it - if(price!="") - { - str+=" at "; - str+=price; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order prices to text | -//+------------------------------------------------------------------+ -string CHistoryOrderInfo::FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const - { - string price,trigger; -//--- Is there its trigger price? - if(price_trigger) - { - price =DoubleToString(price_order,digits); - trigger=DoubleToString(price_trigger,digits); - str =StringFormat("%s (%s)",price,trigger); - } - else - str=DoubleToString(price_order,digits); -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Select a history order on the index | -//+------------------------------------------------------------------+ -bool CHistoryOrderInfo::SelectByIndex(const int index) - { - ulong ticket=HistoryOrderGetTicket(index); - if(ticket==0) - return(false); - Ticket(ticket); -//--- - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/OrderInfo.mqh b/Include/Trade/OrderInfo.mqh deleted file mode 100644 index ba52c37..0000000 --- a/Include/Trade/OrderInfo.mqh +++ /dev/null @@ -1,553 +0,0 @@ -//+------------------------------------------------------------------+ -//| OrderInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class COrderInfo. | -//| Appointment: Class for access to order info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class COrderInfo : public CObject - { -protected: - ulong m_ticket; - ENUM_ORDER_TYPE m_type; - ENUM_ORDER_STATE m_state; - datetime m_expiration; - double m_volume_curr; - double m_price_open; - double m_stop_loss; - double m_take_profit; - -public: - COrderInfo(void); - ~COrderInfo(void); - //--- methods of access to protected data - ulong Ticket(void) const { return(m_ticket); } - //--- fast access methods to the integer order propertyes - datetime TimeSetup(void) const; - ulong TimeSetupMsc(void) const; - datetime TimeDone(void) const; - ulong TimeDoneMsc(void) const; - ENUM_ORDER_TYPE OrderType(void) const; - string TypeDescription(void) const; - ENUM_ORDER_STATE State(void) const; - string StateDescription(void) const; - datetime TimeExpiration(void) const; - ENUM_ORDER_TYPE_FILLING TypeFilling(void) const; - string TypeFillingDescription(void) const; - ENUM_ORDER_TYPE_TIME TypeTime(void) const; - string TypeTimeDescription(void) const; - long Magic(void) const; - long PositionId(void) const; - long PositionById(void) const; - //--- fast access methods to the double order propertyes - double VolumeInitial(void) const; - double VolumeCurrent(void) const; - double PriceOpen(void) const; - double StopLoss(void) const; - double TakeProfit(void) const; - double PriceCurrent(void) const; - double PriceStopLimit(void) const; - //--- fast access methods to the string order propertyes - string Symbol(void) const; - string Comment(void) const; - string ExternalId(void) const; - //--- access methods to the API MQL5 functions - bool InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const; - bool InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const; - bool InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const; - //--- info methods - string FormatType(string &str,const uint type) const; - string FormatStatus(string &str,const uint status) const; - string FormatTypeFilling(string &str,const uint type) const; - string FormatTypeTime(string &str,const uint type) const; - string FormatOrder(string &str) const; - string FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const; - //--- method for select order - bool Select(void); - bool Select(const ulong ticket); - bool SelectByIndex(const int index); - //--- additional methods - void StoreState(void); - bool CheckState(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -COrderInfo::COrderInfo(void) : m_ticket(ULONG_MAX), - m_type(WRONG_VALUE), - m_state(WRONG_VALUE), - m_expiration(0), - m_volume_curr(0.0), - m_price_open(0.0), - m_stop_loss(0.0), - m_take_profit(0.0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -COrderInfo::~COrderInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_SETUP" | -//+------------------------------------------------------------------+ -datetime COrderInfo::TimeSetup(void) const - { - return((datetime)OrderGetInteger(ORDER_TIME_SETUP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_SETUP_MSC" | -//+------------------------------------------------------------------+ -ulong COrderInfo::TimeSetupMsc(void) const - { - return(OrderGetInteger(ORDER_TIME_SETUP_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_DONE" | -//+------------------------------------------------------------------+ -datetime COrderInfo::TimeDone(void) const - { - return((datetime)OrderGetInteger(ORDER_TIME_DONE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_DONE_MSC" | -//+------------------------------------------------------------------+ -ulong COrderInfo::TimeDoneMsc(void) const - { - return(OrderGetInteger(ORDER_TIME_DONE_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE COrderInfo::OrderType(void) const - { - return((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE" as string | -//+------------------------------------------------------------------+ -string COrderInfo::TypeDescription(void) const - { - string str; -//--- - return(FormatType(str,OrderType())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_STATE" | -//+------------------------------------------------------------------+ -ENUM_ORDER_STATE COrderInfo::State(void) const - { - return((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_STATE" as string | -//+------------------------------------------------------------------+ -string COrderInfo::StateDescription(void) const - { - string str; -//--- - return(FormatStatus(str,State())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TIME_EXPIRATION" | -//+------------------------------------------------------------------+ -datetime COrderInfo::TimeExpiration(void) const - { - return((datetime)OrderGetInteger(ORDER_TIME_EXPIRATION)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_FILLING" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE_FILLING COrderInfo::TypeFilling(void) const - { - return((ENUM_ORDER_TYPE_FILLING)OrderGetInteger(ORDER_TYPE_FILLING)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_FILLING" as string | -//+------------------------------------------------------------------+ -string COrderInfo::TypeFillingDescription(void) const - { - string str; -//--- - return(FormatTypeFilling(str,TypeFilling())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_TIME" | -//+------------------------------------------------------------------+ -ENUM_ORDER_TYPE_TIME COrderInfo::TypeTime(void) const - { - return((ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TYPE_TIME" as string | -//+------------------------------------------------------------------+ -string COrderInfo::TypeTimeDescription(void) const - { - string str; -//--- - return(FormatTypeTime(str,TypeFilling())); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_MAGIC" | -//+------------------------------------------------------------------+ -long COrderInfo::Magic(void) const - { - return(OrderGetInteger(ORDER_MAGIC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_POSITION_ID" | -//+------------------------------------------------------------------+ -long COrderInfo::PositionId(void) const - { - return(OrderGetInteger(ORDER_POSITION_ID)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_POSITION_BY_ID" | -//+------------------------------------------------------------------+ -long COrderInfo::PositionById(void) const - { - return(OrderGetInteger(ORDER_POSITION_BY_ID)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_VOLUME_INITIAL" | -//+------------------------------------------------------------------+ -double COrderInfo::VolumeInitial(void) const - { - return(OrderGetDouble(ORDER_VOLUME_INITIAL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_VOLUME_CURRENT" | -//+------------------------------------------------------------------+ -double COrderInfo::VolumeCurrent(void) const - { - return(OrderGetDouble(ORDER_VOLUME_CURRENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_OPEN" | -//+------------------------------------------------------------------+ -double COrderInfo::PriceOpen(void) const - { - return(OrderGetDouble(ORDER_PRICE_OPEN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_SL" | -//+------------------------------------------------------------------+ -double COrderInfo::StopLoss(void) const - { - return(OrderGetDouble(ORDER_SL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_TP" | -//+------------------------------------------------------------------+ -double COrderInfo::TakeProfit(void) const - { - return(OrderGetDouble(ORDER_TP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_CURRENT" | -//+------------------------------------------------------------------+ -double COrderInfo::PriceCurrent(void) const - { - return(OrderGetDouble(ORDER_PRICE_CURRENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_PRICE_STOPLIMIT" | -//+------------------------------------------------------------------+ -double COrderInfo::PriceStopLimit(void) const - { - return(OrderGetDouble(ORDER_PRICE_STOPLIMIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_SYMBOL" | -//+------------------------------------------------------------------+ -string COrderInfo::Symbol(void) const - { - return(OrderGetString(ORDER_SYMBOL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_COMMENT" | -//+------------------------------------------------------------------+ -string COrderInfo::Comment(void) const - { - return(OrderGetString(ORDER_COMMENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "ORDER_EXTERNAL_ID" | -//+------------------------------------------------------------------+ -string COrderInfo::ExternalId(void) const - { - return(OrderGetString(ORDER_EXTERNAL_ID)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetInteger(...) | -//+------------------------------------------------------------------+ -bool COrderInfo::InfoInteger(const ENUM_ORDER_PROPERTY_INTEGER prop_id,long &var) const - { - return(OrderGetInteger(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetDouble(...) | -//+------------------------------------------------------------------+ -bool COrderInfo::InfoDouble(const ENUM_ORDER_PROPERTY_DOUBLE prop_id,double &var) const - { - return(OrderGetDouble(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions OrderGetString(...) | -//+------------------------------------------------------------------+ -bool COrderInfo::InfoString(const ENUM_ORDER_PROPERTY_STRING prop_id,string &var) const - { - return(OrderGetString(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Converts the order type to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatType(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_TYPE_BUY: - str="buy"; - break; - case ORDER_TYPE_SELL: - str="sell"; - break; - case ORDER_TYPE_BUY_LIMIT: - str="buy limit"; - break; - case ORDER_TYPE_SELL_LIMIT: - str="sell limit"; - break; - case ORDER_TYPE_BUY_STOP: - str="buy stop"; - break; - case ORDER_TYPE_SELL_STOP: - str="sell stop"; - break; - case ORDER_TYPE_BUY_STOP_LIMIT: - str="buy stop limit"; - break; - case ORDER_TYPE_SELL_STOP_LIMIT: - str="sell stop limit"; - break; - case ORDER_TYPE_CLOSE_BY: - str="close by"; - break; - default : - str="unknown order type "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order status to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatStatus(string &str,const uint status) const - { -//--- see the type - switch(status) - { - case ORDER_STATE_STARTED: - str="started"; - break; - case ORDER_STATE_PLACED: - str="placed"; - break; - case ORDER_STATE_CANCELED: - str="canceled"; - break; - case ORDER_STATE_PARTIAL: - str="partial"; - break; - case ORDER_STATE_FILLED: - str="filled"; - break; - case ORDER_STATE_REJECTED: - str="rejected"; - break; - case ORDER_STATE_EXPIRED: - str="expired"; - break; - case ORDER_STATE_REQUEST_ADD: - str="request adding"; - break; - case ORDER_STATE_REQUEST_MODIFY: - str="request modifying"; - break; - case ORDER_STATE_REQUEST_CANCEL: - str="request cancelling"; - break; - default : - str="unknown order status "+(string)status; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order filling type to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatTypeFilling(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_FILLING_RETURN: - str="return remainder"; - break; - case ORDER_FILLING_IOC: - str="cancel remainder"; - break; - case ORDER_FILLING_FOK: - str="fill or kill"; - break; - default: - str="unknown type filling "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the type of order by expiration to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatTypeTime(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case ORDER_TIME_GTC: - str="gtc"; - break; - case ORDER_TIME_DAY: - str="day"; - break; - case ORDER_TIME_SPECIFIED: - str="specified"; - break; - case ORDER_TIME_SPECIFIED_DAY: - str="specified day"; - break; - default: - str="unknown type time "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order parameters to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatOrder(string &str) const - { - string type,price; - long tmp_long; -//--- set up - string symbol_name=this.Symbol(); - int digits=_Digits; - if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long)) - digits=(int)tmp_long; -//--- form the order description - str=StringFormat("#%I64u %s %s %s", - Ticket(), - FormatType(type,OrderType()), - DoubleToString(VolumeInitial(),2), - symbol_name); -//--- receive the price of the order - FormatPrice(price,PriceOpen(),PriceStopLimit(),digits); -//--- if there is price, write it - if(price!="") - { - str+=" at "; - str+=price; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the order prices to text | -//+------------------------------------------------------------------+ -string COrderInfo::FormatPrice(string &str,const double price_order,const double price_trigger,const uint digits) const - { - string price,trigger; -//--- Is there its trigger price? - if(price_trigger) - { - price =DoubleToString(price_order,digits); - trigger=DoubleToString(price_trigger,digits); - str =StringFormat("%s (%s)",price,trigger); - } - else - str=DoubleToString(price_order,digits); -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Selecting an order to access | -//+------------------------------------------------------------------+ -bool COrderInfo::Select(void) - { - return(OrderSelect(m_ticket)); - } -//+------------------------------------------------------------------+ -//| Selecting an order to access | -//+------------------------------------------------------------------+ -bool COrderInfo::Select(const ulong ticket) - { - if(OrderSelect(ticket)) - { - m_ticket=ticket; - return(true); - } - m_ticket=ULONG_MAX; -//--- - return(false); - } -//+------------------------------------------------------------------+ -//| Select an order by the index | -//+------------------------------------------------------------------+ -bool COrderInfo::SelectByIndex(const int index) - { - ulong ticket=OrderGetTicket(index); - if(ticket==0) - { - m_ticket=ULONG_MAX; - return(false); - } - m_ticket=ticket; -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Stored order's current state | -//+------------------------------------------------------------------+ -void COrderInfo::StoreState(void) - { - m_type =OrderType(); - m_state =State(); - m_expiration =TimeExpiration(); - m_volume_curr=VolumeCurrent(); - m_price_open =PriceOpen(); - m_stop_loss =StopLoss(); - m_take_profit=TakeProfit(); - } -//+------------------------------------------------------------------+ -//| Check order change | -//+------------------------------------------------------------------+ -bool COrderInfo::CheckState(void) - { - if(m_type==OrderType() && - m_state==State() && - m_expiration==TimeExpiration() && - m_volume_curr==VolumeCurrent() && - m_price_open==PriceOpen() && - m_stop_loss==StopLoss() && - m_take_profit==TakeProfit()) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/PositionInfo.mqh b/Include/Trade/PositionInfo.mqh deleted file mode 100644 index 71a66aa..0000000 --- a/Include/Trade/PositionInfo.mqh +++ /dev/null @@ -1,364 +0,0 @@ -//+------------------------------------------------------------------+ -//| PositionInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CPositionInfo. | -//| Appointment: Class for access to position info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CPositionInfo : public CObject - { -protected: - ENUM_POSITION_TYPE m_type; - double m_volume; - double m_price; - double m_stop_loss; - double m_take_profit; - -public: - CPositionInfo(void); - ~CPositionInfo(void); - //--- fast access methods to the integer position propertyes - ulong Ticket(void) const; - datetime Time(void) const; - ulong TimeMsc(void) const; - datetime TimeUpdate(void) const; - ulong TimeUpdateMsc(void) const; - ENUM_POSITION_TYPE PositionType(void) const; - string TypeDescription(void) const; - long Magic(void) const; - long Identifier(void) const; - //--- fast access methods to the double position propertyes - double Volume(void) const; - double PriceOpen(void) const; - double StopLoss(void) const; - double TakeProfit(void) const; - double PriceCurrent(void) const; - double Commission(void) const; - double Swap(void) const; - double Profit(void) const; - //--- fast access methods to the string position propertyes - string Symbol(void) const; - string Comment(void) const; - //--- access methods to the API MQL5 functions - bool InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const; - bool InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const; - bool InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const; - //--- info methods - string FormatType(string &str,const uint type) const; - string FormatPosition(string &str) const; - //--- methods for select position - bool Select(const string symbol); - bool SelectByMagic(const string symbol,const ulong magic); - bool SelectByTicket(const ulong ticket); - bool SelectByIndex(const int index); - //--- - void StoreState(void); - bool CheckState(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CPositionInfo::CPositionInfo(void) : m_type(WRONG_VALUE), - m_volume(0.0), - m_price(0.0), - m_stop_loss(0.0), - m_take_profit(0.0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPositionInfo::~CPositionInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TICKET" | -//+------------------------------------------------------------------+ -ulong CPositionInfo::Ticket(void) const - { - return((ulong)PositionGetInteger(POSITION_TICKET)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TIME" | -//+------------------------------------------------------------------+ -datetime CPositionInfo::Time(void) const - { - return((datetime)PositionGetInteger(POSITION_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TIME_MSC" | -//+------------------------------------------------------------------+ -ulong CPositionInfo::TimeMsc(void) const - { - return((ulong)PositionGetInteger(POSITION_TIME_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TIME_UPDATE" | -//+------------------------------------------------------------------+ -datetime CPositionInfo::TimeUpdate(void) const - { - return((datetime)PositionGetInteger(POSITION_TIME_UPDATE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TIME_UPDATE_MSC" | -//+------------------------------------------------------------------+ -ulong CPositionInfo::TimeUpdateMsc(void) const - { - return((ulong)PositionGetInteger(POSITION_TIME_UPDATE_MSC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TYPE" | -//+------------------------------------------------------------------+ -ENUM_POSITION_TYPE CPositionInfo::PositionType(void) const - { - return((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TYPE" as string | -//+------------------------------------------------------------------+ -string CPositionInfo::TypeDescription(void) const - { - string str; -//--- - return(FormatType(str,PositionType())); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_MAGIC" | -//+------------------------------------------------------------------+ -long CPositionInfo::Magic(void) const - { - return(PositionGetInteger(POSITION_MAGIC)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_IDENTIFIER" | -//+------------------------------------------------------------------+ -long CPositionInfo::Identifier(void) const - { - return(PositionGetInteger(POSITION_IDENTIFIER)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_VOLUME" | -//+------------------------------------------------------------------+ -double CPositionInfo::Volume(void) const - { - return(PositionGetDouble(POSITION_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_PRICE_OPEN" | -//+------------------------------------------------------------------+ -double CPositionInfo::PriceOpen(void) const - { - return(PositionGetDouble(POSITION_PRICE_OPEN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_SL" | -//+------------------------------------------------------------------+ -double CPositionInfo::StopLoss(void) const - { - return(PositionGetDouble(POSITION_SL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_TP" | -//+------------------------------------------------------------------+ -double CPositionInfo::TakeProfit(void) const - { - return(PositionGetDouble(POSITION_TP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_PRICE_CURRENT" | -//+------------------------------------------------------------------+ -double CPositionInfo::PriceCurrent(void) const - { - return(PositionGetDouble(POSITION_PRICE_CURRENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_COMMISSION" | -//+------------------------------------------------------------------+ -double CPositionInfo::Commission(void) const - { - return(PositionGetDouble(POSITION_COMMISSION)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_SWAP" | -//+------------------------------------------------------------------+ -double CPositionInfo::Swap(void) const - { - return(PositionGetDouble(POSITION_SWAP)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_PROFIT" | -//+------------------------------------------------------------------+ -double CPositionInfo::Profit(void) const - { - return(PositionGetDouble(POSITION_PROFIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_SYMBOL" | -//+------------------------------------------------------------------+ -string CPositionInfo::Symbol(void) const - { - return(PositionGetString(POSITION_SYMBOL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "POSITION_COMMENT" | -//+------------------------------------------------------------------+ -string CPositionInfo::Comment(void) const - { - return(PositionGetString(POSITION_COMMENT)); - } -//+------------------------------------------------------------------+ -//| Access functions PositionGetInteger(...) | -//+------------------------------------------------------------------+ -bool CPositionInfo::InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const - { - return(PositionGetInteger(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions PositionGetDouble(...) | -//+------------------------------------------------------------------+ -bool CPositionInfo::InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const - { - return(PositionGetDouble(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions PositionGetString(...) | -//+------------------------------------------------------------------+ -bool CPositionInfo::InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const - { - return(PositionGetString(prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Converts the position type to text | -//+------------------------------------------------------------------+ -string CPositionInfo::FormatType(string &str,const uint type) const - { -//--- see the type - switch(type) - { - case POSITION_TYPE_BUY: - str="buy"; - break; - case POSITION_TYPE_SELL: - str="sell"; - break; - default: - str="unknown position type "+(string)type; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Converts the position parameters to text | -//+------------------------------------------------------------------+ -string CPositionInfo::FormatPosition(string &str) const - { - string tmp,type; - long tmp_long; - ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); -//--- set up - string symbol_name=this.Symbol(); - int digits=_Digits; - if(SymbolInfoInteger(symbol_name,SYMBOL_DIGITS,tmp_long)) - digits=(int)tmp_long; -//--- form the position description - if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) - str=StringFormat("#%I64u %s %s %s %s", - Ticket(), - FormatType(type,PositionType()), - DoubleToString(Volume(),2), - symbol_name, - DoubleToString(PriceOpen(),digits+3)); - else - str=StringFormat("%s %s %s %s", - FormatType(type,PositionType()), - DoubleToString(Volume(),2), - symbol_name, - DoubleToString(PriceOpen(),digits+3)); -//--- add stops if there are any - double sl=StopLoss(); - double tp=TakeProfit(); - if(sl!=0.0) - { - tmp=StringFormat(" sl: %s",DoubleToString(sl,digits)); - str+=tmp; - } - if(tp!=0.0) - { - tmp=StringFormat(" tp: %s",DoubleToString(tp,digits)); - str+=tmp; - } -//--- return the result - return(str); - } -//+------------------------------------------------------------------+ -//| Access functions PositionSelect(...) | -//+------------------------------------------------------------------+ -bool CPositionInfo::Select(const string symbol) - { - return(PositionSelect(symbol)); - } -//+------------------------------------------------------------------+ -//| Access functions PositionSelect(...) | -//+------------------------------------------------------------------+ -bool CPositionInfo::SelectByMagic(const string symbol,const ulong magic) - { - bool res=false; - uint total=PositionsTotal(); -//--- - for(uint i=0; i0); - } -//+------------------------------------------------------------------+ -//| Stored position's current state | -//+------------------------------------------------------------------+ -void CPositionInfo::StoreState(void) - { - m_type =PositionType(); - m_volume =Volume(); - m_price =PriceOpen(); - m_stop_loss =StopLoss(); - m_take_profit=TakeProfit(); - } -//+------------------------------------------------------------------+ -//| Check position change | -//+------------------------------------------------------------------+ -bool CPositionInfo::CheckState(void) - { - if(m_type==PositionType() && - m_volume==Volume() && - m_price==PriceOpen() && - m_stop_loss==StopLoss() && - m_take_profit==TakeProfit()) - return(false); -//--- - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/SymbolInfo.mqh b/Include/Trade/SymbolInfo.mqh deleted file mode 100644 index 0a56c68..0000000 --- a/Include/Trade/SymbolInfo.mqh +++ /dev/null @@ -1,789 +0,0 @@ -//+------------------------------------------------------------------+ -//| SymbolInfo.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CSymbolInfo. | -//| Appointment: Class for access to symbol info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CSymbolInfo : public CObject - { -protected: - string m_name; // symbol name - MqlTick m_tick; // structure of tick; - double m_point; // symbol point - double m_tick_value; // symbol tick value - double m_tick_value_profit; // symbol tick value profit - double m_tick_value_loss; // symbol tick value loss - double m_tick_size; // symbol tick size - double m_contract_size; // symbol contract size - double m_lots_min; // symbol lots min - double m_lots_max; // symbol lots max - double m_lots_step; // symbol lots step - double m_lots_limit; // symbol lots limit - double m_swap_long; // symbol swap long - double m_swap_short; // symbol swap short - int m_digits; // symbol digits - int m_order_mode; // symbol valid orders - ENUM_SYMBOL_TRADE_EXECUTION m_trade_execution; // symbol trade execution - ENUM_SYMBOL_CALC_MODE m_trade_calcmode; // symbol trade calcmode - ENUM_SYMBOL_TRADE_MODE m_trade_mode; // symbol trade mode - ENUM_SYMBOL_SWAP_MODE m_swap_mode; // symbol swap mode - ENUM_DAY_OF_WEEK m_swap3; // symbol swap3 - double m_margin_initial; // symbol margin initial - double m_margin_maintenance; // symbol margin maintenance - bool m_margin_hedged_use_leg; // calculate hedged margin using larger leg - double m_margin_hedged; // symbol margin hedged - int m_trade_time_flags; // symbol trade time flags - int m_trade_fill_flags; // symbol trade fill flags - -public: - CSymbolInfo(void); - ~CSymbolInfo(void); - //--- methods of access to protected data - string Name(void) const { return(m_name); } - bool Name(const string name); - bool Refresh(void); - bool RefreshRates(void); - //--- fast access methods to the integer symbol propertyes - bool Select(void) const; - bool Select(const bool select); - bool IsSynchronized(void) const; - //--- volumes - ulong Volume(void) const { return(m_tick.volume); } - ulong VolumeHigh(void) const; - ulong VolumeLow(void) const; - //--- miscellaneous - datetime Time(void) const { return(m_tick.time); } - int Spread(void) const; - bool SpreadFloat(void) const; - int TicksBookDepth(void) const; - //--- trade levels - int StopsLevel(void) const; - int FreezeLevel(void) const; - //--- fast access methods to the double symbol propertyes - //--- bid parameters - double Bid(void) const { return(m_tick.bid); } - double BidHigh(void) const; - double BidLow(void) const; - //--- ask parameters - double Ask(void) const { return(m_tick.ask); } - double AskHigh(void) const; - double AskLow(void) const; - //--- last parameters - double Last(void) const { return(m_tick.last); } - double LastHigh(void) const; - double LastLow(void) const; - //--- fast access methods to the mix symbol propertyes - int OrderMode(void) const { return(m_order_mode); } - //--- terms of trade - ENUM_SYMBOL_CALC_MODE TradeCalcMode(void) const { return(m_trade_calcmode); } - string TradeCalcModeDescription(void) const; - ENUM_SYMBOL_TRADE_MODE TradeMode(void) const { return(m_trade_mode); } - string TradeModeDescription(void) const; - //--- execution terms of trade - ENUM_SYMBOL_TRADE_EXECUTION TradeExecution(void) const { return(m_trade_execution); } - string TradeExecutionDescription(void) const; - //--- swap terms of trade - ENUM_SYMBOL_SWAP_MODE SwapMode(void) const { return(m_swap_mode); } - string SwapModeDescription(void) const; - ENUM_DAY_OF_WEEK SwapRollover3days(void) const { return(m_swap3); } - string SwapRollover3daysDescription(void) const; - //--- dates for futures - datetime StartTime(void) const; - datetime ExpirationTime(void) const; - //--- margin parameters - double MarginInitial(void) const { return(m_margin_initial); } - double MarginMaintenance(void) const { return(m_margin_maintenance); } - bool MarginHedgedUseLeg(void) const { return(m_margin_hedged_use_leg); } - double MarginHedged(void) const { return(m_margin_hedged); } - //--- left for backward compatibility - double MarginLong(void) const { return(0.0); } - double MarginShort(void) const { return(0.0); } - double MarginLimit(void) const { return(0.0); } - double MarginStop(void) const { return(0.0); } - double MarginStopLimit(void) const { return(0.0); } - //--- trade flags parameters - int TradeTimeFlags(void) const { return(m_trade_time_flags); } - int TradeFillFlags(void) const { return(m_trade_fill_flags); } - //--- tick parameters - int Digits(void) const { return(m_digits); } - double Point(void) const { return(m_point); } - double TickValue(void) const { return(m_tick_value); } - double TickValueProfit(void) const { return(m_tick_value_profit); } - double TickValueLoss(void) const { return(m_tick_value_loss); } - double TickSize(void) const { return(m_tick_size); } - //--- lots parameters - double ContractSize(void) const { return(m_contract_size); } - double LotsMin(void) const { return(m_lots_min); } - double LotsMax(void) const { return(m_lots_max); } - double LotsStep(void) const { return(m_lots_step); } - double LotsLimit(void) const { return(m_lots_limit); } - //--- swaps - double SwapLong(void) const { return(m_swap_long); } - double SwapShort(void) const { return(m_swap_short); } - //--- fast access methods to the string symbol propertyes - string CurrencyBase(void) const; - string CurrencyProfit(void) const; - string CurrencyMargin(void) const; - string Bank(void) const; - string Description(void) const; - string Path(void) const; - //--- session information - long SessionDeals(void) const; - long SessionBuyOrders(void) const; - long SessionSellOrders(void) const; - double SessionTurnover(void) const; - double SessionInterest(void) const; - double SessionBuyOrdersVolume(void) const; - double SessionSellOrdersVolume(void) const; - double SessionOpen(void) const; - double SessionClose(void) const; - double SessionAW(void) const; - double SessionPriceSettlement(void) const; - double SessionPriceLimitMin(void) const; - double SessionPriceLimitMax(void) const; - //--- access methods to the API MQL5 functions - bool InfoInteger(const ENUM_SYMBOL_INFO_INTEGER prop_id,long& var) const; - bool InfoDouble(const ENUM_SYMBOL_INFO_DOUBLE prop_id,double& var) const; - bool InfoString(const ENUM_SYMBOL_INFO_STRING prop_id,string& var) const; - bool InfoMarginRate(const ENUM_ORDER_TYPE order_type,double& initial_margin_rate,double& maintenance_margin_rate) const; - //--- service methods - double NormalizePrice(const double price) const; - bool CheckMarketWatch(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CSymbolInfo::CSymbolInfo(void) : m_name(NULL), - m_point(0.0), - m_tick_value(0.0), - m_tick_value_profit(0.0), - m_tick_value_loss(0.0), - m_tick_size(0.0), - m_contract_size(0.0), - m_lots_min(0.0), - m_lots_max(0.0), - m_lots_step(0.0), - m_swap_long(0.0), - m_swap_short(0.0), - m_digits(0), - m_order_mode(0), - m_trade_execution(0), - m_trade_calcmode(0), - m_trade_mode(0), - m_swap_mode(0), - m_swap3(0), - m_margin_initial(0.0), - m_margin_maintenance(0.0), - m_margin_hedged_use_leg(false), - m_margin_hedged(0.0), - m_trade_time_flags(0), - m_trade_fill_flags(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CSymbolInfo::~CSymbolInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Set name | -//+------------------------------------------------------------------+ -bool CSymbolInfo::Name(const string name) - { - string symbol_name=StringLen(name)>0 ? name : _Symbol; -//--- check previous set name - if(m_name!=symbol_name) - { - m_name=symbol_name; - //--- - if(!CheckMarketWatch()) - return(false); - //--- - if(!Refresh()) - { - m_name=""; - Print(__FUNCTION__+": invalid data of symbol '"+symbol_name+"'"); - return(false); - } - } -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Refresh cached data | -//+------------------------------------------------------------------+ -bool CSymbolInfo::Refresh(void) - { - long tmp_long=0; -//--- - if(!SymbolInfoDouble(m_name,SYMBOL_POINT,m_point)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE,m_tick_value)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT,m_tick_value_profit)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_VALUE_LOSS,m_tick_value_loss)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_TICK_SIZE,m_tick_size)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_TRADE_CONTRACT_SIZE,m_contract_size)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MIN,m_lots_min)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_MAX,m_lots_max)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_STEP,m_lots_step)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_VOLUME_LIMIT,m_lots_limit)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_LONG,m_swap_long)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_SWAP_SHORT,m_swap_short)) - return(false); - if(!SymbolInfoInteger(m_name,SYMBOL_DIGITS,tmp_long)) - return(false); - m_digits=(int)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_ORDER_MODE,tmp_long)) - return(false); - m_order_mode=(int)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_EXEMODE,tmp_long)) - return(false); - m_trade_execution=(ENUM_SYMBOL_TRADE_EXECUTION)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_CALC_MODE,tmp_long)) - return(false); - m_trade_calcmode=(ENUM_SYMBOL_CALC_MODE)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_TRADE_MODE,tmp_long)) - return(false); - m_trade_mode=(ENUM_SYMBOL_TRADE_MODE)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_MODE,tmp_long)) - return(false); - m_swap_mode=(ENUM_SYMBOL_SWAP_MODE)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_SWAP_ROLLOVER3DAYS,tmp_long)) - return(false); - m_swap3=(ENUM_DAY_OF_WEEK)tmp_long; - if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_INITIAL,m_margin_initial)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_MAINTENANCE,m_margin_maintenance)) - return(false); - if(!SymbolInfoDouble(m_name,SYMBOL_MARGIN_HEDGED,m_margin_hedged)) - return(false); - if(!SymbolInfoInteger(m_name,SYMBOL_MARGIN_HEDGED_USE_LEG,tmp_long)) - return(false); - m_margin_hedged_use_leg=(bool)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_EXPIRATION_MODE,tmp_long)) - return(false); - m_trade_time_flags=(int)tmp_long; - if(!SymbolInfoInteger(m_name,SYMBOL_FILLING_MODE,tmp_long)) - return(false); - m_trade_fill_flags=(int)tmp_long; -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Refresh cached data | -//+------------------------------------------------------------------+ -bool CSymbolInfo::RefreshRates(void) - { - return(SymbolInfoTick(m_name,m_tick)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SELECT" | -//+------------------------------------------------------------------+ -bool CSymbolInfo::Select(void) const - { - return((bool)SymbolInfoInteger(m_name,SYMBOL_SELECT)); - } -//+------------------------------------------------------------------+ -//| Set the property value "SYMBOL_SELECT" | -//+------------------------------------------------------------------+ -bool CSymbolInfo::Select(const bool select) - { - return(SymbolSelect(m_name,select)); - } -//+------------------------------------------------------------------+ -//| Check synchronize symbol | -//+------------------------------------------------------------------+ -bool CSymbolInfo::IsSynchronized(void) const - { - return(SymbolIsSynchronized(m_name)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_VOLUMEHIGH" | -//+------------------------------------------------------------------+ -ulong CSymbolInfo::VolumeHigh(void) const - { - return(SymbolInfoInteger(m_name,SYMBOL_VOLUMEHIGH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_VOLUMELOW" | -//+------------------------------------------------------------------+ -ulong CSymbolInfo::VolumeLow(void) const - { - return(SymbolInfoInteger(m_name,SYMBOL_VOLUMELOW)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SPREAD" | -//+------------------------------------------------------------------+ -int CSymbolInfo::Spread(void) const - { - return((int)SymbolInfoInteger(m_name,SYMBOL_SPREAD)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SPREAD_FLOAT" | -//+------------------------------------------------------------------+ -bool CSymbolInfo::SpreadFloat(void) const - { - return((bool)SymbolInfoInteger(m_name,SYMBOL_SPREAD_FLOAT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TICKS_BOOKDEPTH" | -//+------------------------------------------------------------------+ -int CSymbolInfo::TicksBookDepth(void) const - { - return((int)SymbolInfoInteger(m_name,SYMBOL_TICKS_BOOKDEPTH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TRADE_STOPS_LEVEL" | -//+------------------------------------------------------------------+ -int CSymbolInfo::StopsLevel(void) const - { - return((int)SymbolInfoInteger(m_name,SYMBOL_TRADE_STOPS_LEVEL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TRADE_FREEZE_LEVEL" | -//+------------------------------------------------------------------+ -int CSymbolInfo::FreezeLevel(void) const - { - return((int)SymbolInfoInteger(m_name,SYMBOL_TRADE_FREEZE_LEVEL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_BIDHIGH" | -//+------------------------------------------------------------------+ -double CSymbolInfo::BidHigh(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_BIDHIGH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_BIDLOW" | -//+------------------------------------------------------------------+ -double CSymbolInfo::BidLow(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_BIDLOW)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_ASKHIGH" | -//+------------------------------------------------------------------+ -double CSymbolInfo::AskHigh(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_ASKHIGH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_ASKLOW" | -//+------------------------------------------------------------------+ -double CSymbolInfo::AskLow(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_ASKLOW)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_LASTHIGH" | -//+------------------------------------------------------------------+ -double CSymbolInfo::LastHigh(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_LASTHIGH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_LASTLOW" | -//+------------------------------------------------------------------+ -double CSymbolInfo::LastLow(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_LASTLOW)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TRADE_CALC_MODE" as string | -//+------------------------------------------------------------------+ -string CSymbolInfo::TradeCalcModeDescription(void) const - { - string str; -//--- - switch(m_trade_calcmode) - { - case SYMBOL_CALC_MODE_FOREX: - str="Calculation of profit and margin for Forex"; - break; - case SYMBOL_CALC_MODE_CFD: - str="Calculation of collateral and earnings for CFD"; - break; - case SYMBOL_CALC_MODE_FUTURES: - str="Calculation of collateral and profits for futures"; - break; - case SYMBOL_CALC_MODE_CFDINDEX: - str="Calculation of collateral and earnings for CFD on indices"; - break; - case SYMBOL_CALC_MODE_CFDLEVERAGE: - str="Calculation of collateral and earnings for the CFD when trading with leverage"; - break; - case SYMBOL_CALC_MODE_EXCH_STOCKS: - str="Calculation for exchange stocks"; - break; - case SYMBOL_CALC_MODE_EXCH_FUTURES: - str="Calculation for exchange futures"; - break; - case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS: - str="Calculation for FORTS futures"; - break; - default: - str="Unknown calculation mode"; - } -//--- result - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TRADE_MODE" as string | -//+------------------------------------------------------------------+ -string CSymbolInfo::TradeModeDescription(void) const - { - string str; -//--- - switch(m_trade_mode) - { - case SYMBOL_TRADE_MODE_DISABLED: - str="Disabled"; - break; - case SYMBOL_TRADE_MODE_LONGONLY: - str="Long only"; - break; - case SYMBOL_TRADE_MODE_SHORTONLY: - str="Short only"; - break; - case SYMBOL_TRADE_MODE_CLOSEONLY: - str="Close only"; - break; - case SYMBOL_TRADE_MODE_FULL: - str="Full access"; - break; - default: - str="Unknown trade mode"; - } -//--- result - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_TRADE_EXEMODE" as string | -//+------------------------------------------------------------------+ -string CSymbolInfo::TradeExecutionDescription(void) const - { - string str; -//--- - switch(m_trade_execution) - { - case SYMBOL_TRADE_EXECUTION_REQUEST: - str="Trading on request"; - break; - case SYMBOL_TRADE_EXECUTION_INSTANT: - str="Trading on live streaming prices"; - break; - case SYMBOL_TRADE_EXECUTION_MARKET: - str="Execution of orders on the market"; - break; - case SYMBOL_TRADE_EXECUTION_EXCHANGE: - str="Exchange execution"; - break; - default: - str="Unknown trade execution"; - } -//--- result - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SWAP_MODE" as string | -//+------------------------------------------------------------------+ -string CSymbolInfo::SwapModeDescription(void) const - { - string str; -//--- - switch(m_swap_mode) - { - case SYMBOL_SWAP_MODE_DISABLED: - str="No swaps"; - break; - case SYMBOL_SWAP_MODE_POINTS: - str="Swaps are calculated in points"; - break; - case SYMBOL_SWAP_MODE_CURRENCY_SYMBOL: - str="Swaps are calculated in base currency"; - break; - case SYMBOL_SWAP_MODE_CURRENCY_MARGIN: - str="Swaps are calculated in margin currency"; - break; - case SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT: - str="Swaps are calculated in deposit currency"; - break; - case SYMBOL_SWAP_MODE_INTEREST_CURRENT: - str="Swaps are calculated as annual interest using the current price"; - break; - case SYMBOL_SWAP_MODE_INTEREST_OPEN: - str="Swaps are calculated as annual interest using the open price"; - break; - case SYMBOL_SWAP_MODE_REOPEN_CURRENT: - str="Swaps are charged by reopening positions at the close price"; - break; - case SYMBOL_SWAP_MODE_REOPEN_BID: - str="Swaps are charged by reopening positions at the Bid price"; - break; - default: - str="Unknown swap mode"; - } -//--- result - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SWAP_ROLLOVER3DAYS" as string | -//+------------------------------------------------------------------+ -string CSymbolInfo::SwapRollover3daysDescription(void) const - { - string str; -//--- - switch(m_swap3) - { - case SUNDAY: - str="Sunday"; - break; - case MONDAY: - str="Monday"; - break; - case TUESDAY: - str="Tuesday"; - break; - case WEDNESDAY: - str="Wednesday"; - break; - case THURSDAY: - str="Thursday"; - break; - case FRIDAY: - str="Friday"; - break; - case SATURDAY: - str="Saturday"; - break; - default: - str="Unknown"; - } -//--- result - return(str); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_START_TIME" | -//+------------------------------------------------------------------+ -datetime CSymbolInfo::StartTime(void) const - { - return((datetime)SymbolInfoInteger(m_name,SYMBOL_START_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_EXPIRATION_TIME" | -//+------------------------------------------------------------------+ -datetime CSymbolInfo::ExpirationTime(void) const - { - return((datetime)SymbolInfoInteger(m_name,SYMBOL_EXPIRATION_TIME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_CURRENCY_BASE" | -//+------------------------------------------------------------------+ -string CSymbolInfo::CurrencyBase(void) const - { - return(SymbolInfoString(m_name,SYMBOL_CURRENCY_BASE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_CURRENCY_PROFIT" | -//+------------------------------------------------------------------+ -string CSymbolInfo::CurrencyProfit(void) const - { - return(SymbolInfoString(m_name,SYMBOL_CURRENCY_PROFIT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_CURRENCY_MARGIN" | -//+------------------------------------------------------------------+ -string CSymbolInfo::CurrencyMargin(void) const - { - return(SymbolInfoString(m_name,SYMBOL_CURRENCY_MARGIN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_BANK" | -//+------------------------------------------------------------------+ -string CSymbolInfo::Bank(void) const - { - return(SymbolInfoString(m_name,SYMBOL_BANK)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_DESCRIPTION" | -//+------------------------------------------------------------------+ -string CSymbolInfo::Description(void) const - { - return(SymbolInfoString(m_name,SYMBOL_DESCRIPTION)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_PATH" | -//+------------------------------------------------------------------+ -string CSymbolInfo::Path(void) const - { - return(SymbolInfoString(m_name,SYMBOL_PATH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_DEALS" | -//+------------------------------------------------------------------+ -long CSymbolInfo::SessionDeals(void) const - { - return(SymbolInfoInteger(m_name,SYMBOL_SESSION_DEALS)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_BUY_ORDERS" | -//+------------------------------------------------------------------+ -long CSymbolInfo::SessionBuyOrders(void) const - { - return(SymbolInfoInteger(m_name,SYMBOL_SESSION_BUY_ORDERS)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_SELL_ORDERS" | -//+------------------------------------------------------------------+ -long CSymbolInfo::SessionSellOrders(void) const - { - return(SymbolInfoInteger(m_name,SYMBOL_SESSION_SELL_ORDERS)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_TURNOVER" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionTurnover(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_TURNOVER)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_INTEREST" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionInterest(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_INTEREST)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_BUY_ORDERS_VOLUME" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionBuyOrdersVolume(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_SELL_ORDERS_VOLUME" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionSellOrdersVolume(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_OPEN" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionOpen(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_OPEN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_CLOSE" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionClose(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_CLOSE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_AW" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionAW(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_AW)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_PRICE_SETTLEMENT" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionPriceSettlement(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_SETTLEMENT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_PRICE_LIMIT_MIN" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionPriceLimitMin(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN)); - } -//+------------------------------------------------------------------+ -//| Get the property value "SYMBOL_SESSION_PRICE_LIMIT_MAX" | -//+------------------------------------------------------------------+ -double CSymbolInfo::SessionPriceLimitMax(void) const - { - return(SymbolInfoDouble(m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX)); - } -//+------------------------------------------------------------------+ -//| Access functions SymbolInfoInteger(...) | -//+------------------------------------------------------------------+ -bool CSymbolInfo::InfoInteger(const ENUM_SYMBOL_INFO_INTEGER prop_id,long &var) const - { - return(SymbolInfoInteger(m_name,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions SymbolInfoDouble(...) | -//+------------------------------------------------------------------+ -bool CSymbolInfo::InfoDouble(const ENUM_SYMBOL_INFO_DOUBLE prop_id,double &var) const - { - return(SymbolInfoDouble(m_name,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions SymbolInfoString(...) | -//+------------------------------------------------------------------+ -bool CSymbolInfo::InfoString(const ENUM_SYMBOL_INFO_STRING prop_id,string &var) const - { - return(SymbolInfoString(m_name,prop_id,var)); - } -//+------------------------------------------------------------------+ -//| Access functions SymbolInfoMarginRate(...) | -//+------------------------------------------------------------------+ -bool CSymbolInfo::InfoMarginRate(const ENUM_ORDER_TYPE order_type,double& initial_margin_rate,double& maintenance_margin_rate) const - { - return(SymbolInfoMarginRate(m_name,order_type,initial_margin_rate,maintenance_margin_rate)); - } -//+------------------------------------------------------------------+ -//| Normalize price | -//+------------------------------------------------------------------+ -double CSymbolInfo::NormalizePrice(const double price) const - { - if(m_tick_size!=0) - return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,m_digits)); -//--- - return(NormalizeDouble(price,m_digits)); - } -//+------------------------------------------------------------------+ -//| Checks if symbol is selected in the MarketWatch | -//| and adds symbol to the MarketWatch, if necessary | -//+------------------------------------------------------------------+ -bool CSymbolInfo::CheckMarketWatch(void) - { -//--- check if symbol is selected in the MarketWatch - if(!Select()) - { - if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL) - { - printf(__FUNCTION__+": Unknown symbol '%s'",m_name); - return(false); - } - if(!Select(true)) - { - printf(__FUNCTION__+": Error adding symbol %d",GetLastError()); - return(false); - } - } -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/TerminalInfo.mqh b/Include/Trade/TerminalInfo.mqh deleted file mode 100644 index 3c24618..0000000 --- a/Include/Trade/TerminalInfo.mqh +++ /dev/null @@ -1,225 +0,0 @@ -//+------------------------------------------------------------------+ -//| TerminalInfo.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CTerminalInfo. | -//| Appointment: Class for access to terminal info. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CTerminalInfo : public CObject - { -public: - CTerminalInfo(void); - ~CTerminalInfo(void); - //--- fast access methods to the integer terminal propertyes - int Build(void) const; - bool IsConnected(void) const; - bool IsDLLsAllowed(void) const; - bool IsTradeAllowed(void) const; - bool IsEmailEnabled(void) const; - bool IsFtpEnabled(void) const; - int MaxBars(void) const; - int CodePage(void) const; - int CPUCores(void) const; - int MemoryPhysical(void) const; - int MemoryTotal(void) const; - int MemoryAvailable(void) const; - int MemoryUsed(void) const; - bool IsX64(void) const; - int OpenCLSupport(void) const; - int DiskSpace(void) const; - //--- fast access methods to the string terminal propertyes - string Language(void) const; - string Name(void) const; - string Company(void) const; - string Path(void) const; - string DataPath(void) const; - string CommonDataPath(void) const; - //--- access methods to the API MQL5 functions - long InfoInteger(const ENUM_TERMINAL_INFO_INTEGER prop_id) const; - string InfoString(const ENUM_TERMINAL_INFO_STRING prop_id) const; - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CTerminalInfo::CTerminalInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTerminalInfo::~CTerminalInfo(void) - { - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_BUILD" | -//+------------------------------------------------------------------+ -int CTerminalInfo::Build(void) const - { - return((int)TerminalInfoInteger(TERMINAL_BUILD)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_CONNECTED" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsConnected(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_CONNECTED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_DLLS_ALLOWED" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsDLLsAllowed(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_DLLS_ALLOWED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_TRADE_ALLOWED" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsTradeAllowed(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_EMAIL_ENABLED" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsEmailEnabled(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_EMAIL_ENABLED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_FTP_ENABLED" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsFtpEnabled(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_FTP_ENABLED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_MAXBARS" | -//+------------------------------------------------------------------+ -int CTerminalInfo::MaxBars(void) const - { - return((int)TerminalInfoInteger(TERMINAL_MAXBARS)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_CODEPAGE" | -//+------------------------------------------------------------------+ -int CTerminalInfo::CodePage(void) const - { - return((int)TerminalInfoInteger(TERMINAL_CODEPAGE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_CPU_CORES" | -//+------------------------------------------------------------------+ -int CTerminalInfo::CPUCores(void) const - { - return((int)TerminalInfoInteger(TERMINAL_CPU_CORES)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_MEMORY_PHYSICAL" | -//+------------------------------------------------------------------+ -int CTerminalInfo::MemoryPhysical(void) const - { - return((int)TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_MEMORY_TOTAL" | -//+------------------------------------------------------------------+ -int CTerminalInfo::MemoryTotal(void) const - { - return((int)TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_MEMORY_AVAILABLE" | -//+------------------------------------------------------------------+ -int CTerminalInfo::MemoryAvailable(void) const - { - return((int)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_MEMORY_USED" | -//+------------------------------------------------------------------+ -int CTerminalInfo::MemoryUsed(void) const - { - return((int)TerminalInfoInteger(TERMINAL_MEMORY_USED)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_X64" | -//+------------------------------------------------------------------+ -bool CTerminalInfo::IsX64(void) const - { - return((bool)TerminalInfoInteger(TERMINAL_X64)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_OPENCL_SUPPORT" | -//+------------------------------------------------------------------+ -int CTerminalInfo::OpenCLSupport(void) const - { - return((int)TerminalInfoInteger(TERMINAL_OPENCL_SUPPORT)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_DISK_SPACE" | -//+------------------------------------------------------------------+ -int CTerminalInfo::DiskSpace(void) const - { - return((int)TerminalInfoInteger(TERMINAL_DISK_SPACE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_LANGUAGE" | -//+------------------------------------------------------------------+ -string CTerminalInfo::Language(void) const - { - return(TerminalInfoString(TERMINAL_LANGUAGE)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_NAME" | -//+------------------------------------------------------------------+ -string CTerminalInfo::Name(void) const - { - return(TerminalInfoString(TERMINAL_NAME)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_COMPANY" | -//+------------------------------------------------------------------+ -string CTerminalInfo::Company(void) const - { - return(TerminalInfoString(TERMINAL_COMPANY)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_PATH" | -//+------------------------------------------------------------------+ -string CTerminalInfo::Path(void) const - { - return(TerminalInfoString(TERMINAL_PATH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_DATA_PATH" | -//+------------------------------------------------------------------+ -string CTerminalInfo::DataPath(void) const - { - return(TerminalInfoString(TERMINAL_DATA_PATH)); - } -//+------------------------------------------------------------------+ -//| Get the property value "TERMINAL_COMMONDATA_PATH" | -//+------------------------------------------------------------------+ -string CTerminalInfo::CommonDataPath(void) const - { - return(TerminalInfoString(TERMINAL_COMMONDATA_PATH)); - } -//+------------------------------------------------------------------+ -//| Access functions AccountInfoInteger(...) | -//+------------------------------------------------------------------+ -long CTerminalInfo::InfoInteger(const ENUM_TERMINAL_INFO_INTEGER prop_id) const - { - return(TerminalInfoInteger(prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions AccountInfoString(...) | -//+------------------------------------------------------------------+ -string CTerminalInfo::InfoString(const ENUM_TERMINAL_INFO_STRING prop_id) const - { - return(TerminalInfoString(prop_id)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Trade/Trade.mqh b/Include/Trade/Trade.mqh deleted file mode 100644 index 399fc20..0000000 --- a/Include/Trade/Trade.mqh +++ /dev/null @@ -1,1710 +0,0 @@ -//+------------------------------------------------------------------+ -//| Trade.mqh | -//| Copyright 2009-2020, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include "OrderInfo.mqh" -#include "HistoryOrderInfo.mqh" -#include "PositionInfo.mqh" -#include "DealInfo.mqh" -//+------------------------------------------------------------------+ -//| enumerations | -//+------------------------------------------------------------------+ -enum ENUM_LOG_LEVELS - { - LOG_LEVEL_NO =0, - LOG_LEVEL_ERRORS=1, - LOG_LEVEL_ALL =2 - }; -//+------------------------------------------------------------------+ -//| Class CTrade. | -//| Appointment: Class trade operations. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CTrade : public CObject - { -protected: - MqlTradeRequest m_request; // request data - MqlTradeResult m_result; // result data - MqlTradeCheckResult m_check_result; // result check data - bool m_async_mode; // trade mode - ulong m_magic; // expert magic number - ulong m_deviation; // deviation default - ENUM_ORDER_TYPE_FILLING m_type_filling; - ENUM_ACCOUNT_MARGIN_MODE m_margin_mode; - //--- - ENUM_LOG_LEVELS m_log_level; - -public: - CTrade(void); - ~CTrade(void); - //--- methods of access to protected data - void LogLevel(const ENUM_LOG_LEVELS log_level) { m_log_level=log_level; } - void Request(MqlTradeRequest &request) const; - ENUM_TRADE_REQUEST_ACTIONS RequestAction(void) const { return(m_request.action); } - string RequestActionDescription(void) const; - ulong RequestMagic(void) const { return(m_request.magic); } - ulong RequestOrder(void) const { return(m_request.order); } - ulong RequestPosition(void) const { return(m_request.position); } - ulong RequestPositionBy(void) const { return(m_request.position_by); } - string RequestSymbol(void) const { return(m_request.symbol); } - double RequestVolume(void) const { return(m_request.volume); } - double RequestPrice(void) const { return(m_request.price); } - double RequestStopLimit(void) const { return(m_request.stoplimit); } - double RequestSL(void) const { return(m_request.sl); } - double RequestTP(void) const { return(m_request.tp); } - ulong RequestDeviation(void) const { return(m_request.deviation); } - ENUM_ORDER_TYPE RequestType(void) const { return(m_request.type); } - string RequestTypeDescription(void) const; - ENUM_ORDER_TYPE_FILLING RequestTypeFilling(void) const { return(m_request.type_filling); } - string RequestTypeFillingDescription(void) const; - ENUM_ORDER_TYPE_TIME RequestTypeTime(void) const { return(m_request.type_time); } - string RequestTypeTimeDescription(void) const; - datetime RequestExpiration(void) const { return(m_request.expiration); } - string RequestComment(void) const { return(m_request.comment); } - //--- - void Result(MqlTradeResult &result) const; - uint ResultRetcode(void) const { return(m_result.retcode); } - string ResultRetcodeDescription(void) const; - int ResultRetcodeExternal(void) const { return(m_result.retcode_external); } - ulong ResultDeal(void) const { return(m_result.deal); } - ulong ResultOrder(void) const { return(m_result.order); } - double ResultVolume(void) const { return(m_result.volume); } - double ResultPrice(void) const { return(m_result.price); } - double ResultBid(void) const { return(m_result.bid); } - double ResultAsk(void) const { return(m_result.ask); } - string ResultComment(void) const { return(m_result.comment); } - //--- - void CheckResult(MqlTradeCheckResult &check_result) const; - uint CheckResultRetcode(void) const { return(m_check_result.retcode); } - string CheckResultRetcodeDescription(void) const; - double CheckResultBalance(void) const { return(m_check_result.balance); } - double CheckResultEquity(void) const { return(m_check_result.equity); } - double CheckResultProfit(void) const { return(m_check_result.profit); } - double CheckResultMargin(void) const { return(m_check_result.margin); } - double CheckResultMarginFree(void) const { return(m_check_result.margin_free); } - double CheckResultMarginLevel(void) const { return(m_check_result.margin_level); } - string CheckResultComment(void) const { return(m_check_result.comment); } - //--- trade methods - void SetAsyncMode(const bool mode) { m_async_mode=mode; } - void SetExpertMagicNumber(const ulong magic) { m_magic=magic; } - void SetDeviationInPoints(const ulong deviation) { m_deviation=deviation; } - void SetTypeFilling(const ENUM_ORDER_TYPE_FILLING filling) { m_type_filling=filling; } - bool SetTypeFillingBySymbol(const string symbol); - void SetMarginMode(void) { m_margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); } - //--- methods for working with positions - bool PositionOpen(const string symbol,const ENUM_ORDER_TYPE order_type,const double volume, - const double price,const double sl,const double tp,const string comment=""); - bool PositionModify(const string symbol,const double sl,const double tp); - bool PositionModify(const ulong ticket,const double sl,const double tp); - bool PositionClose(const string symbol,const ulong deviation=ULONG_MAX); - bool PositionClose(const ulong ticket,const ulong deviation=ULONG_MAX); - bool PositionCloseBy(const ulong ticket,const ulong ticket_by); - bool PositionClosePartial(const string symbol,const double volume,const ulong deviation=ULONG_MAX); - bool PositionClosePartial(const ulong ticket,const double volume,const ulong deviation=ULONG_MAX); - //--- methods for working with pending orders - bool OrderOpen(const string symbol,const ENUM_ORDER_TYPE order_type,const double volume, - const double limit_price,const double price,const double sl,const double tp, - ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,const datetime expiration=0, - const string comment=""); - bool OrderModify(const ulong ticket,const double price,const double sl,const double tp, - const ENUM_ORDER_TYPE_TIME type_time,const datetime expiration,const double stoplimit=0.0); - bool OrderDelete(const ulong ticket); - //--- additions methods - bool Buy(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment=""); - bool Sell(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment=""); - bool BuyLimit(const double volume,const double price,const string symbol=NULL,const double sl=0.0,const double tp=0.0, - const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,const datetime expiration=0,const string comment=""); - bool BuyStop(const double volume,const double price,const string symbol=NULL,const double sl=0.0,const double tp=0.0, - const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,const datetime expiration=0,const string comment=""); - bool SellLimit(const double volume,const double price,const string symbol=NULL,const double sl=0.0,const double tp=0.0, - const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,const datetime expiration=0,const string comment=""); - bool SellStop(const double volume,const double price,const string symbol=NULL,const double sl=0.0,const double tp=0.0, - const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,const datetime expiration=0,const string comment=""); - //--- method check - virtual double CheckVolume(const string symbol,double volume,double price,ENUM_ORDER_TYPE order_type); - virtual bool OrderCheck(const MqlTradeRequest &request,MqlTradeCheckResult &check_result); - virtual bool OrderSend(const MqlTradeRequest &request,MqlTradeResult &result); - //--- info methods - void PrintRequest(void) const; - void PrintResult(void) const; - //--- positions - string FormatPositionType(string &str,const uint type) const; - //--- orders - string FormatOrderType(string &str,const uint type) const; - string FormatOrderStatus(string &str,const uint status) const; - string FormatOrderTypeFilling(string &str,const uint type) const; - string FormatOrderTypeTime(string &str,const uint type) const; - string FormatOrderPrice(string &str,const double price_order,const double price_trigger,const uint digits) const; - //--- trade request - string FormatRequest(string &str,const MqlTradeRequest &request) const; - string FormatRequestResult(string &str,const MqlTradeRequest &request,const MqlTradeResult &result) const; - -protected: - bool FillingCheck(const string symbol); - bool ExpirationCheck(const string symbol); - bool OrderTypeCheck(const string symbol); - void ClearStructures(void); - bool IsStopped(const string function); - bool IsHedging(void) const { return(m_margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING); } - //--- position select depending on netting or hedging - bool SelectPosition(const string symbol); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CTrade::CTrade(void) : m_async_mode(false), - m_magic(0), - m_deviation(10), - m_type_filling(ORDER_FILLING_FOK), - m_log_level(LOG_LEVEL_ERRORS) - { - SetMarginMode(); -//--- initialize protected data - ClearStructures(); -//--- check programm mode - if(MQL5InfoInteger(MQL5_TESTING)) - m_log_level=LOG_LEVEL_ALL; - if(MQL5InfoInteger(MQL5_OPTIMIZATION)) - m_log_level=LOG_LEVEL_NO; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTrade::~CTrade(void) - { - } -//+------------------------------------------------------------------+ -//| Get the request structure | -//+------------------------------------------------------------------+ -void CTrade::Request(MqlTradeRequest &request) const - { - request.action =m_request.action; - request.magic =m_request.magic; - request.order =m_request.order; - request.symbol =m_request.symbol; - request.volume =m_request.volume; - request.price =m_request.price; - request.stoplimit =m_request.stoplimit; - request.sl =m_request.sl; - request.tp =m_request.tp; - request.deviation =m_request.deviation; - request.type =m_request.type; - request.type_filling=m_request.type_filling; - request.type_time =m_request.type_time; - request.expiration =m_request.expiration; - request.comment =m_request.comment; - request.position =m_request.position; - request.position_by =m_request.position_by; - } -//+------------------------------------------------------------------+ -//| Get the trade action as string | -//+------------------------------------------------------------------+ -string CTrade::RequestActionDescription(void) const - { - string str; -//--- - FormatRequest(str,m_request); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the order type as string | -//+------------------------------------------------------------------+ -string CTrade::RequestTypeDescription(void) const - { - string str; -//--- - FormatOrderType(str,(uint)m_request.order); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the order type filling as string | -//+------------------------------------------------------------------+ -string CTrade::RequestTypeFillingDescription(void) const - { - string str; -//--- - FormatOrderTypeFilling(str,m_request.type_filling); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the order type time as string | -//+------------------------------------------------------------------+ -string CTrade::RequestTypeTimeDescription(void) const - { - string str; -//--- - FormatOrderTypeTime(str,m_request.type_time); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the result structure | -//+------------------------------------------------------------------+ -void CTrade::Result(MqlTradeResult &result) const - { - result.retcode =m_result.retcode; - result.deal =m_result.deal; - result.order =m_result.order; - result.volume =m_result.volume; - result.price =m_result.price; - result.bid =m_result.bid; - result.ask =m_result.ask; - result.comment =m_result.comment; - result.request_id=m_result.request_id; - result.retcode_external=m_result.retcode_external; - } -//+------------------------------------------------------------------+ -//| Get the retcode value as string | -//+------------------------------------------------------------------+ -string CTrade::ResultRetcodeDescription(void) const - { - string str; -//--- - FormatRequestResult(str,m_request,m_result); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Get the check result structure | -//+------------------------------------------------------------------+ -void CTrade::CheckResult(MqlTradeCheckResult &check_result) const - { -//--- copy structure - check_result.retcode =m_check_result.retcode; - check_result.balance =m_check_result.balance; - check_result.equity =m_check_result.equity; - check_result.profit =m_check_result.profit; - check_result.margin =m_check_result.margin; - check_result.margin_free =m_check_result.margin_free; - check_result.margin_level=m_check_result.margin_level; - check_result.comment =m_check_result.comment; - } -//+------------------------------------------------------------------+ -//| Get the check retcode value as string | -//+------------------------------------------------------------------+ -string CTrade::CheckResultRetcodeDescription(void) const - { - string str; - MqlTradeResult result; -//--- - result.retcode=m_check_result.retcode; - FormatRequestResult(str,m_request,result); -//--- - return(str); - } -//+------------------------------------------------------------------+ -//| Open position | -//+------------------------------------------------------------------+ -bool CTrade::PositionOpen(const string symbol,const ENUM_ORDER_TYPE order_type,const double volume, - const double price,const double sl,const double tp,const string comment) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- clean - ClearStructures(); -//--- check - if(order_type!=ORDER_TYPE_BUY && order_type!=ORDER_TYPE_SELL) - { - m_result.retcode=TRADE_RETCODE_INVALID; - m_result.comment="Invalid order type"; - return(false); - } -//--- setting request - m_request.action =TRADE_ACTION_DEAL; - m_request.symbol =symbol; - m_request.magic =m_magic; - m_request.volume =volume; - m_request.type =order_type; - m_request.price =price; - m_request.sl =sl; - m_request.tp =tp; - m_request.deviation=m_deviation; -//--- check order type - if(!OrderTypeCheck(symbol)) - return(false); -//--- check filling - if(!FillingCheck(symbol)) - return(false); - m_request.comment=comment; -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Modify specified opened position | -//+------------------------------------------------------------------+ -bool CTrade::PositionModify(const string symbol,const double sl,const double tp) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- check position existence - if(!SelectPosition(symbol)) - return(false); -//--- clean - ClearStructures(); -//--- setting request - m_request.action =TRADE_ACTION_SLTP; - m_request.symbol =symbol; - m_request.magic =m_magic; - m_request.sl =sl; - m_request.tp =tp; - m_request.position=PositionGetInteger(POSITION_TICKET); -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Modify specified opened position | -//+------------------------------------------------------------------+ -bool CTrade::PositionModify(const ulong ticket,const double sl,const double tp) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- check position existence - if(!PositionSelectByTicket(ticket)) - return(false); -//--- clean - ClearStructures(); -//--- setting request - m_request.action =TRADE_ACTION_SLTP; - m_request.position=ticket; - m_request.symbol =PositionGetString(POSITION_SYMBOL); - m_request.magic =m_magic; - m_request.sl =sl; - m_request.tp =tp; -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Close specified opened position | -//+------------------------------------------------------------------+ -bool CTrade::PositionClose(const string symbol,const ulong deviation) - { - bool partial_close=false; - int retry_count =10; - uint retcode =TRADE_RETCODE_REJECT; -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); - do - { - //--- check - if(SelectPosition(symbol)) - { - if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) - { - //--- prepare request for close BUY position - m_request.type =ORDER_TYPE_SELL; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID); - } - else - { - //--- prepare request for close SELL position - m_request.type =ORDER_TYPE_BUY; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK); - } - } - else - { - //--- position not found - m_result.retcode=retcode; - return(false); - } - //--- setting request - m_request.action =TRADE_ACTION_DEAL; - m_request.symbol =symbol; - m_request.volume =PositionGetDouble(POSITION_VOLUME); - m_request.magic =m_magic; - m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; - //--- check volume - double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX); - if(m_request.volume>max_volume) - { - m_request.volume=max_volume; - partial_close=true; - } - else - partial_close=false; - //--- hedging? just send order - if(IsHedging()) - { - m_request.position=PositionGetInteger(POSITION_TICKET); - return(OrderSend(m_request,m_result)); - } - //--- order send - if(!OrderSend(m_request,m_result)) - { - if(--retry_count!=0) - continue; - if(retcode==TRADE_RETCODE_DONE_PARTIAL) - m_result.retcode=retcode; - return(false); - } - //--- WARNING. If position volume exceeds the maximum volume allowed for deal, - //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, - //--- but partially. It is decreased by the maximum volume allowed for deal. - if(m_async_mode) - break; - retcode=TRADE_RETCODE_DONE_PARTIAL; - if(partial_close) - Sleep(1000); - } - while(partial_close); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Close specified opened position | -//+------------------------------------------------------------------+ -bool CTrade::PositionClose(const ulong ticket,const ulong deviation) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- check position existence - if(!PositionSelectByTicket(ticket)) - return(false); - string symbol=PositionGetString(POSITION_SYMBOL); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); -//--- check - if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) - { - //--- prepare request for close BUY position - m_request.type =ORDER_TYPE_SELL; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID); - } - else - { - //--- prepare request for close SELL position - m_request.type =ORDER_TYPE_BUY; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK); - } -//--- setting request - m_request.action =TRADE_ACTION_DEAL; - m_request.position =ticket; - m_request.symbol =symbol; - m_request.volume =PositionGetDouble(POSITION_VOLUME); - m_request.magic =m_magic; - m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; -//--- close position - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Close one position by other | -//+------------------------------------------------------------------+ -bool CTrade::PositionCloseBy(const ulong ticket,const ulong ticket_by) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- check hedging mode - if(!IsHedging()) - return(false); -//--- check position existence - if(!PositionSelectByTicket(ticket)) - return(false); - string symbol=PositionGetString(POSITION_SYMBOL); - ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); - if(!PositionSelectByTicket(ticket_by)) - return(false); - string symbol_by=PositionGetString(POSITION_SYMBOL); - ENUM_POSITION_TYPE type_by=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); -//--- check positions - if(type==type_by) - return(false); - if(symbol!=symbol_by) - return(false); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); -//--- setting request - m_request.action =TRADE_ACTION_CLOSE_BY; - m_request.position =ticket; - m_request.position_by=ticket_by; - m_request.magic =m_magic; -//--- close position - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Partial close specified opened position (for hedging mode only) | -//+------------------------------------------------------------------+ -bool CTrade::PositionClosePartial(const string symbol,const double volume,const ulong deviation) - { - uint retcode=TRADE_RETCODE_REJECT; -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- for hedging mode only - if(!IsHedging()) - return(false); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); -//--- check - if(SelectPosition(symbol)) - { - if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) - { - //--- prepare request for close BUY position - m_request.type =ORDER_TYPE_SELL; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID); - } - else - { - //--- prepare request for close SELL position - m_request.type =ORDER_TYPE_BUY; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK); - } - } - else - { - //--- position not found - m_result.retcode=retcode; - return(false); - } -//--- check volume - double position_volume=PositionGetDouble(POSITION_VOLUME); - if(position_volume>volume) - position_volume=volume; -//--- setting request - m_request.action =TRADE_ACTION_DEAL; - m_request.symbol =symbol; - m_request.volume =position_volume; - m_request.magic =m_magic; - m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; - m_request.position =PositionGetInteger(POSITION_TICKET); -//--- hedging? just send order - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Partial close specified opened position (for hedging mode only) | -//+------------------------------------------------------------------+ -bool CTrade::PositionClosePartial(const ulong ticket,const double volume,const ulong deviation) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- for hedging mode only - if(!IsHedging()) - return(false); -//--- check position existence - if(!PositionSelectByTicket(ticket)) - return(false); - string symbol=PositionGetString(POSITION_SYMBOL); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); -//--- check - if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) - { - //--- prepare request for close BUY position - m_request.type =ORDER_TYPE_SELL; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID); - } - else - { - //--- prepare request for close SELL position - m_request.type =ORDER_TYPE_BUY; - m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK); - } -//--- check volume - double position_volume=PositionGetDouble(POSITION_VOLUME); - if(position_volume>volume) - position_volume=volume; -//--- setting request - m_request.action =TRADE_ACTION_DEAL; - m_request.position =ticket; - m_request.symbol =symbol; - m_request.volume =position_volume; - m_request.magic =m_magic; - m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; -//--- close position - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Installation pending order | -//+------------------------------------------------------------------+ -bool CTrade::OrderOpen(const string symbol,const ENUM_ORDER_TYPE order_type,const double volume,const double limit_price, - const double price,const double sl,const double tp, - ENUM_ORDER_TYPE_TIME type_time,const datetime expiration,const string comment) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- clean - ClearStructures(); -//--- check filling - if(!FillingCheck(symbol)) - return(false); -//--- check order type - if(order_type==ORDER_TYPE_BUY || order_type==ORDER_TYPE_SELL) - { - m_result.retcode=TRADE_RETCODE_INVALID; - m_result.comment="Invalid order type"; - return(false); - } -//--- check order expiration - if(type_time==ORDER_TIME_GTC && expiration==0) - { - int exp=(int)SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_MODE); - if((exp&SYMBOL_EXPIRATION_GTC)!=SYMBOL_EXPIRATION_GTC) - { - //--- if you place order for an unlimited time and if placing of such orders is prohibited - //--- try to place order with expiration at the end of the day - if((exp&SYMBOL_EXPIRATION_DAY)!=SYMBOL_EXPIRATION_DAY) - { - //--- if even this is not possible - error - Print(__FUNCTION__,": Error: Unable to place order without explicitly specified expiration time"); - m_result.retcode=TRADE_RETCODE_INVALID_EXPIRATION; - m_result.comment="Invalid expiration type"; - return(false); - } - type_time=ORDER_TIME_DAY; - } - } -//--- setting request - m_request.action =TRADE_ACTION_PENDING; - m_request.symbol =symbol; - m_request.magic =m_magic; - m_request.volume =volume; - m_request.type =order_type; - m_request.stoplimit =limit_price; - m_request.price =price; - m_request.sl =sl; - m_request.tp =tp; - m_request.type_time =type_time; - m_request.expiration =expiration; -//--- check order type - if(!OrderTypeCheck(symbol)) - return(false); -//--- check filling - if(!FillingCheck(symbol)) - { - m_result.retcode=TRADE_RETCODE_INVALID_FILL; - Print(__FUNCTION__+": Invalid filling type"); - return(false); - } -//--- check expiration - if(!ExpirationCheck(symbol)) - { - m_result.retcode=TRADE_RETCODE_INVALID_EXPIRATION; - Print(__FUNCTION__+": Invalid expiration type"); - return(false); - } - m_request.comment=comment; -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Modify specified pending order | -//+------------------------------------------------------------------+ -bool CTrade::OrderModify(const ulong ticket,const double price,const double sl,const double tp, - const ENUM_ORDER_TYPE_TIME type_time,const datetime expiration,const double stoplimit) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- check order existence - if(!OrderSelect(ticket)) - return(false); -//--- clean - ClearStructures(); -//--- setting request - m_request.symbol =OrderGetString(ORDER_SYMBOL); - m_request.action =TRADE_ACTION_MODIFY; - m_request.magic =m_magic; - m_request.order =ticket; - m_request.price =price; - m_request.stoplimit =stoplimit; - m_request.sl =sl; - m_request.tp =tp; - m_request.type_time =type_time; - m_request.expiration =expiration; -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Delete specified pending order | -//+------------------------------------------------------------------+ -bool CTrade::OrderDelete(const ulong ticket) - { -//--- check stopped - if(IsStopped(__FUNCTION__)) - return(false); -//--- clean - ClearStructures(); -//--- setting request - m_request.action =TRADE_ACTION_REMOVE; - m_request.magic =m_magic; - m_request.order =ticket; -//--- action and return the result - return(OrderSend(m_request,m_result)); - } -//+------------------------------------------------------------------+ -//| Output full information of request to log | -//+------------------------------------------------------------------+ -void CTrade::PrintRequest(void) const - { - if(m_log_level0.0) - volume=stepvol*(MathFloor(lots/stepvol)-1); - //--- - double minvol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); - if(volumeLOG_LEVEL_ERRORS) - PrintFormat(__FUNCTION__+": %s [%s]",FormatRequest(action,request),FormatRequestResult(fmt,request,result)); - } - else - { - if(m_log_level>LOG_LEVEL_NO) - PrintFormat(__FUNCTION__+": %s [%s]",FormatRequest(action,request),FormatRequestResult(fmt,request,result)); - } -//--- return the result - return(res); - } -//+------------------------------------------------------------------+ -//| Position select depending on netting or hedging | -//+------------------------------------------------------------------+ -bool CTrade::SelectPosition(const string symbol) - { - bool res=false; -//--- - if(IsHedging()) - { - uint total=PositionsTotal(); - for(uint i=0; i -#include -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -void RaiseException(uint exception_code,uint exception_flags,uint number_of_arguments,const ulong &arguments[]); -int UnhandledExceptionFilter(EXCEPTION_POINTERS &exception_info); -PVOID SetUnhandledExceptionFilter(PVOID top_level_exception_filter); -uint GetLastError(void); -void SetLastError(uint err_code); -uint GetErrorMode(void); -uint SetErrorMode(uint mode); -PVOID AddVectoredExceptionHandler(uint first,PVOID handler); -uint RemoveVectoredExceptionHandler(PVOID handle); -PVOID AddVectoredContinueHandler(uint first,PVOID handler); -uint RemoveVectoredContinueHandler(PVOID handle); -void RestoreLastError(uint err_code); -void RaiseFailFastException(EXCEPTION_RECORD &exception_record,CONTEXT &context_record,uint flags); -void FatalAppExitW(uint action,const string message_text); -uint GetThreadErrorMode(void); -int SetThreadErrorMode(uint new_mode,uint& old_mode); -#import diff --git a/Include/WinAPI/fileapi.mqh b/Include/WinAPI/fileapi.mqh deleted file mode 100644 index eec5408..0000000 --- a/Include/WinAPI/fileapi.mqh +++ /dev/null @@ -1,146 +0,0 @@ -//+------------------------------------------------------------------+ -//| fileapi.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include - -//--- -enum STREAM_INFO_LEVELS - { - FindStreamInfoStandard, - FindStreamInfoMaxInfoLevel - }; -//--- -struct BY_HANDLE_FILE_INFORMATION - { - uint dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - uint dwVolumeSerialNumber; - uint nFileSizeHigh; - uint nFileSizeLow; - uint nNumberOfLinks; - uint nFileIndexHigh; - uint nFileIndexLow; - }; -//--- -struct CREATEFILE2_EXTENDED_PARAMETERS - { - uint dwSize; - uint dwFileAttributes; - uint dwFileFlags; - uint dwSecurityQosFlags; - PVOID lpSecurityAttributes; - HANDLE hTemplateFile; - }; -//--- -struct FILE_ATTRIBUTE_DATA - { - uint dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - uint nFileSizeHigh; - uint nFileSizeLow; - }; -//--- -struct FIND_STREAM_DATA - { - long StreamSize; - short cStreamName[MAX_PATH+36]; - }; -//--- -struct FIND_DATAW - { - uint dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - uint nFileSizeHigh; - uint nFileSizeLow; - uint dwReserved0; - uint dwReserved1; - short cFileName[MAX_PATH]; - short cAlternateFileName[14]; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int AreFileApisANSI(void); -int CompareFileTime(FILETIME &file_time1,FILETIME &file_time2); -int CreateDirectoryW(const string path_name,PVOID security_attributes); -HANDLE CreateFile2(const string file_name,uint desired_access,uint share_mode,uint creation_disposition,CREATEFILE2_EXTENDED_PARAMETERS &create_ex_params); -HANDLE CreateFileW(const string file_name,uint desired_access,uint share_mode,PVOID security_attributes,uint creation_disposition,uint flags_and_attributes,HANDLE template_file); -int DefineDosDeviceW(uint flags,const string device_name,const string target_path); -int DeleteFileW(const string file_name); -int DeleteVolumeMountPointW(const string volume_mount_point); -int FileTimeToLocalFileTime(FILETIME &file_time,FILETIME &local_file_time); -int FindClose(HANDLE find_file); -int FindCloseChangeNotification(HANDLE change_handle); -HANDLE FindFirstChangeNotificationW(const string path_name,int watch_subtree,uint notify_filter); -HANDLE FindFirstFileExW(const string file_name,FINDEX_INFO_LEVELS info_level_id,FIND_DATAW &find_file_data,FINDEX_SEARCH_OPS search_op,PVOID search_filter,uint additional_flags); -HANDLE FindFirstFileNameW(const string file_name,uint flags,uint &StringLength,ushort &LinkName[]); -HANDLE FindFirstFileW(const string file_name,FIND_DATAW &find_file_data); -HANDLE FindFirstStreamW(const string file_name,STREAM_INFO_LEVELS InfoLevel,FIND_STREAM_DATA &find_stream_data,uint flags); -HANDLE FindFirstVolumeW(ushort &volume_name[],uint &buffer_length); -int FindNextChangeNotification(HANDLE change_handle); -int FindNextFileNameW(HANDLE find_stream,uint &StringLength,ushort &LinkName[]); -int FindNextFileW(HANDLE find_file,FIND_DATAW &find_file_data); -int FindNextStreamW(HANDLE find_stream,FIND_STREAM_DATA &find_stream_data); -int FindNextVolumeW(HANDLE find_volume,ushort &volume_name[],uint &buffer_length); -int FindVolumeClose(HANDLE find_volume); -int FlushFileBuffers(HANDLE file); -uint GetCompressedFileSizeW(const string file_name,uint &file_size_high); -int GetDiskFreeSpaceExW(const string directory_name,ulong &free_bytes_available_to_caller,ulong &total_number_of_bytes,ulong &total_number_of_free_bytes); -int GetDiskFreeSpaceW(const string root_path_name,uint §ors_per_cluster,uint &bytes_per_sector,uint &number_of_free_clusters,uint &total_number_of_clusters); -uint GetDriveTypeW(const string root_path_name); -int GetFileAttributesExW(const string file_name,GET_FILEEX_INFO_LEVELS info_level_id,FILE_ATTRIBUTE_DATA &file_information); -uint GetFileAttributesW(const string file_name); -int GetFileInformationByHandle(HANDLE file,BY_HANDLE_FILE_INFORMATION &file_information); -uint GetFileSize(HANDLE file,uint &file_size_high); -int GetFileSizeEx(HANDLE file,long &file_size); -int GetFileTime(HANDLE file,FILETIME &creation_time,FILETIME &last_access_time,FILETIME &last_write_time); -uint GetFileType(HANDLE file); -uint GetFinalPathNameByHandleW(HANDLE file,ushort &file_path[],uint file_path,uint flags); -uint GetFullPathNameW(const string file_name,uint buffer_length,ushort &buffer[],ushort &file_part[]); -uint GetLogicalDrives(void); -uint GetLogicalDriveStringsW(uint buffer_length,ushort &buffer[]); -uint GetLongPathNameW(const string short_path,string &long_path,uint buffer); -uint GetShortPathNameW(const string long_path,string &short_path,uint buffer); -uint GetTempFileNameW(const string path_name,const string prefix_string,uint unique,ushort &temp_file_name[]); -uint GetTempPathW(uint buffer_length,ushort &buffer[]); -int GetVolumeInformationByHandleW(HANDLE file,ushort &volume_name_buffer[],uint volume_name_size,uint &volume_serial_number,uint &maximum_component_length,uint &file_system_flags,ushort &file_system_name_buffer[],uint file_system_name_size); -int GetVolumeInformationW(const string root_path_name,ushort &volume_name_buffer[],uint volume_name_size,uint &volume_serial_number,uint &maximum_component_length,uint &file_system_flags,ushort &file_system_name_buffer[],uint file_system_name_size); -int GetVolumeNameForVolumeMountPointW(const string volume_mount_point,string volume_name,uint buffer_length); -int GetVolumePathNamesForVolumeNameW(const string volume_name,string volume_path_names,uint buffer_length,uint &return_length); -int GetVolumePathNameW(const string file_name,ushort &volume_path_name[],uint buffer_length); -int LocalFileTimeToFileTime(FILETIME &local_file_time,FILETIME &file_time); -int LockFile(HANDLE file,uint file_offset_low,uint file_offset_high,uint number_of_bytes_to_lock_low,uint number_of_bytes_to_lock_high); -int LockFileEx(HANDLE file,uint flags,uint reserved,uint number_of_bytes_to_lock_low,uint number_of_bytes_to_lock_high,OVERLAPPED &overlapped); -uint QueryDosDeviceW(const string device_name,ushort &target_path[],uint max); -int ReadFile(HANDLE file,ushort &buffer[],uint number_of_bytes_to_read,uint &number_of_bytes_read,OVERLAPPED &overlapped); -int ReadFile(HANDLE file,ushort &buffer[],uint number_of_bytes_to_read,uint &number_of_bytes_read,PVOID overlapped); -int ReadFileScatter(HANDLE file,FILE_SEGMENT_ELEMENT &segment_array[],uint number_of_bytes_to_read,uint &reserved,OVERLAPPED &overlapped); -int ReadFileScatter(HANDLE file,FILE_SEGMENT_ELEMENT &segment_array[],uint number_of_bytes_to_read,uint &reserved,PVOID overlapped); -int RemoveDirectoryW(const string path_name); -int SetEndOfFile(HANDLE file); -void SetFileApisToANSI(void); -void SetFileApisToOEM(void); -int SetFileAttributesW(const string file_name,uint file_attributes); -int SetFileInformationByHandle(HANDLE file,FILE_INFO_BY_HANDLE_CLASS FileInformationClass,FILE_INFO &file_information,uint buffer_size); -int SetFileIoOverlappedRange(HANDLE FileHandle,uchar &OverlappedRangeStart,uint Length); -uint SetFilePointer(HANDLE file,long distance_to_move,long &distance_to_move_high,uint move_method); -int SetFilePointerEx(HANDLE file,long distance_to_move,long &new_file_pointer,uint move_method); -int SetFileTime(HANDLE file,FILETIME &creation_time,FILETIME &last_access_time,FILETIME &last_write_time); -int SetFileValidData(HANDLE file,long ValidDataLength); -int UnlockFile(HANDLE file,uint file_offset_low,uint file_offset_high,uint number_of_bytes_to_unlock_low,uint number_of_bytes_to_unlock_high); -int UnlockFileEx(HANDLE file,uint reserved,uint number_of_bytes_to_unlock_low,uint number_of_bytes_to_unlock_high,OVERLAPPED &overlapped); -int WriteFile(HANDLE file,const ushort &buffer[],uint number_of_bytes_to_write,uint &number_of_bytes_written,OVERLAPPED &overlapped); -int WriteFile(HANDLE file,const ushort &buffer[],uint number_of_bytes_to_write,uint &number_of_bytes_written,PVOID overlapped); -int WriteFileGather(HANDLE file,FILE_SEGMENT_ELEMENT &segment_array[],uint number_of_bytes_to_write,uint &reserved,OVERLAPPED &overlapped); -int WriteFileGather(HANDLE file,FILE_SEGMENT_ELEMENT &segment_array[],uint number_of_bytes_to_write,uint &reserved,PVOID overlapped); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/handleapi.mqh b/Include/WinAPI/handleapi.mqh deleted file mode 100644 index a03b303..0000000 --- a/Include/WinAPI/handleapi.mqh +++ /dev/null @@ -1,21 +0,0 @@ -//+------------------------------------------------------------------+ -//| handleapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int CloseHandle(HANDLE object); -int DuplicateHandle(HANDLE source_process_handle,HANDLE source_handle,HANDLE target_process_handle,HANDLE &target_handle,uint desired_access,int inherit_handle,uint options); -int GetHandleInformation(HANDLE object,uint& flags); -int SetHandleInformation(HANDLE object,uint mask,uint flags); -#import - -#import "kernelbase.dll" -int CompareObjectHandles(HANDLE first_object_handle, HANDLE second_object_handle); -#import -//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/Include/WinAPI/libloaderapi.mqh b/Include/WinAPI/libloaderapi.mqh deleted file mode 100644 index 58f0f09..0000000 --- a/Include/WinAPI/libloaderapi.mqh +++ /dev/null @@ -1,47 +0,0 @@ -//+------------------------------------------------------------------+ -//| libloaderapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include - -//--- -struct ENUMUILANG - { - uint NumOfEnumUILang; - uint SizeOfEnumUIBuffer; - PVOID EnumUIBuffer; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int DisableThreadLibraryCalls(HANDLE lib_module); -HANDLE FindResourceExW(HANDLE module,const string type,const string name,ushort language); -int FindStringOrdinal(uint find_string_ordinal_flags,const string string_source,int source,const string string_value,int value,int ignore_case); -int FreeLibrary(HANDLE lib_module); -void FreeLibraryAndExitThread(HANDLE lib_module,uint exit_code); -int FreeResource(HANDLE res_data); -uint GetModuleFileNameW(HANDLE module,ushort &filename[],uint size); -HANDLE GetModuleHandleW(const string module_name); -int GetModuleHandleExW(uint flags,const string module_name,HANDLE &module); -PVOID GetProcAddress(HANDLE module,uchar &proc_name[]); -HANDLE LoadLibraryExW(const string lib_file_name,HANDLE file,uint flags); -HANDLE LoadResource(HANDLE module,HANDLE res_info); -PVOID LockResource(HANDLE res_data); -uint SizeofResource(HANDLE module,HANDLE res_info); -PVOID AddDllDirectory(const string new_directory); -int RemoveDllDirectory(PVOID cookie); -int SetDefaultDllDirectories(uint directory_flags); -int EnumResourceLanguagesExW(HANDLE module,const string type,const string name,PVOID enum_func,long param,uint flags,ushort lang_id); -int EnumResourceNamesExW(HANDLE module,const string type,PVOID enum_func,long param,uint flags,ushort lang_id); -int EnumResourceTypesExW(HANDLE module,PVOID enum_func,long param,uint flags,ushort lang_id); -HANDLE FindResourceW(HANDLE module,const string name,const string type); -HANDLE LoadLibraryW(const string lib_file_name); -int EnumResourceNamesW(HANDLE module,const string type,PVOID enum_func,long param); -#import - -#import "user32.dll" -int LoadStringW(HANDLE instance,uint id,string buffer,int buffer_max); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/memoryapi.mqh b/Include/WinAPI/memoryapi.mqh deleted file mode 100644 index 1dfa008..0000000 --- a/Include/WinAPI/memoryapi.mqh +++ /dev/null @@ -1,85 +0,0 @@ -//+------------------------------------------------------------------+ -//| memoryapi.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//--- -enum MEMORY_RESOURCE_NOTIFICATION_TYPE - { - LowMemoryResourceNotification, - HighMemoryResourceNotification - }; -//--- -enum OFFER_PRIORITY - { - VmOfferPriorityVeryLow=1, - VmOfferPriorityLow, - VmOfferPriorityBelowNormal, - VmOfferPriorityNormal - }; -//--- -enum WIN32_MEMORY_INFORMATION_CLASS - { - MemoryRegionInfo - }; -//--- -struct WIN32_MEMORY_RANGE_ENTRY - { - PVOID VirtualAddress; - ulong NumberOfBytes; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int AllocateUserPhysicalPages(HANDLE hProcess,ulong &NumberOfPages,ulong &PageArray[]); -int AllocateUserPhysicalPagesNuma(HANDLE hProcess,ulong &NumberOfPages,ulong &PageArray[],uint nndPreferred); -HANDLE CreateFileMappingFromApp(HANDLE hFile,PVOID SecurityAttributes,uint PageProtection,ulong MaximumSize,const string Name); -HANDLE CreateFileMappingNumaW(HANDLE hFile,PVOID lpFileMappingAttributes,uint flProtect,uint dwMaximumSizeHigh,uint dwMaximumSizeLow,const string lpName,uint nndPreferred); -HANDLE CreateFileMappingW(HANDLE hFile,PVOID lpFileMappingAttributes,uint flProtect,uint dwMaximumSizeHigh,uint dwMaximumSizeLow,const string lpName); -HANDLE CreateMemoryResourceNotification(MEMORY_RESOURCE_NOTIFICATION_TYPE NotificationType); -uint DiscardVirtualMemory(PVOID VirtualAddress,ulong Size); -int FlushViewOfFile(const PVOID lpBaseAddress,ulong dwNumberOfBytesToFlush); -int FreeUserPhysicalPages(HANDLE hProcess,ulong &NumberOfPages,ulong &PageArray[]); -ulong GetLargePageMinimum(void); -int GetMemoryErrorHandlingCapabilities(uint &Capabilities); -int GetProcessWorkingSetSizeEx(HANDLE hProcess,ulong &lpMinimumWorkingSetSize,ulong &lpMaximumWorkingSetSize,uint &Flags); -int GetSystemFileCacheSize(ulong &lpMinimumFileCacheSize,ulong &lpMaximumFileCacheSize,uint &lpFlags); -uint GetWriteWatch(uint dwFlags,PVOID lpBaseAddress,ulong dwRegionSize,PVOID &lpAddresses[],uint &lpdwCount,uint &lpdwGranularity); -int MapUserPhysicalPages(PVOID VirtualAddress,ulong &NumberOfPages,ulong &PageArray[]); -PVOID MapViewOfFile(HANDLE hFileMappingObject,uint dwDesiredAccess,uint dwFileOffsetHigh,uint dwFileOffsetLow,ulong dwNumberOfBytesToMap); -PVOID MapViewOfFileEx(HANDLE hFileMappingObject,uint dwDesiredAccess,uint dwFileOffsetHigh,uint dwFileOffsetLow,ulong dwNumberOfBytesToMap,PVOID lpBaseAddress); -PVOID MapViewOfFileFromApp(HANDLE hFileMappingObject,uint DesiredAccess,ulong FileOffset,ulong NumberOfBytesToMap); -uint OfferVirtualMemory(PVOID VirtualAddress,ulong Size,OFFER_PRIORITY Priority); -HANDLE OpenFileMappingW(uint dwDesiredAccess,int bInheritHandle,const string lpName); -int PrefetchVirtualMemory(HANDLE hProcess,uint &NumberOfEntries,WIN32_MEMORY_RANGE_ENTRY &VirtualAddresses,uint Flags); -int QueryMemoryResourceNotification(HANDLE ResourceNotificationHandle,int &ResourceState); -int ReadProcessMemory(HANDLE hProcess,const PVOID lpBaseAddress,PVOID lpBuffer,ulong nSize,ulong &lpNumberOfBytesRead); -uint ReclaimVirtualMemory(const PVOID VirtualAddress,ulong Size); -PVOID RegisterBadMemoryNotification(PVOID Callback); -uint ResetWriteWatch(PVOID lpBaseAddress,ulong dwRegionSize); -int SetProcessWorkingSetSizeEx(HANDLE hProcess,ulong dwMinimumWorkingSetSize,ulong dwMaximumWorkingSetSize,uint Flags); -int SetSystemFileCacheSize(ulong MinimumFileCacheSize,ulong MaximumFileCacheSize,uint Flags); -int UnmapViewOfFile(const PVOID lpBaseAddress); -int UnmapViewOfFileEx(PVOID BaseAddress,uint UnmapFlags); -int UnregisterBadMemoryNotification(PVOID RegistrationHandle); -PVOID VirtualAlloc(PVOID lpAddress,ulong dwSize,uint flAllocationType,uint flProtect); -PVOID VirtualAllocEx(HANDLE hProcess,PVOID lpAddress,ulong dwSize,uint flAllocationType,uint flProtect); -PVOID VirtualAllocExNuma(HANDLE hProcess,PVOID lpAddress,ulong dwSize,uint flAllocationType,uint flProtect,uint nndPreferred); -int VirtualFree(PVOID lpAddress,ulong dwSize,uint dwFreeType); -int VirtualFreeEx(HANDLE hProcess,PVOID lpAddress,ulong dwSize,uint dwFreeType); -int VirtualLock(PVOID lpAddress,ulong dwSize); -int VirtualProtect(PVOID lpAddress,ulong dwSize,uint flNewProtect,uint &lpflOldProtect); -int VirtualProtectEx(HANDLE hProcess,PVOID lpAddress,ulong dwSize,uint flNewProtect,uint &lpflOldProtect); -ulong VirtualQuery(const PVOID lpAddress,MEMORY_BASIC_INFORMATION &lpBuffer,ulong dwLength); -ulong VirtualQueryEx(HANDLE hProcess,const PVOID lpAddress,MEMORY_BASIC_INFORMATION &lpBuffer,ulong dwLength); -int VirtualUnlock(PVOID lpAddress,ulong dwSize); -int WriteProcessMemory(HANDLE hProcess,PVOID lpBaseAddress,PVOID lpBuffer,ulong nSize,ulong &lpNumberOfBytesWritten); -int WriteProcessMemory(HANDLE hProcess,PVOID lpBaseAddress,uchar &lpBuffer[],ulong nSize,ulong &lpNumberOfBytesWritten); -int WriteProcessMemory(HANDLE hProcess,uchar &lpBaseAddress[],PVOID lpBuffer,ulong nSize,ulong &lpNumberOfBytesWritten); -int WriteProcessMemory(HANDLE hProcess,uchar &lpBaseAddress[],uchar &lpBuffer[],ulong nSize,ulong &lpNumberOfBytesWritten); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/processenv.mqh b/Include/WinAPI/processenv.mqh deleted file mode 100644 index bbf83bb..0000000 --- a/Include/WinAPI/processenv.mqh +++ /dev/null @@ -1,27 +0,0 @@ -//+------------------------------------------------------------------+ -//| processenv.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int SetEnvironmentStringsW(string new_environment); -HANDLE GetStdHandle(uint std_handle); -int SetStdHandle(uint std_handle,HANDLE handle); -int SetStdHandleEx(uint std_handle,HANDLE handle,HANDLE &prev_value); -string GetCommandLineW(void); -string GetEnvironmentStringsW(void); -int FreeEnvironmentStringsW(string v); -uint GetEnvironmentVariableW(const string name,ushort &buffer[],uint size); -int SetEnvironmentVariableW(const string name,const string value); -uint ExpandEnvironmentStringsW(const string src,string dst,uint size); -int SetCurrentDirectoryW(const string path_name); -uint GetCurrentDirectoryW(uint buffer_length,ushort &buffer[]); -uint GetCurrentDirectoryW(uint buffer_length,string &buffer); -uint SearchPathW(const string path,const string file_name,const string extension,uint buffer_length,ushort &buffer[],string &file_part); -int NeedCurrentDirectoryForExePathW(const string exe_name); -#import diff --git a/Include/WinAPI/processthreadsapi.mqh b/Include/WinAPI/processthreadsapi.mqh deleted file mode 100644 index bc81fa1..0000000 --- a/Include/WinAPI/processthreadsapi.mqh +++ /dev/null @@ -1,202 +0,0 @@ -//+------------------------------------------------------------------+ -//| processthreadsapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -//--- -enum THREAD_INFORMATION_CLASS - { - ThreadMemoryPriority, - ThreadAbsoluteCpuPriority, - ThreadDynamicCodePolicy, - ThreadPowerThrottling, - ThreadInformationClassMax - }; -//--- -enum PROCESS_INFORMATION_CLASS - { - ProcessMemoryPriority, - ProcessMemoryExhaustionInfo, - ProcessAppMemoryInfo, - ProcessInPrivateInfo, - ProcessPowerThrottling, - ProcessReservedValue1, - ProcessTelemetryCoverageInfo, - ProcessProtectionLevelInfo, - ProcessInformationClassMax - }; -//--- -enum PROCESS_MEMORY_EXHAUSTION_TYPE - { - PMETypeFailFastOnCommitFailure, - PMETypeMax - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -//--- -struct PROCESS_INFORMATION - { - HANDLE hProcess; - HANDLE hThread; - uint dwProcessId; - uint dwThreadId; - }; -//--- -struct STARTUPINFOW - { - uint cb; - string lpReserved; - string lpDesktop; - string lpTitle; - uint dwX; - uint dwY; - uint dwXSize; - uint dwYSize; - uint dwXCountChars; - uint dwYCountChars; - uint dwFillAttribute; - uint dwFlags; - ushort wShowWindow; - ushort cbReserved2; - PVOID lpReserved2; - HANDLE hStdInput; - HANDLE hStdOutput; - HANDLE hStdError; - }; -//--- -struct MEMORY_PRIORITY_INFORMATION - { - uint MemoryPriority; - }; -//--- -struct THREAD_POWER_THROTTLING_STATE - { - uint Version; - uint ControlMask; - uint StateMask; - }; -//--- -struct APP_MEMORY_INFORMATION - { - ulong AvailableCommit; - ulong PrivateCommitUsage; - ulong PeakPrivateCommitUsage; - ulong TotalCommitUsage; - }; -//--- -struct PROCESS_MEMORY_EXHAUSTION_INFO - { - ushort Version; - ushort Reserved; - PROCESS_MEMORY_EXHAUSTION_TYPE Type; - ulong Value; - }; -//--- -struct PROCESS_POWER_THROTTLING_STATE - { - uint Version; - uint ControlMask; - uint StateMask; - }; -//--- -struct PROCESS_PROTECTION_LEVEL_INFORMATION - { - uint ProtectionLevel; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -uint QueueUserAPC(PVOID apc,HANDLE thread,ulong data); -int GetProcessTimes(HANDLE process,FILETIME &creation_time,FILETIME &exit_time,FILETIME &kernel_time,FILETIME &user_time); -HANDLE GetCurrentProcess(void); -uint GetCurrentProcessId(void); -void ExitProcess(uint exit_code); -int TerminateProcess(HANDLE process,uint exit_code); -int GetExitCodeProcess(HANDLE process,uint &exit_code); -int SwitchToThread(void); -HANDLE CreateThread(PVOID thread_attributes,ulong stack_size,PVOID start_address,PVOID parameter,uint creation_flags,uint &thread_id); -HANDLE CreateRemoteThread(HANDLE process,PVOID thread_attributes,ulong stack_size,PVOID start_address,PVOID parameter,uint creation_flags,uint &thread_id); -HANDLE GetCurrentThread(void); -uint GetCurrentThreadId(void); -HANDLE OpenThread(uint desired_access,int inherit_handle,uint thread_id); -int SetThreadPriority(HANDLE thread,int priority); -int SetThreadPriorityBoost(HANDLE thread,int disable_priority_boost); -int GetThreadPriorityBoost(HANDLE thread,int &disable_priority_boost); -int GetThreadPriority(HANDLE thread); -void ExitThread(uint exit_code); -int TerminateThread(HANDLE thread,uint exit_code); -int GetExitCodeThread(HANDLE thread,uint &exit_code); -uint SuspendThread(HANDLE thread); -uint ResumeThread(HANDLE thread); -uint TlsAlloc(void); -PVOID TlsGetValue(uint tls_index); -int TlsSetValue(uint tls_index,PVOID tls_value); -int TlsFree(uint tls_index); -int CreateProcessW(const string application_name,string command_line,PVOID process_attributes,PVOID thread_attributes,int inherit_handles,uint creation_flags,PVOID environment,const string current_directory,STARTUPINFOW &startup_info,PROCESS_INFORMATION &process_information); -int SetProcessShutdownParameters(uint level,uint flags); -uint GetProcessVersion(uint process_id); -void GetStartupInfoW(STARTUPINFOW &startup_info); -int SetPriorityClass(HANDLE process,uint priority_class); -uint GetPriorityClass(HANDLE process); -int SetThreadStackGuarantee(ulong stack_size_in_bytes); -int ProcessIdToSessionId(uint process_id,uint &session_id); -uint GetProcessId(HANDLE process); -uint GetThreadId(HANDLE thread); -void FlushProcessWriteBuffers(void); -uint GetProcessIdOfThread(HANDLE thread); -int InitializeProcThreadAttributeList(PVOID attribute_list,uint attribute_count,uint flags,ulong &size); -void DeleteProcThreadAttributeList(PVOID attribute_list); -int SetProcessAffinityUpdateMode(HANDLE process,uint flags); -int QueryProcessAffinityUpdateMode(HANDLE process,uint &flags); -int UpdateProcThreadAttribute(PVOID attribute_list,uint flags,uint attribute,PVOID value,ulong size,PVOID previous_value,ulong &return_size); -HANDLE CreateRemoteThreadEx(HANDLE process,PVOID thread_attributes,ulong stack_size,PVOID start_address,PVOID parameter,uint creation_flags,PVOID attribute_list,uint &thread_id); -void GetCurrentThreadStackLimits(ulong &low_limit,ulong &high_limit); -int GetThreadContext(HANDLE thread,CONTEXT &context); -int GetProcessMitigationPolicy(HANDLE process,PROCESS_MITIGATION_POLICY mitigation_policy,PVOID buffer,ulong length); -int SetThreadContext(HANDLE thread,const CONTEXT &context); -int SetProcessMitigationPolicy(PROCESS_MITIGATION_POLICY mitigation_policy,PVOID buffer,ulong length); -int FlushInstructionCache(HANDLE process,const PVOID base_address,ulong size); -int GetThreadTimes(HANDLE thread,FILETIME &creation_time,FILETIME &exit_time,FILETIME &kernel_time,FILETIME &user_time); -HANDLE OpenProcess(uint desired_access,int inherit_handle,uint process_id); -int IsProcessorFeaturePresent(uint processor_feature); -int GetProcessHandleCount(HANDLE process,uint &handle_count); -uint GetCurrentProcessorNumber(void); -int SetThreadIdealProcessorEx(HANDLE thread,PROCESSOR_NUMBER &ideal_processor,PROCESSOR_NUMBER &previous_ideal_processor); -int GetThreadIdealProcessorEx(HANDLE thread,PROCESSOR_NUMBER &ideal_processor); -void GetCurrentProcessorNumberEx(PROCESSOR_NUMBER &proc_number); -int GetProcessPriorityBoost(HANDLE process,int &disable_priority_boost); -int SetProcessPriorityBoost(HANDLE process,int disable_priority_boost); -int GetThreadIOPendingFlag(HANDLE thread,int &io_is_pending); -int GetSystemTimes(FILETIME &idle_time,FILETIME &kernel_time,FILETIME &user_time); -int GetThreadInformation(HANDLE thread,THREAD_INFORMATION_CLASS thread_information_class,PVOID thread_information,uint thread_information_size); -int SetThreadInformation(HANDLE thread,THREAD_INFORMATION_CLASS thread_information_class,PVOID thread_information,uint thread_information_size); -int IsProcessCritical(HANDLE process,int &critical); -int SetProtectedPolicy(const GUID &policy_guid,ulong policy_value,ulong &old_policy_value); -int QueryProtectedPolicy(const GUID &policy_guid,ulong &policy_value); -uint SetThreadIdealProcessor(HANDLE thread,uint ideal_processor); -int SetProcessInformation(HANDLE process,PROCESS_INFORMATION_CLASS process_information_class,PVOID process_information,uint process_information_size); -int GetProcessInformation(HANDLE process,PROCESS_INFORMATION_CLASS process_information_class,PVOID process_information,uint process_information_size); -int GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION &information,uint buffer_length,ulong returned_length,HANDLE process,uint flags); -int GetProcessDefaultCpuSets(HANDLE process,ulong &cpu_set_ids,uint cpu_set_id_count,ulong required_id_count); -int SetProcessDefaultCpuSets(HANDLE process,const uint &cpu_set_ids,uint cpu_set_id_count); -int GetThreadSelectedCpuSets(HANDLE thread,ulong &cpu_set_ids,uint cpu_set_id_count,ulong required_id_count); -int SetThreadSelectedCpuSets(HANDLE thread,const uint &cpu_set_ids,uint cpu_set_id_count); -int GetProcessShutdownParameters(uint &level,uint &flags); -int SetThreadDescription(HANDLE thread,const string thread_description); -int GetThreadDescription(HANDLE thread,string &thread_description); -#import -#import "advapi32.dll" -int CreateProcessAsUserW(HANDLE token,const string application_name,string command_line,PVOID process_attributes,PVOID thread_attributes,int inherit_handles,uint creation_flags,PVOID environment,const string current_directory,STARTUPINFOW &startup_info,PROCESS_INFORMATION &process_information); -int SetThreadToken(HANDLE thread,HANDLE token); -int OpenProcessToken(HANDLE process_handle,uint desired_access,HANDLE &token_handle); -int OpenThreadToken(HANDLE thread_handle,uint desired_access,int open_as_self,HANDLE &token_handle); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/securitybaseapi.mqh b/Include/WinAPI/securitybaseapi.mqh deleted file mode 100644 index f27838b..0000000 --- a/Include/WinAPI/securitybaseapi.mqh +++ /dev/null @@ -1,119 +0,0 @@ -//+------------------------------------------------------------------+ -//| securitybaseapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "advapi32.dll" -int AccessCheck(SECURITY_DESCRIPTOR &security_descriptor,HANDLE client_token,uint desired_access,GENERIC_MAPPING &generic_mapping,PRIVILEGE_SET &privilege_set,uint &privilege_set_length,uint &granted_access,int &access_status); -int AccessCheckAndAuditAlarmW(const string subsystem_name,PVOID handle_id,string object_type_name,string object_name,SECURITY_DESCRIPTOR &security_descriptor,uint desired_access,GENERIC_MAPPING &generic_mapping,int object_creation,uint &granted_access,int &access_status,int &generate_on_close); -int AccessCheckByType(SECURITY_DESCRIPTOR &security_descriptor,SID &principal_self_sid,HANDLE client_token,uint desired_access,OBJECT_TYPE_LIST &object_type_list,uint object_type_list_length,GENERIC_MAPPING &generic_mapping,PRIVILEGE_SET &privilege_set,uint &privilege_set_length,uint &granted_access,int &access_status); -int AccessCheckByTypeResultList(SECURITY_DESCRIPTOR &security_descriptor,SID &principal_self_sid,HANDLE client_token,uint desired_access,OBJECT_TYPE_LIST &object_type_list,uint object_type_list_length,GENERIC_MAPPING &generic_mapping,PRIVILEGE_SET &privilege_set,uint &privilege_set_length,uint &granted_access_list,uint &access_status_list); -int AccessCheckByTypeAndAuditAlarmW(const string subsystem_name,PVOID handle_id,const string object_type_name,const string object_name,SECURITY_DESCRIPTOR &security_descriptor,SID &principal_self_sid,uint desired_access,AUDIT_EVENT_TYPE audit_type,uint flags,OBJECT_TYPE_LIST &object_type_list,uint object_type_list_length,GENERIC_MAPPING &generic_mapping,int object_creation,uint &granted_access,int &access_status,int &generate_on_close); -int AccessCheckByTypeResultListAndAuditAlarmW(const string subsystem_name,PVOID handle_id,const string object_type_name,const string object_name,SECURITY_DESCRIPTOR &security_descriptor,SID &principal_self_sid,uint desired_access,AUDIT_EVENT_TYPE audit_type,uint flags,OBJECT_TYPE_LIST &object_type_list,uint object_type_list_length,GENERIC_MAPPING &generic_mapping,int object_creation,uint &granted_access_list,uint &access_status_list,int &generate_on_close); -int AccessCheckByTypeResultListAndAuditAlarmByHandleW(const string subsystem_name,PVOID handle_id,HANDLE client_token,const string object_type_name,const string object_name,SECURITY_DESCRIPTOR &security_descriptor,SID &principal_self_sid,uint desired_access,AUDIT_EVENT_TYPE audit_type,uint flags,OBJECT_TYPE_LIST &object_type_list,uint object_type_list_length,GENERIC_MAPPING &generic_mapping,int object_creation,uint &granted_access_list,uint &access_status_list,int &generate_on_close); -int AddAccessAllowedAce(ACL &acl,uint ace_revision,uint access_mask,SID &sid); -int AddAccessAllowedAceEx(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,SID &sid); -int AddAccessAllowedObjectAce(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,GUID &object_type_guid,GUID &inherited_object_type_guid,SID &sid); -int AddAccessDeniedAce(ACL &acl,uint ace_revision,uint access_mask,SID &sid); -int AddAccessDeniedAceEx(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,SID &sid); -int AddAccessDeniedObjectAce(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,GUID &object_type_guid,GUID &inherited_object_type_guid,SID &sid); -int AddAce(ACL &acl,uint ace_revision,uint starting_ace_index,PVOID ace_list,uint ace_list_length); -int AddAuditAccessAce(ACL &acl,uint ace_revision,uint access_mask,SID &sid,int audit_success,int audit_failure); -int AddAuditAccessAceEx(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,SID &sid,int audit_success,int audit_failure); -int AddAuditAccessObjectAce(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,GUID &object_type_guid,GUID &inherited_object_type_guid,SID &sid,int audit_success,int audit_failure); -int AddMandatoryAce(ACL &acl,uint ace_revision,uint ace_flags,uint mandatory_policy,SID &label_sid); -int AdjustTokenGroups(HANDLE token_handle,int reset_to_default,TOKEN_GROUPS &new_state,uint buffer_length,TOKEN_GROUPS &previous_state,uint &return_length); -int AdjustTokenPrivileges(HANDLE token_handle,int disable_all_privileges,TOKEN_PRIVILEGES &new_state,uint buffer_length,TOKEN_PRIVILEGES &previous_state,uint &return_length); -int AllocateAndInitializeSid(SID_IDENTIFIER_AUTHORITY &identifier_authority,uchar sub_authority_count,uint sub_authority0,uint sub_authority1,uint sub_authority2,uint sub_authority3,uint sub_authority4,uint sub_authority5,uint sub_authority6,uint sub_authority7,SID &sid); -int AllocateLocallyUniqueId(LUID &luid); -int AreAllAccessesGranted(uint granted_access,uint desired_access); -int AreAnyAccessesGranted(uint granted_access,uint desired_access); -int CheckTokenMembership(HANDLE token_handle,SID &sid_to_check,int &is_member); -int ConvertToAutoInheritPrivateObjectSecurity(SECURITY_DESCRIPTOR &parent_descriptor,SECURITY_DESCRIPTOR ¤t_security_descriptor,SECURITY_DESCRIPTOR &new_security_descriptor,GUID &object_type,uchar is_directory_object,GENERIC_MAPPING &generic_mapping); -int CopySid(uint destination_sid_length,SID &destination_sid,SID &source_sid); -int CreatePrivateObjectSecurity(SECURITY_DESCRIPTOR &parent_descriptor,SECURITY_DESCRIPTOR &creator_descriptor,SECURITY_DESCRIPTOR &new_descriptor,int is_directory_object,HANDLE token,GENERIC_MAPPING &generic_mapping); -int CreatePrivateObjectSecurityEx(SECURITY_DESCRIPTOR &parent_descriptor,SECURITY_DESCRIPTOR &creator_descriptor,SECURITY_DESCRIPTOR &new_descriptor,GUID &object_type,int is_container_object,uint auto_inherit_flags,HANDLE token,GENERIC_MAPPING &generic_mapping); -int CreatePrivateObjectSecurityWithMultipleInheritance(SECURITY_DESCRIPTOR &parent_descriptor,SECURITY_DESCRIPTOR &creator_descriptor,SECURITY_DESCRIPTOR &new_descriptor,GUID &object_types,uint guid_count,int is_container_object,uint auto_inherit_flags,HANDLE token,GENERIC_MAPPING &generic_mapping); -int CreateRestrictedToken(HANDLE existing_token_handle,uint flags,uint disable_sid_count,SID_AND_ATTRIBUTES &sids_to_disable,uint delete_privilege_count,LUID_AND_ATTRIBUTES &privileges_to_delete,uint restricted_sid_count,SID_AND_ATTRIBUTES &sids_to_restrict,HANDLE &new_token_handle); -int CreateWellKnownSid(WELL_KNOWN_SID_TYPE well_known_sid_type,SID &domain_sid,SID &sid,uint &sid); -int EqualDomainSid(SID &sid1,SID &sid2,int &equal); -int DeleteAce(ACL &acl,uint ace_index); -int DestroyPrivateObjectSecurity(SECURITY_DESCRIPTOR &object_descriptor); -int DuplicateToken(HANDLE existing_token_handle,SECURITY_IMPERSONATION_LEVEL impersonation_level,HANDLE &duplicate_token_handle); -int DuplicateTokenEx(HANDLE existing_token,uint desired_access,PVOID token_attributes,SECURITY_IMPERSONATION_LEVEL impersonation_level,TOKEN_TYPE token_type,HANDLE &new_token); -int EqualPrefixSid(SID &sid1,SID &sid2); -int EqualSid(SID &sid1,SID &sid2); -int FindFirstFreeAce(ACL &acl,PVOID &ace); -PVOID FreeSid(SID &sid); -int GetAce(ACL &acl,uint ace_index,PVOID &ace); -int GetAclInformation(ACL &acl,PVOID acl_information,uint acl_information_length,ACL_INFORMATION_CLASS acl_information_class); -int GetFileSecurityW(const string file_name,uint requested_information,SECURITY_DESCRIPTOR &security_descriptor,uint length,uint &length_needed); -int GetKernelObjectSecurity(HANDLE handle,uint requested_information,SECURITY_DESCRIPTOR &security_descriptor,uint length,uint &length_needed); -uint GetLengthSid(SID &sid); -int GetPrivateObjectSecurity(SECURITY_DESCRIPTOR &object_descriptor,uint security_information,SECURITY_DESCRIPTOR &resultant_descriptor,uint descriptor_length,uint &return_length); -int GetSecurityDescriptorControl(SECURITY_DESCRIPTOR &security_descriptor,ushort &control,uint &revision); -int GetSecurityDescriptorDacl(SECURITY_DESCRIPTOR &security_descriptor,int &dacl_present,ACL &dacl,int &dacl_defaulted); -int GetSecurityDescriptorGroup(SECURITY_DESCRIPTOR &security_descriptor,SID &group,int &group_defaulted); -uint GetSecurityDescriptorLength(SECURITY_DESCRIPTOR &security_descriptor); -int GetSecurityDescriptorOwner(SECURITY_DESCRIPTOR &security_descriptor,SID &owner,int &owner_defaulted); -uint GetSecurityDescriptorRMControl(SECURITY_DESCRIPTOR &security_descriptor,uchar &rm_control); -int GetSecurityDescriptorSacl(SECURITY_DESCRIPTOR &security_descriptor,int &sacl_present,ACL &sacl,int &sacl_defaulted); -PVOID GetSidIdentifierAuthority(SID &sid); -uint GetSidLengthRequired(uchar sub_authority_count); -PVOID GetSidSubAuthority(SID &sid,uint sub_authority); -PVOID GetSidSubAuthorityCount(SID &sid); -int GetTokenInformation(HANDLE token_handle,TOKEN_INFORMATION_CLASS token_information_class,PVOID &token_information,uint token_information_length,uint &return_length); -int GetWindowsAccountDomainSid(SID &sid,SID &domain_sid,uint &domain_sid); -int ImpersonateAnonymousToken(HANDLE thread_handle); -int ImpersonateLoggedOnUser(HANDLE token); -int ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL impersonation_level); -int InitializeAcl(ACL &acl,uint acl_length,uint acl_revision); -int InitializeSecurityDescriptor(SECURITY_DESCRIPTOR &security_descriptor,uint revision); -int InitializeSid(SID &sid,SID_IDENTIFIER_AUTHORITY &identifier_authority,uchar sub_authority_count); -int IsTokenRestricted(HANDLE token_handle); -int IsValidAcl(ACL &acl); -int IsValidSecurityDescriptor(SECURITY_DESCRIPTOR &security_descriptor); -int IsValidSid(SID &sid); -int IsWellKnownSid(SID &sid,WELL_KNOWN_SID_TYPE well_known_sid_type); -int MakeAbsoluteSD(SECURITY_DESCRIPTOR &self_relative_security_descriptor,SECURITY_DESCRIPTOR &absolute_security_descriptor,uint &absolute_security_descriptor_size,ACL &dacl,uint &dacl_size,ACL &sacl,uint &sacl_size,SID &owner,uint &owner_size,SID &primary_group,uint &primary_group_size); -int MakeSelfRelativeSD(SECURITY_DESCRIPTOR &absolute_security_descriptor,SECURITY_DESCRIPTOR &self_relative_security_descriptor,uint &buffer_length); -void MapGenericMask(uint &access_mask,GENERIC_MAPPING &generic_mapping); -int ObjectCloseAuditAlarmW(const string subsystem_name,PVOID handle_id,int generate_on_close); -int ObjectDeleteAuditAlarmW(const string subsystem_name,PVOID handle_id,int generate_on_close); -int ObjectOpenAuditAlarmW(const string subsystem_name,PVOID handle_id,string object_type_name,string object_name,SECURITY_DESCRIPTOR &security_descriptor,HANDLE client_token,uint desired_access,uint granted_access,PRIVILEGE_SET &privileges,int object_creation,int access_granted,int &generate_on_close); -int ObjectPrivilegeAuditAlarmW(const string subsystem_name,PVOID handle_id,HANDLE client_token,uint desired_access,PRIVILEGE_SET &privileges,int access_granted); -int PrivilegeCheck(HANDLE client_token,PRIVILEGE_SET &required_privileges,int &result); -int PrivilegedServiceAuditAlarmW(const string subsystem_name,const string service_name,HANDLE client_token,PRIVILEGE_SET &privileges,int access_granted); -void QuerySecurityAccessMask(uint security_information,uint &desired_access); -int RevertToSelf(void); -int SetAclInformation(ACL &acl,PVOID acl_information,uint acl_information_length,ACL_INFORMATION_CLASS acl_information_class); -int SetFileSecurityW(const string file_name,uint security_information,SECURITY_DESCRIPTOR &security_descriptor); -int SetKernelObjectSecurity(HANDLE handle,uint security_information,SECURITY_DESCRIPTOR &security_descriptor); -int SetPrivateObjectSecurity(uint security_information,SECURITY_DESCRIPTOR &modification_descriptor,SECURITY_DESCRIPTOR &objects_security_descriptor,GENERIC_MAPPING &generic_mapping,HANDLE token); -int SetPrivateObjectSecurityEx(uint security_information,SECURITY_DESCRIPTOR &modification_descriptor,SECURITY_DESCRIPTOR &objects_security_descriptor,uint auto_inherit_flags,GENERIC_MAPPING &generic_mapping,HANDLE token); -void SetSecurityAccessMask(uint security_information,uint &desired_access); -int SetSecurityDescriptorControl(SECURITY_DESCRIPTOR &security_descriptor,ushort control_bits_of_interest,ushort control_bits_to_set); -int SetSecurityDescriptorDacl(SECURITY_DESCRIPTOR &security_descriptor,int dacl_present,ACL &dacl,int dacl_defaulted); -int SetSecurityDescriptorGroup(SECURITY_DESCRIPTOR &security_descriptor,SID &group,int group_defaulted); -int SetSecurityDescriptorOwner(SECURITY_DESCRIPTOR &security_descriptor,SID &owner,int owner_defaulted); -uint SetSecurityDescriptorRMControl(SECURITY_DESCRIPTOR &security_descriptor,uchar &rm_control); -int SetSecurityDescriptorSacl(SECURITY_DESCRIPTOR &security_descriptor,int sacl_present,ACL &sacl,int sacl_defaulted); -int SetTokenInformation(HANDLE token_handle,TOKEN_INFORMATION_CLASS token_information_class,PVOID token_information,uint token_information_length); -int CveEventWrite(const string cve_id,const string additional_details); -#import - -#import "kernel32.dll" -int AddResourceAttributeAce(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,SID &sid,CLAIM_SECURITY_ATTRIBUTES_INFORMATION &attribute_info,uint &return_length); -int AddScopedPolicyIDAce(ACL &acl,uint ace_revision,uint ace_flags,uint access_mask,SID &sid); -int CheckTokenCapability(HANDLE token_handle,SID &capability_sid_to_check,int &has_capability); -int GetAppContainerAce(ACL &acl,uint starting_ace_index,PVOID &app_container_ace,uint &app_container_ace_index); -int CheckTokenMembershipEx(HANDLE token_handle,SID &sid_to_check,uint flags,int &is_member); -int SetCachedSigningLevel(HANDLE &source_files,uint source_file_count,uint flags,HANDLE target_file); -int GetCachedSigningLevel(HANDLE file,ulong flags,ulong signing_level,uchar &thumbprint[],ulong thumbprint_size,ulong thumbprint_algorithm); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/sysinfoapi.mqh b/Include/WinAPI/sysinfoapi.mqh deleted file mode 100644 index 5bbc515..0000000 --- a/Include/WinAPI/sysinfoapi.mqh +++ /dev/null @@ -1,95 +0,0 @@ -//+------------------------------------------------------------------+ -//| sysinfoapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//--- -enum COMPUTER_NAME_FORMAT - { - ComputerNameNetBIOS, - ComputerNameDnsHostname, - ComputerNameDnsDomain, - ComputerNameDnsFullyQualified, - ComputerNamePhysicalNetBIOS, - ComputerNamePhysicalDnsHostname, - ComputerNamePhysicalDnsDomain, - ComputerNamePhysicalDnsFullyQualified, - ComputerNameMax - }; -//--- -struct DUMMYSTRUCTNAME - { - uint dwOemId; - ushort wProcessorArchitecture; - ushort wReserved; - }; -//--- -struct MEMORYSTATUSEX - { - uint dwLength; - uint dwMemoryLoad; - ulong ullTotalPhys; - ulong ullAvailPhys; - ulong ullTotalPageFile; - ulong ullAvailPageFile; - ulong ullTotalVirtual; - ulong ullAvailVirtual; - ulong ullAvailExtendedVirtual; - }; -//--- -struct SYSTEM_INFO - { - uint dwOemId; - uint dwPageSize; - PVOID lpMinimumApplicationAddress; - PVOID lpMaximumApplicationAddress; - ulong dwActiveProcessorMask; - uint dwNumberOfProcessors; - uint dwProcessorType; - uint dwAllocationGranularity; - ushort wProcessorLevel; - ushort wProcessorRevision; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int GlobalMemoryStatusEx(MEMORYSTATUSEX &buffer); -void GetSystemInfo(SYSTEM_INFO &system_info); -void GetSystemTime(SYSTEMTIME &system_time); -void GetSystemTimeAsFileTime(FILETIME &system_time_as_file_time); -void GetLocalTime(SYSTEMTIME &system_time); -uint GetVersion(void); -int SetLocalTime(const SYSTEMTIME &system_time); -uint GetTickCount(void); -ulong GetTickCount64(void); -int GetSystemTimeAdjustment(uint &time_adjustment,uint &time_increment,int &time_adjustment_disabled); -uint GetSystemDirectoryW(ushort &buffer[],uint size); -uint GetWindowsDirectoryW(ushort &buffer[],uint size); -uint GetSystemWindowsDirectoryW(ushort &buffer[],uint size); -int GetComputerNameExW(COMPUTER_NAME_FORMAT name_type,ushort &buffer[],uint &size); -int SetComputerNameExW(COMPUTER_NAME_FORMAT name_type,const string buffer); -int SetSystemTime(const SYSTEMTIME &system_time); -int GetVersionExW(OSVERSIONINFOW &version_information); -int GetLogicalProcessorInformation(SYSTEM_LOGICAL_PROCESSOR_INFORMATION &buffer[],uint &returned_length); -int GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP relationship_type,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX &buffer[],uint &returned_length); -void GetNativeSystemInfo(SYSTEM_INFO &system_info); -void GetSystemTimePreciseAsFileTime(FILETIME &system_time_as_file_time); -int GetProductInfo(uint os_major_version,uint os_minor_version,uint sp_major_version,uint sp_minor_version,uint &returned_product_type); -uint EnumSystemFirmwareTables(uint firmware_table_provider_signature,PVOID &firmware_table_enum_buffer,uint buffer_size); -uint EnumSystemFirmwareTables(uint firmware_table_provider_signature,uchar &firmware_table_enum_buffer[],uint buffer_size); -uint GetSystemFirmwareTable(uint firmware_table_provider_signature,uint firmware_table_id,PVOID firmware_table_buffer,uint buffer_size); -uint GetSystemFirmwareTable(uint firmware_table_provider_signature,uint firmware_table_id,uchar &firmware_table_buffer[],uint buffer_size); -int DnsHostnameToComputerNameExW(const string hostname,ushort &computer_name[],uint &size); -int GetPhysicallyInstalledSystemMemory(ulong &total_memory_in_kilobytes); -int SetComputerNameEx2W(COMPUTER_NAME_FORMAT name_type,uint flags,const string buffer); -int SetSystemTimeAdjustment(uint time_adjustment,int time_adjustment_disabled); -int InstallELAMCertificateInfo(HANDLE elam_file); -int GetProcessorSystemCycleTime(ushort group,PVOID &buffer,uint &returned_length); -int GetProcessorSystemCycleTime(ushort group,SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION &buffer[],uint &returned_length); -int SetComputerNameW(const string computer_name); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/winapi.mqh b/Include/WinAPI/winapi.mqh deleted file mode 100644 index 47105b1..0000000 --- a/Include/WinAPI/winapi.mqh +++ /dev/null @@ -1,21 +0,0 @@ -//+------------------------------------------------------------------+ -//| winapi.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include "windef.mqh" -#include "winnt.mqh" -#include "fileapi.mqh" -#include "winbase.mqh" -#include "winuser.mqh" -#include "wingdi.mqh" -#include "winreg.mqh" -#include "handleapi.mqh" -#include "processthreadsapi.mqh" -#include "securitybaseapi.mqh" -#include "errhandlingapi.mqh" -#include "sysinfoapi.mqh" -#include "processenv.mqh" -#include "libloaderapi.mqh" -#include "memoryapi.mqh" -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/winbase.mqh b/Include/WinAPI/winbase.mqh deleted file mode 100644 index 529fad1..0000000 --- a/Include/WinAPI/winbase.mqh +++ /dev/null @@ -1,814 +0,0 @@ -//+------------------------------------------------------------------+ -//| WinBase.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include -#include - -//--- -#define OFS_MAXPATHNAME 128 -#define HW_PROFILE_GUIDLEN 39 -#define MAX_PROFILE_LEN 80 -#define RESTART_MAX_CMD_LINE 1024 - -//--- -enum COPYFILE2_COPY_PHASE - { - COPYFILE2_PHASE_NONE=0, - COPYFILE2_PHASE_PREPARE_SOURCE, - COPYFILE2_PHASE_PREPARE_DEST, - COPYFILE2_PHASE_READ_SOURCE, - COPYFILE2_PHASE_WRITE_DESTINATION, - COPYFILE2_PHASE_SERVER_COPY, - COPYFILE2_PHASE_NAMEGRAFT_COPY, - COPYFILE2_PHASE_MAX - }; -//--- -enum COPYFILE2_MESSAGE_ACTION - { - COPYFILE2_PROGRESS_CONTINUE=0, - COPYFILE2_PROGRESS_CANCEL, - COPYFILE2_PROGRESS_STOP, - COPYFILE2_PROGRESS_QUIET, - COPYFILE2_PROGRESS_PAUSE - }; -//--- -enum COPYFILE2_MESSAGE_TYPE - { - COPYFILE2_CALLBACK_NONE=0, - COPYFILE2_CALLBACK_CHUNK_STARTED, - COPYFILE2_CALLBACK_CHUNK_FINISHED, - COPYFILE2_CALLBACK_STREAM_STARTED, - COPYFILE2_CALLBACK_STREAM_FINISHED, - COPYFILE2_CALLBACK_POLL_CONTINUE, - COPYFILE2_CALLBACK_ERROR, - COPYFILE2_CALLBACK_MAX - }; -//--- -enum DEP_SYSTEM_POLICY_TYPE - { - DEPPolicyAlwaysOff=0, - DEPPolicyAlwaysOn, - DEPPolicyOptIn, - DEPPolicyOptOut, - DEPTotalPolicyCount - }; -//--- -enum FILE_ID_TYPE - { - FileIdType, - ObjectIdType, - ExtendedFileIdType, - MaximumFileIdType - }; -//--- -enum PRIORITY_HINT - { - IoPriorityHintVeryLow=0, - IoPriorityHintLow, - IoPriorityHintNormal, - MaximumIoPriorityHintType - }; -//--- -enum PROC_THREAD_ATTRIBUTE_NUM - { - ProcThreadAttributeParentProcess=0, - ProcThreadAttributeHandleList=2, - ProcThreadAttributeGroupAffinity=3, - ProcThreadAttributePreferredNode=4, - ProcThreadAttributeIdealProcessor=5, - ProcThreadAttributeUmsThread=6, - ProcThreadAttributeMitigationPolicy=7, - ProcThreadAttributeSecurityCapabilities=9, - ProcThreadAttributeProtectionLevel=11, - ProcThreadAttributeJobList=13, - ProcThreadAttributeChildProcessPolicy=14, - ProcThreadAttributeAllApplicationPackagesPolicy=15, - ProcThreadAttributeWin32kFilter=16, - ProcThreadAttributeSafeOpenPromptOriginClaim=17, - ProcThreadAttributeDesktopAppPolicy=18 - }; -//--- -struct ACTCTX_SECTION_KEYED_DATA_ASSEMBLY_METADATA - { - PVOID lpInformation; - PVOID lpSectionBase; - uint ulSectionLength; - PVOID lpSectionGlobalDataBase; - uint ulSectionGlobalDataLength; - }; -//--- -struct ACTCTX_SECTION_KEYED_DATA - { - uint cbSize; - uint ulDataFormatVersion; - PVOID lpData; - uint ulLength; - PVOID lpSectionGlobalData; - uint ulSectionGlobalDataLength; - PVOID lpSectionBase; - uint ulSectionTotalLength; - HANDLE hActCtx; - uint ulAssemblyRosterIndex; - uint ulFlags; - ACTCTX_SECTION_KEYED_DATA_ASSEMBLY_METADATA AssemblyMetadata; - }; -//--- -struct ACTCTX_SECTION_KEYED_DATA_2600 - { - uint cbSize; - uint ulDataFormatVersion; - PVOID lpData; - uint ulLength; - PVOID lpSectionGlobalData; - uint ulSectionGlobalDataLength; - PVOID lpSectionBase; - uint ulSectionTotalLength; - HANDLE hActCtx; - uint ulAssemblyRosterIndex; - }; -//--- -struct ACTCTXW - { - uint cbSize; - uint dwFlags; - PVOID lpSource; - ushort wProcessorArchitecture; - ushort wLangId; - PVOID lpAssemblyDirectory; - PVOID lpResourceName; - PVOID lpApplicationName; - HANDLE hModule; - }; -//--- -struct ACTIVATION_CONTEXT_BASIC_INFORMATION - { - HANDLE hActCtx; - uint dwFlags; - }; -//--- -struct DCB - { - uint DCBlength; - uint BaudRate; - uint Flags; - ushort wReserved; - ushort XonLim; - ushort XoffLim; - uchar ByteSize; - uchar Parity; - uchar StopBits; - char XonChar; - char XoffChar; - char ErrorChar; - char EofChar; - char EvtChar; - ushort wReserved1; - }; -//--- -struct COMMCONFIG - { - uint dwSize; - ushort wVersion; - ushort wReserved; - DCB dcb; - uint dwProviderSubType; - uint dwProviderOffset; - uint dwProviderSize; - short wcProviderData[2]; - }; -//--- -struct COMMPROP - { - ushort wPacketLength; - ushort wPacketVersion; - uint dwServiceMask; - uint dwReserved1; - uint dwMaxTxQueue; - uint dwMaxRxQueue; - uint dwMaxBaud; - uint dwProvSubType; - uint dwProvCapabilities; - uint dwSettableParams; - uint dwSettableBaud; - ushort wSettableData; - ushort wSettableStopParity; - uint dwCurrentTxQueue; - uint dwCurrentRxQueue; - uint dwProvSpec1; - uint dwProvSpec2; - short wcProvChar[1]; - }; -//--- -struct COMMTIMEOUTS - { - uint ReadIntervalTimeout; - uint ReadTotalTimeoutMultiplier; - uint ReadTotalTimeoutConstant; - uint WriteTotalTimeoutMultiplier; - uint WriteTotalTimeoutConstant; - }; -//--- -struct COMSTAT - { - uint cbInQue; - uint cbOutQue; - }; -//--- -struct COPYFILE2_EXTENDED_PARAMETERS - { - uint dwSize; - uint dwCopyFlags; - PVOID pfCancel; - PVOID pProgressRoutine; - PVOID pvCallbackContext; - }; -//--- -struct EVENTLOG_FULL_INFORMATION - { - uint dwFull; - }; -//--- -struct FILE_ALIGNMENT_INFO: public FILE_INFO - { - uint AlignmentRequirement; - }; -//--- -struct FILE_ALLOCATION_INFO: public FILE_INFO - { - long AllocationSize; - }; -//--- -struct FILE_ATTRIBUTE_TAG_INFO: public FILE_INFO - { - uint FileAttributes; - uint ReparseTag; - }; -//--- -struct FILE_BASIC_INFO: public FILE_INFO - { - long CreationTime; - long LastAccessTime; - long LastWriteTime; - long ChangeTime; - uint FileAttributes; - }; -//--- -struct FILE_COMPRESSION_INFO: public FILE_INFO - { - long CompressedFileSize; - ushort CompressionFormat; - uchar CompressionUnitShift; - uchar ChunkShift; - uchar ClusterShift; - uchar Reserved[3]; - }; -//--- -struct FILE_DISPOSITION_INFO: public FILE_INFO - { - uchar DeleteFile; - }; -//--- -struct FILE_DISPOSITION_INFO_EX: public FILE_INFO - { - uint Flags; - }; -//--- -struct FILE_END_OF_FILE_INFO: public FILE_INFO - { - long EndOfFile; - }; -//--- -struct FILE_FULL_DIR_INFO: public FILE_INFO - { - uint NextEntryOffset; - uint FileIndex; - long CreationTime; - long LastAccessTime; - long LastWriteTime; - long ChangeTime; - long EndOfFile; - long AllocationSize; - uint FileAttributes; - uint FileNameLength; - uint EaSize; - short FileName[1]; - }; -//--- -struct FILE_ID_BOTH_DIR_INFO: public FILE_INFO - { - uint NextEntryOffset; - uint FileIndex; - long CreationTime; - long LastAccessTime; - long LastWriteTime; - long ChangeTime; - long EndOfFile; - long AllocationSize; - uint FileAttributes; - uint FileNameLength; - uint EaSize; - char ShortNameLength; - short ShortName[12]; - long FileId; - short FileName[1]; - }; -//--- -struct FILE_ID_EXTD_DIR_INFO: public FILE_INFO - { - uint NextEntryOffset; - uint FileIndex; - long CreationTime; - long LastAccessTime; - long LastWriteTime; - long ChangeTime; - long EndOfFile; - long AllocationSize; - uint FileAttributes; - uint FileNameLength; - uint EaSize; - uint ReparsePointTag; - FILE_ID_128 FileId; - short FileName[1]; - }; -//--- -struct FILE_ID_INFO: public FILE_INFO - { - ulong VolumeSerialNumber; - FILE_ID_128 FileId; - }; -//--- -struct FILE_IO_PRIORITY_HINT_INFO: public FILE_INFO - { - PRIORITY_HINT PriorityHint; - }; -//--- -struct FILE_NAME_INFO - { - uint FileNameLength; - short FileName[2]; - }; -//--- -struct FILE_STANDARD_INFO: public FILE_INFO - { - long AllocationSize; - long EndOfFile; - uint NumberOfLinks; - uchar DeletePending; - uchar Directory; - }; -//--- -struct FILE_STORAGE_INFO: public FILE_INFO - { - uint LogicalBytesPerSector; - uint PhysicalBytesPerSectorForAtomicity; - uint PhysicalBytesPerSectorForPerformance; - uint FileSystemEffectivePhysicalBytesPerSectorForAtomicity; - uint Flags; - uint ByteOffsetForSectorAlignment; - uint ByteOffsetForPartitionAlignment; - }; -//--- -struct FILE_STREAM_INFO: public FILE_INFO - { - uint NextEntryOffset; - uint StreamNameLength; - long StreamSize; - long StreamAllocationSize; - short StreamName[1]; - }; -//--- -struct HW_PROFILE_INFOW - { - uint dwDockInfo; - short szHwProfileGuid[HW_PROFILE_GUIDLEN]; - short szHwProfileName[MAX_PROFILE_LEN]; - }; -//--- -struct JIT_DEBUG_INFO - { - uint dwSize; - uint dwProcessorArchitecture; - uint dwThreadID; - uint dwReserved0; - ulong lpExceptionAddress; - ulong lpExceptionRecord; - ulong lpContextRecord; - }; -//--- -struct MEMORYSTATUS - { - uint dwLength; - uint dwMemoryLoad; - ulong dwTotalPhys; - ulong dwAvailPhys; - ulong dwTotalPageFile; - ulong dwAvailPageFile; - ulong dwTotalVirtual; - ulong dwAvailVirtual; - }; -//--- -struct OFSTRUCT - { - uchar cBytes; - uchar fFixedDisk; - ushort nErrCode; - ushort Reserved1; - ushort Reserved2; - char szPathName[OFS_MAXPATHNAME]; - }; -//--- -struct OPERATION_END_PARAMETERS - { - uint Version; - uint OperationId; - uint Flags; - }; -//--- -struct OPERATION_START_PARAMETERS - { - uint Version; - uint OperationId; - uint Flags; - }; -//--- -struct SYSTEM_POWER_STATUS - { - uchar ACLineStatus; - uchar BatteryFlag; - uchar BatteryLifePercent; - uchar SystemStatusFlag; - uint BatteryLifeTime; - uint BatteryFullLifeTime; - }; -//--- -struct UMS_SCHEDULER_STARTUP_INFO - { - uint UmsVersion; - PVOID CompletionList; - PVOID SchedulerProc; - PVOID SchedulerParam; - }; -//--- -struct WIN32_STREAM_ID - { - uint dwStreamId; - uint dwStreamAttributes; - long Size; - uint dwStreamNameSize; - }; -//--- -struct UMS_SYSTEM_THREAD_INFORMATION - { - uint UmsVersion; - uint ThreadUmsFlags; - }; -//--- -struct FILE_ID_DESCRIPTOR - { - uint dwSize; - FILE_ID_TYPE Type; - long FileId; - }; -//--- -struct SYSTEMTIME - { - ushort wYear; - ushort wMonth; - ushort wDayOfWeek; - ushort wDay; - ushort wHour; - ushort wMinute; - ushort wSecond; - ushort wMilliseconds; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -int ActivateActCtx(HANDLE act_ctx,PVOID &cookie); -int ActivateActCtx(ACTCTXW &act_ctx,PVOID &cookie); -ushort AddAtomW(const string str); -int AddIntegrityLabelToBoundaryDescriptor(HANDLE &BoundaryDescriptor,SID &IntegrityLabel); -void AddRefActCtx(HANDLE act_ctx); -void AddRefActCtx(ACTCTXW &act_ctx); -int AddSecureMemoryCacheCallback(PVOID call_back); -void ApplicationRecoveryFinished(int success); -int ApplicationRecoveryInProgress(int &cancelled); -int BackupRead(HANDLE file,uchar &buffer[],uint number_of_bytes_to_read,uint &number_of_bytes_read,int abort,int process_security,PVOID &context); -int BackupSeek(HANDLE file,uint low_bytes_to_seek,uint high_bytes_to_seek,uint &low_byte_seeked,uint &high_byte_seeked,PVOID &context); -int BackupWrite(HANDLE file,uchar &buffer[],uint number_of_bytes_to_write,uint &number_of_bytes_written,int abort,int process_security,PVOID &context); -HANDLE BeginUpdateResourceW(const string file_name,int delete_existing_resources); -int BindIoCompletionCallback(HANDLE FileHandle,PVOID Function,uint Flags); -int BuildCommDCBAndTimeoutsW(const string def,DCB &lpDCB,COMMTIMEOUTS &comm_timeouts); -int BuildCommDCBW(const string def,DCB &lpDCB); -int CancelDeviceWakeupRequest(HANDLE device); -int CancelTimerQueueTimer(HANDLE TimerQueue,HANDLE Timer); -int CheckNameLegalDOS8Dot3W(const string name,char &oem_name[],uint oem_name_size,int &name_contains_spaces,int &name_legal); -int ClearCommBreak(HANDLE file); -int ClearCommError(HANDLE file,uint &errors,COMSTAT &stat); -int CommConfigDialogW(const string name,HANDLE wnd,COMMCONFIG &lpCC); -int ConvertFiberToThread(void); -PVOID ConvertThreadToFiber(PVOID parameter); -PVOID ConvertThreadToFiberEx(PVOID parameter,uint flags); -int CopyContext(CONTEXT &Destination,uint ContextFlags,CONTEXT &Source); -int CopyFile2(const string existing_file_name,const string new_file_name,COPYFILE2_EXTENDED_PARAMETERS &extended_parameters); -int CopyFileExW(const string existing_file_name,const string new_file_name,PVOID progress_routine,PVOID data,int &cancel,uint copy_flags); -int CopyFileTransactedW(const string existing_file_name,const string new_file_name,PVOID progress_routine,PVOID data,int &cancel,uint copy_flags,HANDLE transaction); -int CopyFileW(const string existing_file_name,const string new_file_name,int fail_if_exists); -HANDLE CreateActCtxW(const ACTCTXW &act_ctx); -int CreateDirectoryExW(const string template_directory,const string new_directory,PVOID security_attributes); -int CreateDirectoryTransactedW(const string template_directory,const string new_directory,PVOID security_attributes,HANDLE transaction); -PVOID CreateFiber(ulong stack_size,PVOID start_address,PVOID parameter); -PVOID CreateFiberEx(ulong stack_commit_size,ulong stack_reserve_size,uint flags,PVOID start_address,PVOID parameter); -HANDLE CreateFileTransactedW(const string file_name,uint desired_access,uint share_mode,PVOID security_attributes,uint creation_disposition,uint flags_and_attributes,HANDLE template_file,HANDLE transaction,ushort &mini_version,PVOID extended_parameter); -int CreateHardLinkTransactedW(const string file_name,const string existing_file_name,PVOID security_attributes,HANDLE transaction); -int CreateHardLinkW(const string file_name,const string existing_file_name,PVOID security_attributes); -int CreateJobSet(uint NumJob,JOB_SET_ARRAY &UserJobSet,uint Flags); -HANDLE CreateMailslotW(const string name,uint max_message_size,uint read_timeout,PVOID security_attributes); -uchar CreateSymbolicLinkTransactedW(const string symlink_file_name,const string target_file_name,uint flags,HANDLE transaction); -uchar CreateSymbolicLinkW(const string symlink_file_name,const string target_file_name,uint flags); -uint CreateTapePartition(HANDLE device,uint partition_method,uint count,uint size); -int CreateUmsCompletionList(PVOID &UmsCompletionList); -int CreateUmsThreadContext(PVOID &ums_thread); -int DeactivateActCtx(uint flags,ulong cookie); -int DebugBreakProcess(HANDLE Process); -int DebugSetProcessKillOnExit(int KillOnExit); -ushort DeleteAtom(ushort atom); -void DeleteFiber(PVOID fiber); -int DeleteFileTransactedW(const string file_name,HANDLE transaction); -int DeleteTimerQueue(HANDLE TimerQueue); -int DeleteUmsCompletionList(PVOID UmsCompletionList); -int DeleteUmsThreadContext(PVOID UmsThread); -int DequeueUmsCompletionListItems(PVOID UmsCompletionList,uint WaitTimeOut,PVOID &UmsThreadList); -uint DisableThreadProfiling(HANDLE PerformanceDataHandle); -int DnsHostnameToComputerNameW(const string hostname,ushort &computer_name[],uint &size); -int DosDateTimeToFileTime(ushort fat_date,ushort fat_time,FILETIME &file_time); -uint EnableThreadProfiling(HANDLE ThreadHandle,uint Flags,ulong HardwareCounters,HANDLE &PerformanceDataHandle); -int EndUpdateResourceW(HANDLE update,int discard); -int EnterUmsSchedulingMode(UMS_SCHEDULER_STARTUP_INFO &SchedulerStartupInfo); -int EnumResourceLanguagesW(HANDLE module,const string type,const string name,PVOID enum_func,long param); -int EnumResourceTypesW(HANDLE module,PVOID enum_func,long param); -uint EraseTape(HANDLE device,uint erase_type,int immediate); -int EscapeCommFunction(HANDLE file,uint func); -int ExecuteUmsThread(PVOID UmsThread); -void FatalExit(int ExitCode); -int FileTimeToDosDateTime(FILETIME &file_time,ushort &fat_date,ushort &fat_time); -int FindActCtxSectionGuid(uint flags,const GUID &extension_guid[],uint section_id,const GUID &guid_to_find[],ACTCTX_SECTION_KEYED_DATA &ReturnedData); -int FindActCtxSectionStringW(uint flags,const GUID &extension_guid[],uint section_id,const string string_to_find,ACTCTX_SECTION_KEYED_DATA &ReturnedData); -ushort FindAtomW(const string str); -HANDLE FindFirstFileNameTransactedW(const string file_name,uint flags,uint &StringLength,string LinkName,HANDLE transaction); -HANDLE FindFirstFileTransactedW(const string file_name,FINDEX_INFO_LEVELS info_level_id,FIND_DATAW &find_file_data,FINDEX_SEARCH_OPS search_op,PVOID search_filter,uint additional_flags,HANDLE transaction); -HANDLE FindFirstStreamTransactedW(const string file_name,STREAM_INFO_LEVELS InfoLevel,FIND_STREAM_DATA &find_stream_data,uint flags,HANDLE transaction); -HANDLE FindFirstVolumeMountPointW(const string root_path_name,ushort &volume_mount_point[],uint buffer_length); -int FindNextVolumeMountPointW(HANDLE find_volume_mount_point,string volume_mount_point,uint buffer_length); -int FindVolumeMountPointClose(HANDLE find_volume_mount_point); -uint FormatMessageW(uint flags,const uchar &source[],uint message_id,uint language_id,ushort &buffer[],uint size,PVOID &Arguments[]); -uint GetActiveProcessorCount(ushort GroupNumber); -ushort GetActiveProcessorGroupCount(void); -int GetApplicationRecoveryCallback(HANDLE process,PVOID &recovery_callback,PVOID ¶meter,uint &ping_interval,uint &flags); -int GetApplicationRestartSettings(HANDLE process,ushort &commandline[],uint &size,uint &flags); -uint GetAtomNameW(ushort atom,ushort &buffer[],int size); -int GetBinaryTypeW(const string application_name,uint &binary_type); -int GetCommConfig(HANDLE comm_dev,COMMCONFIG &lpCC,uint &size); -int GetCommMask(HANDLE file,uint &evt_mask); -int GetCommModemStatus(HANDLE file,uint &modem_stat); -int GetCommProperties(HANDLE file,COMMPROP &comm_prop); -int GetCommState(HANDLE file,DCB &lpDCB); -int GetCommTimeouts(HANDLE file,COMMTIMEOUTS &comm_timeouts); -uint GetCompressedFileSizeTransactedW(const string file_name,uint &file_size_high,HANDLE transaction); -int GetComputerNameW(ushort &buffer[],uint &size); -int GetCurrentActCtx(HANDLE &act_ctx); -int GetCurrentActCtx(ACTCTXW &act_ctx); -PVOID GetCurrentUmsThread(void); -int GetDefaultCommConfigW(const string name,COMMCONFIG &lpCC,uint &size); -int GetDevicePowerState(HANDLE device,int &on); -uint GetDllDirectoryW(uint buffer_length,ushort &buffer[]); -ulong GetEnabledXStateFeatures(void); -int GetFileAttributesTransactedW(const string file_name,GET_FILEEX_INFO_LEVELS info_level_id,PVOID file_information,HANDLE transaction); -int GetFileBandwidthReservation(HANDLE file,uint &period_milliseconds,uint &bytes_per_period,int &discardable,uint &transfer_size,uint &num_outstanding_requests); -int GetFileInformationByHandleEx(HANDLE file,FILE_INFO_BY_HANDLE_CLASS FileInformationClass,PVOID file_information,uint buffer_size); -int GetFileInformationByHandleEx(HANDLE file,FILE_INFO_BY_HANDLE_CLASS FileInformationClass,uchar &file_information[],uint buffer_size); -uint GetFirmwareEnvironmentVariableExW(const string name,const string guid,PVOID buffer,uint size,uint &attribubutes); -uint GetFirmwareEnvironmentVariableW(const string name,const string guid,PVOID buffer,uint size); -int GetFirmwareType(FIRMWARE_TYPE &FirmwareType); -uint GetFullPathNameTransactedW(const string file_name,uint buffer_length,string buffer,string &file_part,HANDLE transaction); -uint GetLongPathNameTransactedW(const string short_path,string long_path,uint buffer,HANDLE transaction); -int GetMailslotInfo(HANDLE mailslot,uint &max_message_size,uint &next_size,uint &message_count,uint &read_timeout); -uint GetMaximumProcessorCount(ushort GroupNumber); -ushort GetMaximumProcessorGroupCount(void); -int GetNamedPipeClientProcessId(HANDLE Pipe,uint &ClientProcessId); -int GetNamedPipeClientSessionId(HANDLE Pipe,uint &ClientSessionId); -int GetNamedPipeServerProcessId(HANDLE Pipe,uint &ServerProcessId); -int GetNamedPipeServerSessionId(HANDLE Pipe,uint &ServerSessionId); -PVOID GetNextUmsListItem(PVOID UmsContext); -int GetNumaAvailableMemoryNode(uchar Node,ulong &AvailableBytes); -int GetNumaAvailableMemoryNodeEx(ushort Node,ulong &AvailableBytes); -int GetNumaNodeNumberFromHandle(HANDLE file,ushort &NodeNumber); -int GetNumaNodeProcessorMask(uchar Node,ulong &ProcessorMask); -int GetNumaProcessorNode(uchar Processor,uchar &NodeNumber); -int GetNumaProcessorNodeEx(PROCESSOR_NUMBER &Processor,ushort &NodeNumber); -int GetNumaProximityNode(uint ProximityId,uchar &NodeNumber); -uint GetPrivateProfileIntW(const string app_name,const string key_name,int default_value,const string file_name); -uint GetPrivateProfileSectionNamesW(string return_buffer,uint size,const string file_name); -uint GetPrivateProfileSectionW(const string app_name,string returned_string,uint size,const string file_name); -uint GetPrivateProfileStringW(const string app_name,const string key_name,const string default_value,string returned_string,uint size,const string file_name); -int GetPrivateProfileStructW(const string section,const string key,PVOID struct_obj,uint size_struct,const string file); -int GetProcessAffinityMask(HANDLE process,ulong &process_affinity_mask,ulong &system_affinity_mask); -int GetProcessDEPPolicy(HANDLE process,uint &flags,int &permanent); -int GetProcessIoCounters(HANDLE process,IO_COUNTERS &io_counters); -int GetProcessWorkingSetSize(HANDLE process,ulong &minimum_working_set_size,ulong &maximum_working_set_size); -uint GetProfileIntW(const string app_name,const string key_name,int default_value); -uint GetProfileSectionW(const string app_name,string returned_string,uint size); -uint GetProfileStringW(const string app_name,const string key_name,const string default_value,string returned_string,uint size); -DEP_SYSTEM_POLICY_TYPE GetSystemDEPPolicy(void); -int GetSystemPowerStatus(SYSTEM_POWER_STATUS &system_power_status); -int GetSystemRegistryQuota(uint "a_allowed,uint "a_used); -uint GetTapeParameters(HANDLE device,uint operation,uint &size,PVOID tape_information); -uint GetTapePosition(HANDLE device,uint position_type,uint &partition,uint &offset_low,uint &offset_high); -uint GetTapeStatus(HANDLE device); -int GetThreadSelectorEntry(HANDLE thread,uint selector,LDT_ENTRY &selector_entry); -int GetUmsCompletionListEvent(PVOID UmsCompletionList,HANDLE &UmsCompletionEvent); -int GetUmsSystemThreadInformation(HANDLE ThreadHandle,UMS_SYSTEM_THREAD_INFORMATION &SystemThreadInfo); -int GetXStateFeaturesMask(CONTEXT &Context,ulong &FeatureMask); -ushort GlobalAddAtomExW(const string str,uint Flags); -ushort GlobalAddAtomW(const string str); -HANDLE GlobalAlloc(uint flags,ulong bytes); -ulong GlobalCompact(uint min_free); -ushort GlobalDeleteAtom(ushort atom); -ushort GlobalFindAtomW(const string str); -void GlobalFix(HANDLE mem); -uint GlobalFlags(HANDLE mem); -HANDLE GlobalFree(HANDLE mem); -uint GlobalGetAtomNameW(ushort atom,ushort &buffer[],int size); -HANDLE GlobalHandle(const PVOID mem); -PVOID GlobalLock(HANDLE mem); -void GlobalMemoryStatus(MEMORYSTATUS &buffer); -HANDLE GlobalReAlloc(HANDLE mem,ulong bytes,uint flags); -ulong GlobalSize(HANDLE mem); -void GlobalUnfix(HANDLE mem); -int GlobalUnlock(HANDLE mem); -int GlobalUnWire(HANDLE mem); -PVOID GlobalWire(HANDLE mem); -int InitAtomTable(uint size); -int InitializeContext(uchar &Buffer[],uint ContextFlags,CONTEXT &Context,uint &ContextLength); -int InitializeContext(PVOID Buffer,uint ContextFlags,CONTEXT &Context,uint &ContextLength); -int IsBadCodePtr(PVOID lpfn); -int IsBadHugeReadPtr(PVOID lp,ulong ucb); -int IsBadHugeWritePtr(PVOID lp,ulong ucb); -int IsBadReadPtr(PVOID lp,ulong ucb); -int IsBadStringPtrW(const string lpsz,ulong max); -int IsBadWritePtr(PVOID lp,ulong ucb); -int IsNativeVhdBoot(int &NativeVhdBoot); -int IsSystemResumeAutomatic(void); -HANDLE LoadPackagedLibrary(const string lib_file_name,uint Reserved); -HANDLE LocalAlloc(uint flags,ulong bytes); -ulong LocalCompact(uint min_free); -uint LocalFlags(HANDLE mem); -HANDLE LocalFree(HANDLE mem); -HANDLE LocalHandle(const PVOID mem); -PVOID LocalLock(HANDLE mem); -HANDLE LocalReAlloc(HANDLE mem,ulong bytes,uint flags); -ulong LocalShrink(HANDLE mem,uint new_size); -ulong LocalSize(HANDLE mem); -int LocalUnlock(HANDLE mem); -PVOID LocateXStateFeature(CONTEXT &Context,uint FeatureId,uint &Length); -string lstrcatW(ushort &string1[],const string string2); -int lstrcmpiW(const string string1,const string string2); -int lstrcmpW(const string string1,const string string2); -string lstrcpynW(ushort &string1[],const string string2,int max_length); -string lstrcpyW(ushort &string1[],const string string2); -int lstrlenW(const string str); -int MapUserPhysicalPagesScatter(PVOID &VirtualAddresses[],ulong NumberOfPages,ulong &PageArray[]); -PVOID MapViewOfFileExNuma(HANDLE file_mapping_object,uint desired_access,uint file_offset_high,uint file_offset_low,ulong number_of_bytes_to_map,PVOID base_address,uint preferred); -int MoveFileExW(const string existing_file_name,const string new_file_name,uint flags); -int MoveFileTransactedW(const string existing_file_name,const string new_file_name,PVOID progress_routine,PVOID data,uint flags,HANDLE transaction); -int MoveFileW(const string existing_file_name,const string new_file_name); -int MoveFileWithProgressW(const string existing_file_name,const string new_file_name,PVOID progress_routine,PVOID data,uint flags); -int MulDiv(int number,int numerator,int denominator); -HANDLE OpenFileById(HANDLE volume_hint,FILE_ID_DESCRIPTOR &file_id,uint desired_access,uint share_mode,PVOID security_attributes,uint flags_and_attributes); -int PowerClearRequest(HANDLE PowerRequest,POWER_REQUEST_TYPE RequestType); -HANDLE PowerCreateRequest(REASON_CONTEXT &Context); -int PowerSetRequest(HANDLE PowerRequest,POWER_REQUEST_TYPE RequestType); -uint PrepareTape(HANDLE device,uint operation,int immediate); -int PulseEvent(HANDLE event); -int PurgeComm(HANDLE file,uint flags); -int QueryActCtxSettingsW(uint flags,HANDLE act_ctx,const string name_space,const string name,string buffer,ulong buffer,ulong &written_or_required); -int QueryActCtxSettingsW(uint flags,ACTCTXW &act_ctx,const string name_space,const string name,string buffer,ulong buffer,ulong &written_or_required); -int QueryActCtxW(uint flags,HANDLE act_ctx,PVOID sub_instance,uint info_class,PVOID buffer,ulong buffer,ulong &written_or_required); -int QueryActCtxW(uint flags,ACTCTXW &act_ctx,PVOID sub_instance,uint info_class,PVOID buffer,ulong buffer,ulong &written_or_required); -int QueryFullProcessImageNameW(HANDLE process,uint flags,string exe_name,uint &size); -uint QueryThreadProfiling(HANDLE ThreadHandle,uchar &Enabled); -int QueryUmsThreadInformation(PVOID UmsThread,RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass,PVOID UmsThreadInformation,uint UmsThreadInformationLength,uint &ReturnLength); -int ReadDirectoryChangesExW(HANDLE directory,PVOID buffer,uint buffer_length,int watch_subtree,uint notify_filter,uint &bytes_returned,OVERLAPPED &overlapped,PVOID completion_routine,READ_DIRECTORY_NOTIFY_INFORMATION_CLASS ReadDirectoryNotifyInformationClass); -int ReadDirectoryChangesW(HANDLE directory,PVOID buffer,uint buffer_length,int watch_subtree,uint notify_filter,uint &bytes_returned,OVERLAPPED &overlapped,PVOID completion_routine); -uint ReadThreadProfilingData(HANDLE PerformanceDataHandle,uint Flags,PERFORMANCE_DATA &PerformanceData); -int RegisterApplicationRecoveryCallback(PVOID recovey_callback,PVOID parameter,uint ping_interval,uint flags); -int RegisterApplicationRestart(const string commandline,uint flags); -int RegisterWaitForSingleObject(HANDLE &new_wait_object,HANDLE object,PVOID Callback,PVOID Context,uint milliseconds,uint flags); -void ReleaseActCtx(HANDLE act_ctx); -void ReleaseActCtx(ACTCTXW &act_ctx); -int RemoveDirectoryTransactedW(const string path_name,HANDLE transaction); -int RemoveSecureMemoryCacheCallback(PVOID call_back); -HANDLE ReOpenFile(HANDLE original_file,uint desired_access,uint share_mode,uint flags_and_attributes); -int ReplaceFileW(const string replaced_file_name,const string replacement_file_name,const string backup_file_name,uint replace_flags,PVOID exclude,PVOID reserved); -int ReplacePartitionUnit(string TargetPartition,string SparePartition,uint Flags); -int RequestDeviceWakeup(HANDLE device); -int RequestWakeupLatency(LATENCY_TIME latency); -void RestoreLastError(uint err_code); -int SetCommBreak(HANDLE file); -int SetCommConfig(HANDLE comm_dev,COMMCONFIG &lpCC,uint size); -int SetCommMask(HANDLE file,uint evt_mask); -int SetCommState(HANDLE file,DCB &lpDCB); -int SetCommTimeouts(HANDLE file,COMMTIMEOUTS &comm_timeouts); -int SetDefaultCommConfigW(const string name,COMMCONFIG &lpCC,uint size); -int SetDllDirectoryW(const string path_name); -int SetFileAttributesTransactedW(const string file_name,uint file_attributes,HANDLE transaction); -int SetFileBandwidthReservation(HANDLE file,uint period_milliseconds,uint bytes_per_period,int discardable,uint &transfer_size,uint &num_outstanding_requests); -int SetFileCompletionNotificationModes(HANDLE FileHandle,uchar Flags); -int SetFileShortNameW(HANDLE file,const string short_name); -int SetFirmwareEnvironmentVariableExW(const string name,const string guid,PVOID value,uint size,uint attributes); -int SetFirmwareEnvironmentVariableW(const string name,const string guid,PVOID value,uint size); -uint SetHandleCount(uint number); -int SetMailslotInfo(HANDLE mailslot,uint read_timeout); -int SetMessageWaitingIndicator(HANDLE msg_indicator,uint msg_count); -int SetProcessAffinityMask(HANDLE process,PVOID process_affinity_mask); -int SetProcessDEPPolicy(uint flags); -int SetProcessWorkingSetSize(HANDLE process,ulong minimum_working_set_size,ulong maximum_working_set_size); -int SetSearchPathMode(uint flags); -int SetSystemPowerState(int suspend,int force); -uint SetTapeParameters(HANDLE device,uint operation,PVOID tape_information); -uint SetTapePosition(HANDLE device,uint position_method,uint partition,uint offset_low,uint offset_high,int immediate); -PVOID SetThreadAffinityMask(HANDLE thread,PVOID thread_affinity_mask); -uint SetThreadExecutionState(uint flags); -HANDLE SetTimerQueueTimer(HANDLE TimerQueue,PVOID Callback,PVOID Parameter,uint DueTime,uint Period,int PreferIo); -int SetUmsThreadInformation(PVOID UmsThread,RTL_UMS_THREAD_INFO_CLASS UmsThreadInfoClass,PVOID UmsThreadInformation,uint UmsThreadInformationLength); -int SetupComm(HANDLE file,uint in_queue,uint out_queue); -int SetVolumeLabelW(const string root_path_name,const string volume_name); -int SetVolumeMountPointW(const string volume_mount_point,const string volume_name); -int SetXStateFeaturesMask(CONTEXT &Context,ulong FeatureMask); -uint SignalObjectAndWait(HANDLE object_to_signal,HANDLE object_to_wait_on,uint milliseconds,int alertable); -void SwitchToFiber(PVOID fiber); -int TransmitCommChar(HANDLE file,char symbol); -int UmsThreadYield(PVOID SchedulerParam); -int UnregisterApplicationRecoveryCallback(void); -int UnregisterApplicationRestart(void); -int UnregisterWait(HANDLE WaitHandle); -int UpdateResourceW(HANDLE update,const string type,const string name,ushort &language,PVOID data,uint cb); -int VerifyVersionInfoW(OSVERSIONINFOEXW &version_information,uint type_mask,ulong condition_mask); -int WaitCommEvent(HANDLE file,uint &evt_mask,OVERLAPPED &overlapped); -uchar Wow64EnableWow64FsRedirection(uchar Wow64FsEnableRedirection); -int Wow64GetThreadContext(HANDLE thread,CONTEXT &context); -int Wow64GetThreadSelectorEntry(HANDLE thread,uint selector,LDT_ENTRY &selector_entry); -int Wow64SetThreadContext(HANDLE thread,CONTEXT &context); -uint Wow64SuspendThread(HANDLE thread); -int WritePrivateProfileSectionW(const string app_name,const string str,const string file_name); -int WritePrivateProfileStringW(const string app_name,const string key_name,const string str,const string file_name); -int WritePrivateProfileStructW(const string section,const string key,PVOID struct_obj,uint size_struct,const string file); -int WriteProfileSectionW(const string app_name,const string str); -int WriteProfileStringW(const string app_name,const string key_name,const string str); -uint WriteTapemark(HANDLE device,uint tapemark_type,uint tapemark_count,int immediate); -uint WTSGetActiveConsoleSessionId(void); -int ZombifyActCtx(HANDLE act_ctx); -int ZombifyActCtx(ACTCTXW &act_ctx); -#import - -#import "advapi32.dll" -int AddConditionalAce(ACL &acl,uint ace_revision,uint AceFlags,uchar AceType,uint AccessMask,SID &sid,string ConditionStr,uint &ReturnLength); -int BackupEventLogW(HANDLE event_log,const string backup_file_name); -int ClearEventLogW(HANDLE event_log,const string backup_file_name); -void CloseEncryptedFileRaw(PVOID context); -int CloseEventLog(HANDLE event_log); -int DecryptFileW(const string file_name,uint reserved); -int DeregisterEventSource(HANDLE event_log); -int EncryptFileW(const string file_name); -int FileEncryptionStatusW(const string file_name,uint &status); -int GetCurrentHwProfileW(HW_PROFILE_INFOW &hw_profile_info); -int GetEventLogInformation(HANDLE event_log,uint info_level,PVOID buffer,uint buf_size,uint &bytes_needed); -int GetNumberOfEventLogRecords(HANDLE event_log,uint &NumberOfRecords); -int GetOldestEventLogRecord(HANDLE event_log,uint &OldestRecord); -int GetUserNameW(string buffer,uint &buffer); -int IsTextUnicode(PVOID lpv,int size,int &result); -int IsTokenUntrusted(HANDLE TokenHandle); -int LogonUserExW(const string username,const string domain,const string password,uint logon_type,uint logon_provider,HANDLE &token,PVOID &logon_sid,PVOID &profile_buffer,uint &profile_length,QUOTA_LIMITS "a_limits); -int LogonUserW(const string username,const string domain,const string password,uint logon_type,uint logon_provider,HANDLE &token); -int LookupAccountNameW(const string system_name,const string account_name,SID &Sid,uint &sid,string ReferencedDomainName,uint &referenced_domain_name,SID_NAME_USE &use); -int LookupAccountSidW(const string system_name,SID &Sid,string Name,uint &name,string ReferencedDomainName,uint &referenced_domain_name,SID_NAME_USE &use); -int LookupPrivilegeDisplayNameW(const string system_name,const string name,string display_name,uint &display_name,uint &language_id); -int LookupPrivilegeNameW(const string system_name,LUID &luid,string name,uint &name); -int LookupPrivilegeValueW(const string system_name,const string name,LUID &luid); -int NotifyChangeEventLog(HANDLE event_log,HANDLE event); -HANDLE OpenBackupEventLogW(const string lpUNCServerName,const string file_name); -uint OpenEncryptedFileRawW(const string file_name,uint flags,PVOID &context); -HANDLE OpenEventLogW(const string lpUNCServerName,const string source_name); -int OperationEnd(OPERATION_END_PARAMETERS &OperationEndParams); -int OperationStart(OPERATION_START_PARAMETERS &OperationStartParams); -uint ReadEncryptedFileRaw(PVOID export_callback,PVOID callback_context,PVOID context); -int ReadEventLogW(HANDLE event_log,uint read_flags,uint record_offset,PVOID buffer,uint number_of_bytes_to_read,uint &bytes_read,uint &min_number_of_bytes_needed); -HANDLE RegisterEventSourceW(const string lpUNCServerName,const string source_name); -int ReportEventW(HANDLE event_log,ushort &type,ushort &category,uint dwEventID,SID &user_sid,ushort &num_strings,uint data_size,const string &strings[],PVOID raw_data); -uint WriteEncryptedFileRaw(PVOID import_callback,PVOID callback_context,PVOID context); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/windef.mqh b/Include/WinAPI/windef.mqh deleted file mode 100644 index bac0fbc..0000000 --- a/Include/WinAPI/windef.mqh +++ /dev/null @@ -1,325 +0,0 @@ -//+------------------------------------------------------------------+ -//| windef.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#define HANDLE long -#define PVOID long -//--- -#define ANYSIZE_ARRAY 1 -#define MAX_BREAKPOINTS 8 -#define MAX_WATCHPOINTS 2 -#define MAX_HW_COUNTERS 16 -#define MAX_PATH 260 -#define EXCEPTION_MAXIMUM_PARAMETERS 15 - -//--- -enum LATENCY_TIME - { - LT_DONT_CARE, - LT_LOWEST_LATENCY - }; -//--- -enum GET_FILEEX_INFO_LEVELS - { - GetFileExInfoStandard, - GetFileExMaxInfoLevel - }; -//--- -enum FINDEX_INFO_LEVELS - { - FindExInfoStandard, - FindExInfoBasic, - FindExInfoMaxInfoLevel - }; -//--- -enum FINDEX_SEARCH_OPS - { - FindExSearchNameMatch, - FindExSearchLimitToDirectories, - FindExSearchLimitToDevices, - FindExSearchMaxSearchOp - }; -//--- -enum DPI_AWARENESS - { - DPI_AWARENESS_INVALID=-1, - DPI_AWARENESS_UNAWARE=0, - DPI_AWARENESS_SYSTEM_AWARE=1, - DPI_AWARENESS_PER_MONITOR_AWARE=2 - }; -//--- -enum DPI_HOSTING_BEHAVIOR - { - DPI_HOSTING_BEHAVIOR_INVALID=-1, - DPI_HOSTING_BEHAVIOR_DEFAULT=0, - DPI_HOSTING_BEHAVIOR_MIXED=1 - }; -//--- -enum FILE_INFO_BY_HANDLE_CLASS - { - FileBasicInfo=0, - FileStandardInfo=1, - FileNameInfo=2, - FileRenameInfo=3, - FileDispositionInfo= 4, - FileAllocationInfo = 5, - FileEndOfFileInfo=6, - FileStreamInfo=7, - FileCompressionInfo=8, - FileAttributeTagInfo=9, - FileIdBothDirectoryInfo=10, - FileIdBothDirectoryRestartInfo=11, - FileIoPriorityHintInfo = 12, - FileRemoteProtocolInfo = 13, - FileFullDirectoryInfo=14, - FileFullDirectoryRestartInfo=15, - FileStorageInfo=16, - FileAlignmentInfo=17, - FileIdInfo=18, - FileIdExtdDirectoryInfo=19, - FileIdExtdDirectoryRestartInfo=20, - MaximumFileInfoByHandlesClass - }; -//--- -enum READ_DIRECTORY_NOTIFY_INFORMATION_CLASS - { - ReadDirectoryNotifyInformation=1, - ReadDirectoryNotifyExtendedInformation - }; -//--- -enum WELL_KNOWN_SID_TYPE - { - WinNullSid=0, - WinWorldSid= 1, - WinLocalSid= 2, - WinCreatorOwnerSid= 3, - WinCreatorGroupSid= 4, - WinCreatorOwnerServerSid=5, - WinCreatorGroupServerSid= 6, - WinNtAuthoritySid=7, - WinDialupSid=8, - WinNetworkSid=9, - WinBatchSid=10, - WinInteractiveSid=11, - WinServiceSid=12, - WinAnonymousSid=13, - WinProxySid=14, - WinEnterpriseControllersSid=15, - WinSelfSid=16, - WinAuthenticatedUserSid=17, - WinRestrictedCodeSid= 18, - WinTerminalServerSid= 19, - WinRemoteLogonIdSid=20, - WinLogonIdsSid=21, - WinLocalSystemSid=22, - WinLocalServiceSid=23, - WinNetworkServiceSid=24, - WinBuiltinDomainSid=25, - WinBuiltinAdministratorsSid=26, - WinBuiltinUsersSid=27, - WinBuiltinGuestsSid=28, - WinBuiltinPowerUsersSid=29, - WinBuiltinAccountOperatorsSid=30, - WinBuiltinSystemOperatorsSid=31, - WinBuiltinPrintOperatorsSid=32, - WinBuiltinBackupOperatorsSid=33, - WinBuiltinReplicatorSid=34, - WinBuiltinPreWindows2000CompatibleAccessSid=35, - WinBuiltinRemoteDesktopUsersSid=36, - WinBuiltinNetworkConfigurationOperatorsSid=37, - WinAccountAdministratorSid=38, - WinAccountGuestSid=39, - WinAccountKrbtgtSid=40, - WinAccountDomainAdminsSid=41, - WinAccountDomainUsersSid=42, - WinAccountDomainGuestsSid=43, - WinAccountComputersSid=44, - WinAccountControllersSid=45, - WinAccountCertAdminsSid=46, - WinAccountSchemaAdminsSid=47, - WinAccountEnterpriseAdminsSid=48, - WinAccountPolicyAdminsSid=49, - WinAccountRasAndIasServersSid=50, - WinNTLMAuthenticationSid=51, - WinDigestAuthenticationSid=52, - WinSChannelAuthenticationSid=53, - WinThisOrganizationSid=54, - WinOtherOrganizationSid=55, - WinBuiltinIncomingForestTrustBuildersSid=56, - WinBuiltinPerfMonitoringUsersSid=57, - WinBuiltinPerfLoggingUsersSid=58, - WinBuiltinAuthorizationAccessSid=59, - WinBuiltinTerminalServerLicenseServersSid=60, - WinBuiltinDCOMUsersSid=61, - WinBuiltinIUsersSid=62, - WinIUserSid=63, - WinBuiltinCryptoOperatorsSid=64, - WinUntrustedLabelSid=65, - WinLowLabelSid=66, - WinMediumLabelSid=67, - WinHighLabelSid=68, - WinSystemLabelSid=69, - WinWriteRestrictedCodeSid=70, - WinCreatorOwnerRightsSid=71, - WinCacheablePrincipalsGroupSid=72, - WinNonCacheablePrincipalsGroupSid=73, - WinEnterpriseReadonlyControllersSid=74, - WinAccountReadonlyControllersSid=75, - WinBuiltinEventLogReadersGroup=76, - WinNewEnterpriseReadonlyControllersSid=77, - WinBuiltinCertSvcDComAccessGroup=78, - WinMediumPlusLabelSid=79, - WinLocalLogonSid=80, - WinConsoleLogonSid=81, - WinThisOrganizationCertificateSid= 82, - WinApplicationPackageAuthoritySid= 83, - WinBuiltinAnyPackageSid=84, - WinCapabilityInternetClientSid=85, - WinCapabilityInternetClientServerSid=86, - WinCapabilityPrivateNetworkClientServerSid=87, - WinCapabilityPicturesLibrarySid=88, - WinCapabilityVideosLibrarySid=89, - WinCapabilityMusicLibrarySid=90, - WinCapabilityDocumentsLibrarySid=91, - WinCapabilitySharedUserCertificatesSid=92, - WinCapabilityEnterpriseAuthenticationSid=93, - WinCapabilityRemovableStorageSid=94, - WinBuiltinRDSRemoteAccessServersSid=95, - WinBuiltinRDSEndpointServersSid=96, - WinBuiltinRDSManagementServersSid=97, - WinUserModeDriversSid=98, - WinBuiltinHyperVAdminsSid=99, - WinAccountCloneableControllersSid=100, - WinBuiltinAccessControlAssistanceOperatorsSid=101, - WinBuiltinRemoteManagementUsersSid=102, - WinAuthenticationAuthorityAssertedSid=103, - WinAuthenticationServiceAssertedSid=104, - WinLocalAccountSid=105, - WinLocalAccountAndAdministratorSid=106, - WinAccountProtectedUsersSid=107, - WinCapabilityAppointmentsSid=108, - WinCapabilityContactsSid=109, - WinAccountDefaultSystemManagedSid=110, - WinBuiltinDefaultSystemManagedGroupSid=111, - WinBuiltinStorageReplicaAdminsSid=112, - WinAccountKeyAdminsSid=113, - WinAccountEnterpriseKeyAdminsSid=114, - WinAuthenticationKeyTrustSid=115, - WinAuthenticationKeyPropertyMFASid=116, - WinAuthenticationKeyPropertyAttestationSid=117, - WinAuthenticationFreshKeyAuthSid=118, - WinBuiltinDeviceOwnersSid=119 - }; -//--- -union FILE_SEGMENT_ELEMENT - { - PVOID Buffer; - ulong Alignment; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -//--- -struct REASON_CONTEXT - { - uint Version; - uint Flags; - PVOID Reason; - }; -//--- -struct OVERLAPPED - { - PVOID Internal; - PVOID InternalHigh; - uint Offset; - uint OffsetHigh; - HANDLE hEvent; - }; -//--- -struct LDT_ENTRY - { - ushort LimitLow; - ushort BaseLow; - uchar BaseMid; - uchar Flags1; - uchar Flags2; - uchar BaseHi; - }; -//--- -struct GUID - { - ulong Data1; - ushort Data2; - ushort Data3; - uchar Data4[8]; - }; -//--- -struct FILETIME - { - uint dwLowDateTime; - uint dwHighDateTime; - }; -//--- -struct POINT - { - int x; - int y; - }; -//--- -struct POINTL - { - int x; - int y; - }; -//--- -struct POINTS - { - short x; - short y; - }; -//--- -struct RECT - { - int left; - int top; - int right; - int bottom; - }; -//--- -struct RECTL - { - int left; - int top; - int right; - int bottom; - }; -//--- -struct SIZE - { - int cx; - int cy; - }; -//--- -struct FILE_INFO - { - }; -//--- -struct CLAIM_SECURITY_ATTRIBUTE_V1 - { - PVOID Name; - ushort ValueType; - ushort Reserved; - uint Flags; - uint ValueCount; - PVOID Values; - }; -//--- -struct CLAIM_SECURITY_ATTRIBUTES_INFORMATION - { - ushort Version; - ushort Reserved; - uint AttributeCount; - PVOID Attribute; - }; -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/wingdi.mqh b/Include/WinAPI/wingdi.mqh deleted file mode 100644 index 81ffe5c..0000000 --- a/Include/WinAPI/wingdi.mqh +++ /dev/null @@ -1,2080 +0,0 @@ -//+------------------------------------------------------------------+ -//| wingdi.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//--- -#define MM_MAX_AXES_NAMELEN 16 -#define MM_MAX_NUMAXES 16 -#define CCHDEVICENAME 32 -#define LF_FACESIZE 32 -#define LF_FULLFACESIZE 64 -#define ELF_VENDOR_SIZE 4 -#define CCHFORMNAME 32 - -//--- -enum DISPLAYCONFIG_COLOR_ENCODING - { - DISPLAYCONFIG_COLOR_ENCODING_RGB=0, - DISPLAYCONFIG_COLOR_ENCODING_YCBCR444=1, - DISPLAYCONFIG_COLOR_ENCODING_YCBCR422=2, - DISPLAYCONFIG_COLOR_ENCODING_YCBCR420=3, - DISPLAYCONFIG_COLOR_ENCODING_INTENSITY=4, - DISPLAYCONFIG_COLOR_ENCODING_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_DEVICE_INFO_TYPE - { - DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME=1, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME=2, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE=3, - DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME=4, - DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE=5, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE=6, - DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION=7, - DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION=8, - DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO=9, - DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE=10, - DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL=11, - DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_MODE_INFO_TYPE - { - DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE=1, - DISPLAYCONFIG_MODE_INFO_TYPE_TARGET=2, - DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE=3, - DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_PIXELFORMAT - { - DISPLAYCONFIG_PIXELFORMAT_8BPP=1, - DISPLAYCONFIG_PIXELFORMAT_16BPP=2, - DISPLAYCONFIG_PIXELFORMAT_24BPP=3, - DISPLAYCONFIG_PIXELFORMAT_32BPP=4, - DISPLAYCONFIG_PIXELFORMAT_NONGDI=5, - DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32=0xffffffff - }; -//--- -enum DISPLAYCONFIG_ROTATION - { - DISPLAYCONFIG_ROTATION_IDENTITY=1, - DISPLAYCONFIG_ROTATION_ROTATE90=2, - DISPLAYCONFIG_ROTATION_ROTATE180=3, - DISPLAYCONFIG_ROTATION_ROTATE270=4, - DISPLAYCONFIG_ROTATION_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_SCALING - { - DISPLAYCONFIG_SCALING_IDENTITY=1, - DISPLAYCONFIG_SCALING_CENTERED=2, - DISPLAYCONFIG_SCALING_STRETCHED=3, - DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX=4, - DISPLAYCONFIG_SCALING_CUSTOM=5, - DISPLAYCONFIG_SCALING_PREFERRED=128, - DISPLAYCONFIG_SCALING_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_SCANLINE_ORDERING - { - DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED=0, - DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE=1, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED=2, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST=DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST=3, - DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_TOPOLOGY_ID - { - DISPLAYCONFIG_TOPOLOGY_INTERNAL=0x00000001, - DISPLAYCONFIG_TOPOLOGY_CLONE=0x00000002, - DISPLAYCONFIG_TOPOLOGY_EXTEND=0x00000004, - DISPLAYCONFIG_TOPOLOGY_EXTERNAL=0x00000008, - DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32=0xFFFFFFFF - }; -//--- -enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY - { - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER=-1, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15=0, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO=1, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO=2, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO=3, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI=4, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI=5, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS=6, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN=8, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI=9, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL=10, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED=11, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL=12, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED=13, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE=14, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST=15, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED=16, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL=0x80000000, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32=0xFFFFFFFF - }; -//--- -struct ABC - { - int abcA; - uint abcB; - int abcC; - }; -//--- -struct ABCFLOAT - { - float abcfA; - float abcfB; - float abcfC; - }; -//--- -struct AXISINFOW - { - int axMinValue; - int axMaxValue; - short axAxisName[MM_MAX_AXES_NAMELEN]; - }; -//--- -struct AXESLISTW - { - uint axlReserved; - uint axlNumAxes; - AXISINFOW axlAxisInfo[MM_MAX_NUMAXES]; - }; -//--- -struct BITMAP - { - int bmType; - int bmWidth; - int bmHeight; - int bmWidthBytes; - ushort bmPlanes; - ushort bmBitsPixel; - PVOID bmBits; - }; -//--- -struct BITMAPCOREHEADER - { - uint bcSize; - ushort bcWidth; - ushort bcHeight; - ushort bcPlanes; - ushort bcBitCount; - }; -//--- -struct BITMAPFILEHEADER - { - ushort bfType; - uint bfSize; - ushort bfReserved1; - ushort bfReserved2; - uint bfOffBits; - }; -//--- -struct RGBTRIPLE - { - uchar rgbtBlue; - uchar rgbtGreen; - uchar rgbtRed; - }; -//--- -struct BITMAPCOREINFO - { - BITMAPCOREHEADER bmciHeader; - RGBTRIPLE bmciColors[1]; - }; -//--- -struct BITMAPINFOHEADER - { - uint biSize; - int biWidth; - int biHeight; - ushort biPlanes; - ushort biBitCount; - uint biCompression; - uint biSizeImage; - int biXPelsPerMeter; - int biYPelsPerMeter; - uint biClrUsed; - uint biClrImportant; - }; -//--- -struct RGBQUAD - { - uchar rgbBlue; - uchar rgbGreen; - uchar rgbRed; - uchar rgbReserved; - }; -//--- -struct BITMAPINFO - { - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[1]; - }; -//--- -struct CIEXYZ - { - int ciexyzX; - int ciexyzY; - int ciexyzZ; - }; -//--- -struct CIEXYZTRIPLE - { - CIEXYZ ciexyzRed; - CIEXYZ ciexyzGreen; - CIEXYZ ciexyzBlue; - }; -//--- -struct BITMAPV4HEADER - { - uint bV4Size; - int bV4Width; - int bV4Height; - ushort bV4Planes; - ushort bV4BitCount; - uint bV4V4Compression; - uint bV4SizeImage; - int bV4XPelsPerMeter; - int bV4YPelsPerMeter; - uint bV4ClrUsed; - uint bV4ClrImportant; - uint bV4RedMask; - uint bV4GreenMask; - uint bV4BlueMask; - uint bV4AlphaMask; - uint bV4CSType; - CIEXYZTRIPLE bV4Endpoints; - uint bV4GammaRed; - uint bV4GammaGreen; - uint bV4GammaBlue; - }; -//--- -struct BITMAPV5HEADER - { - uint bV5Size; - int bV5Width; - int bV5Height; - ushort bV5Planes; - ushort bV5BitCount; - uint bV5Compression; - uint bV5SizeImage; - int bV5XPelsPerMeter; - int bV5YPelsPerMeter; - uint bV5ClrUsed; - uint bV5ClrImportant; - uint bV5RedMask; - uint bV5GreenMask; - uint bV5BlueMask; - uint bV5AlphaMask; - uint bV5CSType; - CIEXYZTRIPLE bV5Endpoints; - uint bV5GammaRed; - uint bV5GammaGreen; - uint bV5GammaBlue; - uint bV5Intent; - uint bV5ProfileData; - uint bV5ProfileSize; - uint bV5Reserved; - }; -//--- -struct BLENDFUNCTION - { - uchar BlendOp; - uchar BlendFlags; - uchar SourceConstantAlpha; - uchar AlphaFormat; - }; -//--- -struct FONTSIGNATURE - { - uint fsUsb[4]; - uint fsCsb[2]; - }; -//--- -struct CHARSETINFO - { - uint ciCharset; - uint ciACP; - FONTSIGNATURE fs; - }; -//--- -struct COLORADJUSTMENT - { - ushort caSize; - ushort caFlags; - ushort caIlluminantIndex; - ushort caRedGamma; - ushort caGreenGamma; - ushort caBlueGamma; - ushort caReferenceBlack; - ushort caReferenceWhite; - short caContrast; - short caBrightness; - short caColorfulness; - short caRedGreenTint; - }; -//--- -struct DESIGNVECTOR - { - uint dvReserved; - uint dvNumAxes; - int dvValues[MM_MAX_NUMAXES]; - }; -//--- -struct DIBSECTION - { - BITMAP dsBm; - BITMAPINFOHEADER dsBmih; - uint dsBitfields[3]; - HANDLE dshSection; - uint dsOffset; - }; -//--- -struct DISPLAY_DEVICEA - { - uint cb; - char DeviceName[32]; - char DeviceString[128]; - uint StateFlags; - char DeviceID[128]; - char DeviceKey[128]; - }; -//--- -struct DISPLAY_DEVICEW - { - uint cb; - short DeviceName[32]; - short DeviceString[128]; - uint StateFlags; - short DeviceID[128]; - short DeviceKey[128]; - }; -//--- -struct DISPLAYCONFIG_2DREGION - { - uint cx; - uint cy; - }; -//--- -struct DISPLAYCONFIG_DEVICE_INFO_HEADER - { - DISPLAYCONFIG_DEVICE_INFO_TYPE type; - uint size; - LUID adapterId; - uint id; - }; -//--- -struct DISPLAYCONFIG_ADAPTER_NAME - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - short adapterDevicePath[128]; - }; -//--- -struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO - { - POINTL PathSourceSize; - RECTL DesktopImageRegion; - RECTL DesktopImageClip; - }; -//--- -struct DISPLAYCONFIG_PATH_SOURCE_INFO - { - LUID adapterId; - uint id; - uint modeInfoIdx; - uint statusFlags; - }; -//--- -struct DISPLAYCONFIG_RATIONAL - { - uint Numerator; - uint Denominator; - }; -//--- -struct DISPLAYCONFIG_PATH_TARGET_INFO - { - LUID adapterId; - uint id; - uint modeInfoIdx; - DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; - DISPLAYCONFIG_ROTATION rotation; - DISPLAYCONFIG_SCALING scaling; - DISPLAYCONFIG_RATIONAL refreshRate; - DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; - int targetAvailable; - uint statusFlags; - }; -//--- -struct DISPLAYCONFIG_PATH_INFO - { - DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo; - DISPLAYCONFIG_PATH_TARGET_INFO targetInfo; - uint flags; - }; -//--- -struct DISPLAYCONFIG_SDR_WHITE_LEVEL - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - uint SDRWhiteLevel; - }; -//--- -struct DISPLAYCONFIG_SOURCE_DEVICE_NAME - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - short viewGdiDeviceName[CCHDEVICENAME]; - }; -//--- -struct DISPLAYCONFIG_SOURCE_MODE - { - uint width; - uint height; - DISPLAYCONFIG_PIXELFORMAT pixelFormat; - POINTL position; - }; -//--- -struct DISPLAYCONFIG_TARGET_BASE_TYPE - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY baseOutputTechnology; - }; -//--- -struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS - { - uint value; - }; -//--- -struct DISPLAYCONFIG_TARGET_DEVICE_NAME - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags; - DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; - ushort edidManufactureId; - ushort edidProductCodeId; - uint connectorInstance; - short monitorFriendlyDeviceName[64]; - short monitorDevicePath[128]; - }; -//--- -struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO - { - ulong pixelRate; - DISPLAYCONFIG_RATIONAL hSyncFreq; - DISPLAYCONFIG_RATIONAL vSyncFreq; - DISPLAYCONFIG_2DREGION activeSize; - DISPLAYCONFIG_2DREGION totalSize; - uint videoStandard; - DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; - }; -//--- -struct DISPLAYCONFIG_TARGET_MODE - { - DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo; - }; -//--- -struct DISPLAYCONFIG_TARGET_PREFERRED_MODE - { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - uint width; - uint height; - DISPLAYCONFIG_TARGET_MODE targetMode; - }; -//--- -struct DOCINFOW - { - int cbSize; - const string lpszDocName; - const string lpszOutput; - const string lpszDatatype; - uint fwType; - }; -//--- -struct DRAWPATRECT - { - POINT ptPosition; - POINT ptSize; - ushort wStyle; - ushort wPattern; - }; -//--- -struct EMR - { - uint iType; - uint nSize; - }; -//--- -struct EMRABORTPATH - { - EMR emr; - }; -//--- -struct XFORM - { - float eM11; - float eM12; - float eM21; - float eM22; - float eDx; - float eDy; - }; -//--- -struct EMRALPHABLEND - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int cxDest; - int cyDest; - uint dwRop; - int xSrc; - int ySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - int cxSrc; - int cySrc; - }; -//--- -struct EMRANGLEARC - { - EMR emr; - POINTL ptlCenter; - uint nRadius; - float eStartAngle; - float eSweepAngle; - }; -//--- -struct EMRARC - { - EMR emr; - RECTL rclBox; - POINTL ptlStart; - POINTL ptlEnd; - }; -//--- -struct EMRBITBLT - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int cxDest; - int cyDest; - uint dwRop; - int xSrc; - int ySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - }; -//--- -struct EMRCOLORCORRECTPALETTE - { - EMR emr; - uint ihPalette; - uint nFirstEntry; - uint nPalEntries; - uint nReserved; - }; -//--- -struct EMRCOLORMATCHTOTARGET - { - EMR emr; - uint dwAction; - uint dwFlags; - uint cbName; - uint cbData; - uchar Data[1]; - }; -//--- -struct LOGBRUSH - { - uint lbStyle; - uint lbColor; - ulong lbHatch; - }; -//--- -struct EMRCREATEBRUSHINDIRECT - { - EMR emr; - uint ihBrush; - LOGBRUSH lb; - }; -//--- -struct LOGCOLORSPACEW - { - uint lcsSignature; - uint lcsVersion; - uint lcsSize; - int lcsCSType; - int lcsIntent; - CIEXYZTRIPLE lcsEndpoints; - uint lcsGammaRed; - uint lcsGammaGreen; - uint lcsGammaBlue; - short lcsFilename[MAX_PATH]; - }; -//--- -struct EMRCREATECOLORSPACEW - { - EMR emr; - uint ihCS; - LOGCOLORSPACEW lcs; - uint dwFlags; - uint cbData; - uchar Data[1]; - }; -//--- -struct EMRCREATEDIBPATTERNBRUSHPT - { - EMR emr; - uint ihBrush; - uint iUsage; - uint offBmi; - uint cbBmi; - uint offBits; - uint cbBits; - }; -//--- -struct EMRCREATEMONOBRUSH - { - EMR emr; - uint ihBrush; - uint iUsage; - uint offBmi; - uint cbBmi; - uint offBits; - uint cbBits; - }; -//--- -struct LOGPALETTE - { - ushort palVersion; - ushort palNumEntries; - }; -//--- -struct LOGPEN - { - uint lopnStyle; - POINT lopnWidth; - uint lopnColor; - }; -//--- -struct EMRCREATEPALETTE - { - EMR emr; - uint ihPal; - LOGPALETTE lgpl; - }; -//--- -struct EMRCREATEPEN - { - EMR emr; - uint ihPen; - LOGPEN lopn; - }; -//--- -struct EMRELLIPSE - { - EMR emr; - RECTL rclBox; - }; -//--- -struct EMREOF - { - EMR emr; - uint nPalEntries; - uint offPalEntries; - uint nSizeLast; - }; -//--- -struct EMREXCLUDECLIPRECT - { - EMR emr; - RECTL rclClip; - }; -//--- -struct LOGFONTW - { - int lfHeight; - int lfWidth; - int lfEscapement; - int lfOrientation; - int lfWeight; - uchar lfItalic; - uchar lfUnderline; - uchar lfStrikeOut; - uchar lfCharSet; - uchar lfOutPrecision; - uchar lfClipPrecision; - uchar lfQuality; - uchar lfPitchAndFamily; - short lfFaceName[LF_FACESIZE]; - }; -//--- -struct PANOSE - { - uchar bFamilyType; - uchar bSerifStyle; - uchar bWeight; - uchar bProportion; - uchar bContrast; - uchar bStrokeVariation; - uchar bArmStyle; - uchar bLetterform; - uchar bMidline; - uchar bXHeight; - }; -//--- -struct EXTLOGFONTW - { - LOGFONTW elfLogFont; - short elfFullName[LF_FULLFACESIZE]; - short elfStyle[LF_FACESIZE]; - uint elfVersion; - uint elfStyleSize; - uint elfMatch; - uint elfReserved; - uchar elfVendorId[ELF_VENDOR_SIZE]; - uint elfCulture; - PANOSE elfPanose; - }; -//--- -struct EMREXTCREATEFONTINDIRECTW - { - EMR emr; - uint ihFont; - EXTLOGFONTW elfw; - }; -//--- -struct EXTLOGPEN - { - uint elpPenStyle; - uint elpWidth; - uint elpBrushStyle; - uint elpColor; - ulong elpHatch; - uint elpNumEntries; - uint elpStyleEntry[1]; - }; -//--- -struct EMREXTCREATEPEN - { - EMR emr; - uint ihPen; - uint offBmi; - uint cbBmi; - uint offBits; - uint cbBits; - EXTLOGPEN elp; - }; -//--- -struct EMREXTESCAPE - { - EMR emr; - int iEscape; - int cbEscData; - uchar EscData[1]; - }; -//--- -struct EMREXTFLOODFILL - { - EMR emr; - POINTL ptlStart; - uint crColor; - uint iMode; - }; -//--- -struct EMREXTSELECTCLIPRGN - { - EMR emr; - uint cbRgnData; - uint iMode; - uchar RgnData[1]; - }; -//--- -struct EMRTEXT - { - POINTL ptlReference; - uint nChars; - uint offString; - uint fOptions; - RECTL rcl; - uint offDx; - }; -//--- -struct EMREXTTEXTOUTA - { - EMR emr; - RECTL rclBounds; - uint iGraphicsMode; - float exScale; - float eyScale; - EMRTEXT emrtext; - }; -//--- -struct EMRFILLPATH - { - EMR emr; - RECTL rclBounds; - }; -//--- -struct EMRFILLRGN - { - EMR emr; - RECTL rclBounds; - uint cbRgnData; - uint ihBrush; - uchar RgnData[1]; - }; -//--- -struct EMRFORMAT - { - uint dSignature; - uint nVersion; - uint cbData; - uint offData; - }; -//--- -struct EMRFRAMERGN - { - EMR emr; - RECTL rclBounds; - uint cbRgnData; - uint ihBrush; - SIZE szlStroke; - uchar RgnData[1]; - }; -//--- -struct EMRGDICOMMENT - { - EMR emr; - uint cbData; - uchar Data[1]; - }; -//--- -struct EMRGLSBOUNDEDRECORD - { - EMR emr; - RECTL rclBounds; - uint cbData; - uchar Data[1]; - }; -//--- -struct EMRGLSRECORD - { - EMR emr; - uint cbData; - uchar Data[1]; - }; -//--- -struct PIXELFORMATDESCRIPTOR - { - ushort nSize; - ushort nVersion; - uint dwFlags; - uchar iPixelType; - uchar cColorBits; - uchar cRedBits; - uchar cRedShift; - uchar cGreenBits; - uchar cGreenShift; - uchar cBlueBits; - uchar cBlueShift; - uchar cAlphaBits; - uchar cAlphaShift; - uchar cAccumBits; - uchar cAccumRedBits; - uchar cAccumGreenBits; - uchar cAccumBlueBits; - uchar cAccumAlphaBits; - uchar cDepthBits; - uchar cStencilBits; - uchar cAuxBuffers; - uchar iLayerType; - uchar bReserved; - uint dwLayerMask; - uint dwVisibleMask; - uint dwDamageMask; - }; -//--- -struct TRIVERTEX - { - int x; - int y; - ushort red; - ushort green; - ushort blue; - ushort alpha; - }; -//--- -struct EMRGRADIENTFILL - { - EMR emr; - RECTL rclBounds; - uint nVer; - uint nTri; - uint ulMode; - TRIVERTEX Ver[1]; - }; -//--- -struct EMRINVERTRGN - { - EMR emr; - RECTL rclBounds; - uint cbRgnData; - uchar RgnData[1]; - }; -//--- -struct EMRLINETO - { - EMR emr; - POINTL ptl; - }; -//--- -struct EMRMASKBLT - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int cxDest; - int cyDest; - uint dwRop; - int xSrc; - int ySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - int xMask; - int yMask; - uint iUsageMask; - uint offBmiMask; - uint cbBmiMask; - uint offBitsMask; - uint cbBitsMask; - }; -//--- -struct EMRMODIFYWORLDTRANSFORM - { - EMR emr; - XFORM xform; - uint iMode; - }; -//--- -struct EMRNAMEDESCAPE - { - EMR emr; - int iEscape; - int cbDriver; - int cbEscData; - uchar EscData[1]; - }; -//--- -struct EMROFFSETCLIPRGN - { - EMR emr; - POINTL ptlOffset; - }; -//--- -struct EMRPIXELFORMAT - { - EMR emr; - PIXELFORMATDESCRIPTOR pfd; - }; -//--- -struct EMRPLGBLT - { - EMR emr; - RECTL rclBounds; - POINTL aptlDest[3]; - int xSrc; - int ySrc; - int cxSrc; - int cySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - int xMask; - int yMask; - uint iUsageMask; - uint offBmiMask; - uint cbBmiMask; - uint offBitsMask; - uint cbBitsMask; - }; -//--- -struct EMRPOLYDRAW - { - EMR emr; - RECTL rclBounds; - uint cptl; - POINTL aptl[1]; - uchar abTypes[1]; - }; -//--- -struct EMRPOLYDRAW16 - { - EMR emr; - RECTL rclBounds; - uint cpts; - POINTS apts[1]; - uchar abTypes[1]; - }; -//--- -struct EMRPOLYLINE - { - EMR emr; - RECTL rclBounds; - uint cptl; - POINTL aptl[1]; - }; -//--- -struct EMRPOLYLINE16 - { - EMR emr; - RECTL rclBounds; - uint cpts; - POINTS apts[1]; - }; -//--- -struct EMRPOLYPOLYLINE - { - EMR emr; - RECTL rclBounds; - uint nPolys; - uint cptl; - uint aPolyCounts[1]; - POINTL aptl[1]; - }; -//--- -struct EMRPOLYPOLYLINE16 - { - EMR emr; - RECTL rclBounds; - uint nPolys; - uint cpts; - uint aPolyCounts[1]; - POINTS apts[1]; - }; -//--- -struct EMRPOLYTEXTOUTW - { - EMR emr; - RECTL rclBounds; - uint iGraphicsMode; - float exScale; - float eyScale; - int cStrings; - EMRTEXT aemrtext[1]; - }; -//--- -struct EMRRESIZEPALETTE - { - EMR emr; - uint ihPal; - uint cEntries; - }; -//--- -struct EMRRESTOREDC - { - EMR emr; - int iRelative; - }; -//--- -struct EMRROUNDRECT - { - EMR emr; - RECTL rclBox; - SIZE szlCorner; - }; -//--- -struct EMRSCALEVIEWPORTEXTEX - { - EMR emr; - int xNum; - int xDenom; - int yNum; - int yDenom; - }; -//--- -struct EMRSELECTCLIPPATH - { - EMR emr; - uint iMode; - }; -//--- -struct EMRSELECTOBJECT - { - EMR emr; - uint ihObject; - }; -//--- -struct EMRSELECTPALETTE - { - EMR emr; - uint ihPal; - }; -//--- -struct EMRSETARCDIRECTION - { - EMR emr; - uint iArcDirection; - }; -//--- -struct EMRSETBKCOLOR - { - EMR emr; - uint crColor; - }; -//--- -struct EMRSETCOLORADJUSTMENT - { - EMR emr; - COLORADJUSTMENT ColorAdjustment; - }; -//--- -struct EMRSETCOLORSPACE - { - EMR emr; - uint ihCS; - }; -//--- -struct EMRSETDIBITSTODEVICE - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int xSrc; - int ySrc; - int cxSrc; - int cySrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - uint iUsageSrc; - uint iStartScan; - uint cScans; - }; -//--- -struct EMRSETICMPROFILE - { - EMR emr; - uint dwFlags; - uint cbName; - uint cbData; - uchar Data[1]; - }; -//--- -struct EMRSETMAPPERFLAGS - { - EMR emr; - uint dwFlags; - }; -//--- -struct EMRSETMITERLIMIT - { - EMR emr; - float eMiterLimit; - }; -//--- -struct PALETTEENTRY - { - uchar red; - uchar green; - uchar blue; - uchar flags; - }; -//--- -struct EMRSETPALETTEENTRIES - { - EMR emr; - uint ihPal; - uint iStart; - uint cEntries; - PALETTEENTRY aPalEntries[1]; - }; -//--- -struct EMRSETPIXELV - { - EMR emr; - POINTL ptlPixel; - uint crColor; - }; -//--- -struct EMRSETVIEWPORTEXTEX - { - EMR emr; - SIZE szlExtent; - }; -//--- -struct EMRSETVIEWPORTORGEX - { - EMR emr; - POINTL ptlOrigin; - }; -//--- -struct EMRSETWORLDTRANSFORM - { - EMR emr; - XFORM xform; - }; -//--- -struct EMRSTRETCHBLT - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int cxDest; - int cyDest; - uint dwRop; - int xSrc; - int ySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - int cxSrc; - int cySrc; - }; -//--- -struct EMRSTRETCHDIBITS - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int xSrc; - int ySrc; - int cxSrc; - int cySrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - uint iUsageSrc; - uint dwRop; - int cxDest; - int cyDest; - }; -//--- -struct EMRTRANSPARENTBLT - { - EMR emr; - RECTL rclBounds; - int xDest; - int yDest; - int cxDest; - int cyDest; - uint dwRop; - int xSrc; - int ySrc; - XFORM xformSrc; - uint crBkColorSrc; - uint iUsageSrc; - uint offBmiSrc; - uint cbBmiSrc; - uint offBitsSrc; - uint cbBitsSrc; - int cxSrc; - int cySrc; - }; -//--- -struct ENHMETAHEADER - { - uint iType; - uint nSize; - RECTL rclBounds; - RECTL rclFrame; - uint dSignature; - uint nVersion; - uint nBytes; - uint nRecords; - ushort nHandles; - ushort sReserved; - uint nDescription; - uint offDescription; - uint nPalEntries; - SIZE szlDevice; - SIZE szlMillimeters; - uint cbPixelFormat; - uint offPixelFormat; - uint bOpenGL; - SIZE szlMicrometers; - }; -//--- -struct ENHMETARECORD - { - uint iType; - uint nSize; - uint dParm[1]; - }; -//--- -struct ENUMLOGFONTEXW - { - LOGFONTW elfLogFont; - short elfFullName[LF_FULLFACESIZE]; - short elfStyle[LF_FACESIZE]; - short elfScript[LF_FACESIZE]; - }; -//--- -struct ENUMLOGFONTEXDVW - { - ENUMLOGFONTEXW elfEnumLogfontEx; - DESIGNVECTOR elfDesignVector; - }; -//--- -struct ENUMLOGFONTW - { - LOGFONTW elfLogFont; - short elfFullName[LF_FULLFACESIZE]; - short elfStyle[LF_FACESIZE]; - }; -//--- -struct NEWTEXTMETRICW - { - int tmHeight; - int tmAscent; - int tmDescent; - int tmInternalLeading; - int tmExternalLeading; - int tmAveCharWidth; - int tmMaxCharWidth; - int tmWeight; - int tmOverhang; - int tmDigitizedAspectX; - int tmDigitizedAspectY; - short tmFirstChar; - short tmLastChar; - short tmDefaultChar; - short tmBreakChar; - uchar tmItalic; - uchar tmUnderlined; - uchar tmStruckOut; - uchar tmPitchAndFamily; - uchar tmCharSet; - uint ntmFlags; - uint ntmSizeEM; - uint ntmCellHeight; - uint ntmAvgWidth; - }; -//--- -struct NEWTEXTMETRICEXW - { - NEWTEXTMETRICW ntmTm; - FONTSIGNATURE ntmFontSig; - }; -//--- -struct ENUMTEXTMETRICW - { - NEWTEXTMETRICEXW etmNewTextMetricEx; - AXESLISTW etmAxesList; - }; -//--- -struct FIXED - { - ushort fract; - short value; - }; -//--- -struct POINTFLOAT - { - float x; - float y; - }; -//--- -struct GCP_RESULTSW - { - uint lStructSize; - string lpOutString; - PVOID lpOrder; - PVOID lpDx; - PVOID lpCaretPos; - PVOID lpClass; - PVOID lpGlyphs; - uint nGlyphs; - int nMaxFit; - }; -//--- -struct GLYPHMETRICS - { - uint gmBlackBoxX; - uint gmBlackBoxY; - POINT gmptGlyphOrigin; - short gmCellIncX; - short gmCellIncY; - }; -//--- -struct GLYPHMETRICSFLOAT - { - float gmfBlackBoxX; - float gmfBlackBoxY; - POINTFLOAT gmfptGlyphOrigin; - float gmfCellIncX; - float gmfCellIncY; - }; -//--- -struct WCRANGE - { - short wcLow; - ushort cGlyphs; - }; -//--- -struct GLYPHSET - { - uint cbThis; - uint flAccel; - uint cGlyphsSupported; - uint cRanges; - WCRANGE ranges[1]; - }; -//--- -struct GRADIENT_RECT - { - uint UpperLeft; - uint LowerRight; - }; -//--- -struct GRADIENT_TRIANGLE - { - uint Vertex1; - uint Vertex2; - uint Vertex3; - }; -//--- -struct HANDLETABLE - { - PVOID objectHandle[1]; - }; -//--- -struct KERNINGPAIR - { - ushort wFirst; - ushort wSecond; - int iKernAmount; - }; -//--- -struct LAYERPLANEDESCRIPTOR - { - ushort nSize; - ushort nVersion; - uint dwFlags; - uchar iPixelType; - uchar cColorBits; - uchar cRedBits; - uchar cRedShift; - uchar cGreenBits; - uchar cGreenShift; - uchar cBlueBits; - uchar cBlueShift; - uchar cAlphaBits; - uchar cAlphaShift; - uchar cAccumBits; - uchar cAccumRedBits; - uchar cAccumGreenBits; - uchar cAccumBlueBits; - uchar cAccumAlphaBits; - uchar cDepthBits; - uchar cStencilBits; - uchar cAuxBuffers; - uchar iLayerPlane; - uchar bReserved; - uint crTransparent; - }; -//--- -struct LOCALESIGNATURE - { - uint lsUsb[4]; - uint lsCsbDefault[2]; - uint lsCsbSupported[2]; - }; -//--- -struct MAT2 - { - FIXED eM11; - FIXED eM12; - FIXED eM21; - FIXED eM22; - }; -//--- -struct METAFILEPICT - { - int mm; - int xExt; - int yExt; - HANDLE hMF; - }; -//--- -struct METAHEADER - { - ushort mtType; - ushort mtHeaderSize; - ushort mtVersion; - uint mtSize; - ushort mtNoObjects; - uint mtMaxRecord; - ushort mtNoParameters; - }; -//--- -struct METARECORD - { - uint rdSize; - ushort rdFunction; - ushort rdParm[1]; - }; -//--- -struct TEXTMETRICW - { - int tmHeight; - int tmAscent; - int tmDescent; - int tmInternalLeading; - int tmExternalLeading; - int tmAveCharWidth; - int tmMaxCharWidth; - int tmWeight; - int tmOverhang; - int tmDigitizedAspectX; - int tmDigitizedAspectY; - short tmFirstChar; - short tmLastChar; - short tmDefaultChar; - short tmBreakChar; - uchar tmItalic; - uchar tmUnderlined; - uchar tmStruckOut; - uchar tmPitchAndFamily; - uchar tmCharSet; - }; -//--- -struct OUTLINETEXTMETRICW - { - uint otmSize; - TEXTMETRICW otmTextMetrics; - uchar otmFiller; - PANOSE otmPanoseNumber; - uint otmfsSelection; - uint otmfsType; - int otmsCharSlopeRise; - int otmsCharSlopeRun; - int otmItalicAngle; - uint otmEMSquare; - int otmAscent; - int otmDescent; - uint otmLineGap; - uint otmsCapEmHeight; - uint otmsXHeight; - RECT otmrcFontBox; - int otmMacAscent; - int otmMacDescent; - uint otmMacLineGap; - uint otmusMinimumPPEM; - POINT otmptSubscriptSize; - POINT otmptSubscriptOffset; - POINT otmptSuperscriptSize; - POINT otmptSuperscriptOffset; - uint otmsStrikeoutSize; - int otmsStrikeoutPosition; - int otmsUnderscoreSize; - int otmsUnderscorePosition; - PVOID otmpFamilyName; //char otmpFamilyName[]; - PVOID otmpFaceName; //char otmpFaceName[]; - PVOID otmpStyleName; //char otmpStyleName[]; - PVOID otmpFullName; //char otmpFullName[]; - }; -//--- -struct PELARRAY - { - int paXCount; - int paYCount; - int paXExt; - int paYExt; - uchar paRGBs; - }; -//--- -struct POINTFX - { - FIXED x; - FIXED y; - }; -//--- -struct POLYTEXTW - { - int x; - int y; - uint n; - const string lpstr; - uint uiFlags; - RECT rcl; - PVOID pdx; - }; -//--- -struct PSFEATURE_CUSTPAPER - { - int lOrientation; - int lWidth; - int lHeight; - int lWidthOffset; - int lHeightOffset; - }; -//--- -struct PSFEATURE_OUTPUT - { - int bPageIndependent; - int bSetPageDevice; - }; -//--- -struct PSINJECTDATA - { - uint DataBytes; - ushort InjectionPoint; - ushort PageNumber; - }; -//--- -struct RASTERIZER_STATUS - { - short nSize; - short wFlags; - short nLanguageID; - }; -//--- -struct RGNDATAHEADER - { - uint dwSize; - uint iType; - uint nCount; - uint nRgnSize; - RECT rcBound; - }; -//--- -struct RGNDATA - { - RGNDATAHEADER rdh; - char Buffer[1]; - }; -//--- -struct TTPOLYCURVE - { - ushort wType; - ushort cpfx; - POINTFX apfx[1]; - }; -//--- -struct TTPOLYGONHEADER - { - uint cb; - uint dwType; - POINTFX pfxStart; - }; -//--- -struct DEVMODEW - { - short dmDeviceName[CCHDEVICENAME]; - ushort dmSpecVersion; - ushort dmDriverVersion; - ushort dmSize; - ushort dmDriverExtra; - uint dmFields; - short dmOrientation; - short dmPaperSize; - short dmPaperLength; - short dmPaperWidth; - short dmScale; - short dmCopies; - short dmDefaultSource; - short dmPrintQuality; - short dmColor; - short dmDuplex; - short dmYResolution; - short dmTTOption; - short dmCollate; - short dmFormName[CCHFORMNAME]; - ushort dmLogPixels; - uint dmBitsPerPel; - uint dmPelsWidth; - uint dmPelsHeight; - uint dmDisplayFlags; - uint dmDisplayFrequency; - uint dmICMMethod; - uint dmICMIntent; - uint dmMediaType; - uint dmDitherType; - uint dmReserved1; - uint dmReserved2; - uint dmPanningWidth; - uint dmPanningHeight; - }; -//--- -struct WGLSWAP - { - HANDLE hdc; - uint uiFlags; - }; -//--- -union DISPLAYCONFIG_MODE - { - DISPLAYCONFIG_TARGET_MODE targetMode; - DISPLAYCONFIG_SOURCE_MODE sourceMode; - DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo; - }; -//--- -struct DISPLAYCONFIG_MODE_INFO - { - DISPLAYCONFIG_MODE_INFO_TYPE infoType; - uint id; - LUID adapterId; - DISPLAYCONFIG_MODE mode; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "gdi32.dll" -int AbortDoc(HANDLE hdc); -int AbortPath(HANDLE hdc); -HANDLE AddFontMemResourceEx(PVOID file_view,uint size,PVOID resrved,uint &num_fonts); -int AddFontResourceExW(const string name,uint fl,PVOID res); -int AddFontResourceW(string); -int AngleArc(HANDLE hdc,int x,int y,uint r,float StartAngle,float SweepAngle); -int AnimatePalette(HANDLE pal,uint start_index,uint entries,PALETTEENTRY &ppe); -int Arc(HANDLE hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); -int ArcTo(HANDLE hdc,int left,int top,int right,int bottom,int xr1,int yr1,int xr2,int yr2); -int BeginPath(HANDLE hdc); -int BitBlt(HANDLE hdc,int x,int y,int cx,int cy,HANDLE src,int x1,int y1,uint rop); -int CancelDC(HANDLE hdc); -int CheckColorsInGamut(HANDLE hdc,RGBTRIPLE &lpRGBTriple,PVOID buffer,uint count); -int ChoosePixelFormat(HANDLE hdc,PIXELFORMATDESCRIPTOR &ppfd); -int Chord(HANDLE hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); -HANDLE CloseEnhMetaFile(HANDLE hdc); -int CloseFigure(HANDLE hdc); -HANDLE CloseMetaFile(HANDLE hdc); -int ColorCorrectPalette(HANDLE hdc,HANDLE pal,uint first,uint num); -int ColorMatchToTarget(HANDLE hdc,HANDLE target,uint action); -int CombineRgn(HANDLE dst,HANDLE src1,HANDLE src2,int mode); -int CombineTransform(XFORM &out,XFORM &lpxf1,XFORM &lpxf2); -HANDLE CopyEnhMetaFileW(HANDLE enh,const string file_name); -HANDLE CopyMetaFileW(HANDLE,string LPCWSTR); -HANDLE CreateBitmap(int width,int height,uint planes,uint bit_count,PVOID bits); -HANDLE CreateBitmap(int width,int height,uint planes,uint bit_count,char &bits[]); -HANDLE CreateBitmapIndirect(BITMAP &pbm); -HANDLE CreateBrushIndirect(LOGBRUSH &plbrush); -HANDLE CreateColorSpaceW(LOGCOLORSPACEW &lplcs); -HANDLE CreateCompatibleBitmap(HANDLE hdc,int cx,int cy); -HANDLE CreateCompatibleDC(HANDLE hdc); -HANDLE CreateDCW(const string driver,const string device,const string port,DEVMODEW &pdm); -HANDLE CreateDIBitmap(HANDLE hdc,BITMAPINFOHEADER &pbmih,uint init,PVOID bits,BITMAPINFO &pbmi,uint usage); -HANDLE CreateDIBPatternBrush(HANDLE h,uint usage); -HANDLE CreateDIBPatternBrushPt(PVOID lpPackedDIB,uint usage); -HANDLE CreateDIBSection(HANDLE hdc,BITMAPINFO &pbmi,uint usage,PVOID bits,HANDLE section,uint offset); -HANDLE CreateDiscardableBitmap(HANDLE hdc,int cx,int cy); -HANDLE CreateEllipticRgn(int x1,int y1,int x2,int y2); -HANDLE CreateEllipticRgnIndirect(RECT &lprect); -HANDLE CreateEnhMetaFileW(HANDLE hdc,const string filename,RECT &lprc,const string desc); -HANDLE CreateFontIndirectExW(ENUMLOGFONTEXDVW &); -HANDLE CreateFontIndirectW(LOGFONTW &lplf); -HANDLE CreateFontW(int height,int width,int escapement,int orientation,int weight,uint italic,uint underline,uint strike_out,uint char_set,uint out_precision,uint clip_precision,uint quality,uint pitch_and_family,const string face_name); -HANDLE CreateHalftonePalette(HANDLE hdc); -HANDLE CreateHatchBrush(int hatch,uint clr); -HANDLE CreateICW(const string driver,const string device,const string port,DEVMODEW &pdm); -HANDLE CreateMetaFileW(const string file); -HANDLE CreatePalette(LOGPALETTE &plpal); -HANDLE CreatePatternBrush(HANDLE hbm); -HANDLE CreatePen(int style,int width,uint clr); -HANDLE CreatePenIndirect(LOGPEN &plpen); -HANDLE CreatePolygonRgn(POINT &pptl[],int point,int mode); -HANDLE CreatePolyPolygonRgn(const POINT &pptl[],const int &pc[],int poly,int mode); -HANDLE CreateRectRgn(int x1,int y1,int x2,int y2); -HANDLE CreateRectRgnIndirect(RECT &lprect); -HANDLE CreateRoundRectRgn(int x1,int y1,int x2,int y2,int w,int h); -int CreateScalableFontResourceW(uint hidden,const string font,const string file,const string path); -HANDLE CreateSolidBrush(uint clr); -int DeleteColorSpace(HANDLE hcs); -int DeleteDC(HANDLE hdc); -int DeleteEnhMetaFile(HANDLE hmf); -int DeleteMetaFile(HANDLE hmf); -int DeleteObject(PVOID ho); -int DescribePixelFormat(HANDLE hdc,int pixel_format,uint bytes,PIXELFORMATDESCRIPTOR &ppfd); -int DPtoLP(HANDLE hdc,POINT &lppt,int c); -int DrawEscape(HANDLE hdc,int escape,int in,uchar &in[]); -int Ellipse(HANDLE hdc,int left,int top,int right,int bottom); -int EndDoc(HANDLE hdc); -int EndPage(HANDLE hdc); -int EndPath(HANDLE hdc); -int EnumEnhMetaFile(HANDLE hdc,HANDLE hmf,PVOID proc,PVOID param,RECT &rect); -int EnumFontFamiliesExW(HANDLE hdc,LOGFONTW &logfont,PVOID proc,PVOID param,uint flags); -int EnumFontFamiliesW(HANDLE hdc,const string logfont,PVOID proc,PVOID param); -int EnumFontsW(HANDLE hdc,const string logfont,PVOID proc,PVOID param); -int EnumICMProfilesW(HANDLE hdc,PVOID proc,PVOID param); -int EnumMetaFile(HANDLE hdc,HANDLE hmf,PVOID proc,PVOID param); -int EnumObjects(HANDLE hdc,int type,PVOID func,PVOID param); -int EqualRgn(HANDLE hrgn1,HANDLE hrgn2); -int Escape(HANDLE hdc,int escape,int in,uchar &in[],PVOID out); -int ExcludeClipRect(HANDLE hdc,int left,int top,int right,int bottom); -HANDLE ExtCreatePen(uint pen_style,uint width,LOGBRUSH &plbrush,uint style,const uint &pstyle[]); -HANDLE ExtCreateRegion(XFORM &lpx,uint count,RGNDATA &data); -int ExtEscape(HANDLE hdc,int escape,int inp,uchar &in_data[],int output,uchar &out_data[]); -int ExtFloodFill(HANDLE hdc,int x,int y,uint clr,uint type); -int ExtSelectClipRgn(HANDLE hdc,HANDLE hrgn,int mode); -int ExtTextOutW(HANDLE hdc,int x,int y,uint options,const RECT &lprect,const string str,uint c,const int &dx[]); -int FillPath(HANDLE hdc); -int FillRgn(HANDLE hdc,HANDLE hrgn,HANDLE hbr); -int FixBrushOrgEx(HANDLE hdc,int x,int y,POINT &ptl); -int FlattenPath(HANDLE hdc); -int FloodFill(HANDLE hdc,int x,int y,uint clr); -int FrameRgn(HANDLE hdc,HANDLE hrgn,HANDLE hbr,int w,int h); -int GdiAlphaBlend(HANDLE dest,int dest,int dest,int dest,int dest,HANDLE src,int src,int src,int src,int src,BLENDFUNCTION &ftn); -int GdiComment(HANDLE hdc,uint size,const uchar &data[]); -int GdiFlush(void); -uint GdiGetBatchLimit(void); -int GdiGradientFill(HANDLE hdc,TRIVERTEX &vertex,uint vertex,PVOID mesh,uint count,uint mode); -uint GdiSetBatchLimit(uint dw); -int GdiTransparentBlt(HANDLE dest,int dest,int dest,int dest,int dest,HANDLE src,int src,int src,int src,int src,uint transparent); -int GetArcDirection(HANDLE hdc); -int GetAspectRatioFilterEx(HANDLE hdc,SIZE &lpsize); -int GetBitmapBits(HANDLE hbit,int cb,PVOID bits); -int GetBitmapDimensionEx(HANDLE hbit,SIZE &lpsize); -uint GetBkColor(HANDLE hdc); -int GetBkMode(HANDLE hdc); -uint GetBoundsRect(HANDLE hdc,RECT &lprect,uint flags); -int GetBrushOrgEx(HANDLE hdc,POINT &lppt); -int GetCharABCWidthsFloatW(HANDLE hdc,uint first,uint last,ABCFLOAT &lpABC[]); -int GetCharABCWidthsI(HANDLE hdc,uint first,uint cgi,ushort &pgi[],ABC &pabc[]); -int GetCharABCWidthsW(HANDLE hdc,uint first,uint last,ABC &lpABC[]); -uint GetCharacterPlacementW(HANDLE hdc,const string str,int count,int mex_extent,GCP_RESULTSW &results,uint flags); -int GetCharWidthFloatW(HANDLE hdc,uint first,uint last,float &buffer[]); -int GetCharWidthI(HANDLE hdc,uint first,uint cgi,ushort &pgi[],int &widths[]); -int GetCharWidthW(HANDLE hdc,uint first,uint last,int &buffer[]); -int GetClipBox(HANDLE hdc,RECT &lprect); -int GetClipRgn(HANDLE hdc,HANDLE hrgn); -int GetColorAdjustment(HANDLE hdc,COLORADJUSTMENT &lpca); -HANDLE GetColorSpace(HANDLE hdc); -PVOID GetCurrentObject(HANDLE hdc,uint type); -int GetCurrentPositionEx(HANDLE hdc,POINT &lppt); -uint GetDCBrushColor(HANDLE hdc); -int GetDCOrgEx(HANDLE hdc,POINT &lppt); -uint GetDCPenColor(HANDLE hdc); -int GetDeviceCaps(HANDLE hdc,int index); -int GetDeviceGammaRamp(HANDLE hdc,PVOID ramp); -int GetDeviceGammaRamp(HANDLE hdc,ushort &ramp[]); -uint GetDIBColorTable(HANDLE hdc,uint start,uint entries,RGBQUAD &prgbq[]); -int GetDIBits(HANDLE hdc,HANDLE hbm,uint start,uint lines,PVOID bits,BITMAPINFO &lpbmi,uint usage); -uint GetEnhMetaFileBits(HANDLE hEMF,uint size,uchar &data[]); -uint GetEnhMetaFileDescriptionW(HANDLE hemf,uint buffer,string description); -uint GetEnhMetaFileHeader(HANDLE hemf,uint size,ENHMETAHEADER &enh_meta_header); -uint GetEnhMetaFilePaletteEntries(HANDLE hemf,uint num_entries,PALETTEENTRY &palette_entries); -uint GetEnhMetaFilePixelFormat(HANDLE hemf,uint buffer,PIXELFORMATDESCRIPTOR &ppfd); -HANDLE GetEnhMetaFileW(const string name); -uint GetFontData(HANDLE hdc,uint table,uint offset,PVOID buffer,uint buffer); -uint GetFontLanguageInfo(HANDLE hdc); -uint GetFontUnicodeRanges(HANDLE hdc,PVOID lpgs); -uint GetFontUnicodeRanges(HANDLE hdc,GLYPHSET &lpgs); -uint GetGlyphIndicesW(HANDLE hdc,const string lpstr,int c,ushort &pgi[],uint fl); -uint GetGlyphOutlineW(HANDLE hdc,uint symbol,uint format,GLYPHMETRICS &lpgm,uint buffer,PVOID buffer,MAT2 &lpmat2); -int GetGraphicsMode(HANDLE hdc); -int GetICMProfileW(HANDLE hdc,uint &buf_size,ushort &filename[]); -uint GetKerningPairsW(HANDLE hdc,uint pairs,KERNINGPAIR &kern_pair); -uint GetLayout(HANDLE hdc); -int GetLogColorSpaceW(HANDLE color_space,LOGCOLORSPACEW &buffer,uint size); -int GetMapMode(HANDLE hdc); -uint GetMetaFileBitsEx(HANDLE hMF,uint buffer,PVOID data); -HANDLE GetMetaFileW(const string name); -int GetMetaRgn(HANDLE hdc,HANDLE hrgn); -int GetMiterLimit(HANDLE hdc,float &plimit); -uint GetNearestColor(HANDLE hdc,uint clr); -uint GetNearestPaletteIndex(HANDLE h,uint clr); -uint GetObjectType(PVOID h); -int GetObjectW(HANDLE h,int c,PVOID pv); -uint GetOutlineTextMetricsW(HANDLE hdc,uint copy,OUTLINETEXTMETRICW &potm); -uint GetPaletteEntries(HANDLE hpal,uint start,uint entries,PALETTEENTRY &pal_entries); -int GetPath(HANDLE hdc,POINT &apt,uchar &aj,int cpt); -uint GetPixel(HANDLE hdc,int x,int y); -int GetPixelFormat(HANDLE hdc); -int GetPolyFillMode(HANDLE hdc); -int GetRandomRgn(HANDLE hdc,HANDLE hrgn,int i); -int GetRasterizerCaps(RASTERIZER_STATUS &lpraststat,uint bytes); -uint GetRegionData(HANDLE hrgn,uint count,RGNDATA &rgn_data); -uint GetRegionData(HANDLE hrgn,uint count,PVOID rgn_data); -int GetRgnBox(HANDLE hrgn,RECT &lprc); -int GetROP2(HANDLE hdc); -PVOID GetStockObject(int i); -int GetStretchBltMode(HANDLE hdc); -uint GetSystemPaletteEntries(HANDLE hdc,uint start,uint entries,PALETTEENTRY &pal_entries); -uint GetSystemPaletteUse(HANDLE hdc); -uint GetTextAlign(HANDLE hdc); -int GetTextCharacterExtra(HANDLE hdc); -int GetTextCharset(HANDLE hdc); -int GetTextCharsetInfo(HANDLE hdc,FONTSIGNATURE &sig,uint flags); -uint GetTextColor(HANDLE hdc); -int GetTextExtentExPointI(HANDLE hdc,ushort &str[],int str_size,int max_extent,int &fit,int &dx[],SIZE &size); -int GetTextExtentExPointW(HANDLE hdc,const string str,int str,int max_extent,int &fit,int &dx[],SIZE &size); -int GetTextExtentPoint32W(HANDLE hdc,const string str,int c,SIZE &psizl); -int GetTextExtentPointI(HANDLE hdc,ushort &in[],int cgi,SIZE &psize); -int GetTextExtentPointW(HANDLE hdc,const string str,int c,SIZE &lpsz); -int GetTextFaceW(HANDLE hdc,int c,ushort &name[]); -int GetTextMetricsW(HANDLE hdc,TEXTMETRICW &lptm); -int GetViewportExtEx(HANDLE hdc,SIZE &lpsize); -int GetViewportOrgEx(HANDLE hdc,POINT &lppoint); -int GetWindowExtEx(HANDLE hdc,SIZE &lpsize); -int GetWindowOrgEx(HANDLE hdc,POINT &lppoint); -uint GetWinMetaFileBits(HANDLE hemf,uint data16,uchar &data16,int map_mode,HANDLE ref); -int GetWorldTransform(HANDLE hdc,XFORM &lpxf); -int IntersectClipRect(HANDLE hdc,int left,int top,int right,int bottom); -int InvertRgn(HANDLE hdc,HANDLE hrgn); -int LineTo(HANDLE hdc,int x,int y); -int LPtoDP(HANDLE hdc,POINT &lppt[],int c); -int MaskBlt(HANDLE dest,int dest,int dest,int width,int height,HANDLE src,int src,int src,HANDLE mask,int mask,int mask,uint rop); -int ModifyWorldTransform(HANDLE hdc,XFORM &lpxf,uint mode); -int MoveToEx(HANDLE hdc,int x,int y,POINT &lppt); -int OffsetClipRgn(HANDLE hdc,int x,int y); -int OffsetRgn(HANDLE hrgn,int x,int y); -int OffsetViewportOrgEx(HANDLE hdc,int x,int y,POINT &lppt); -int OffsetWindowOrgEx(HANDLE hdc,int x,int y,POINT &lppt); -int PaintRgn(HANDLE hdc,HANDLE hrgn); -int PatBlt(HANDLE hdc,int x,int y,int w,int h,uint rop); -HANDLE PathToRegion(HANDLE hdc); -int Pie(HANDLE hdc,int left,int top,int right,int bottom,int xr1,int yr1,int xr2,int yr2); -int PlayEnhMetaFile(HANDLE hdc,HANDLE hmf,RECT &lprect); -int PlayEnhMetaFileRecord(HANDLE hdc,HANDLETABLE &pht,ENHMETARECORD &pmr,uint cht); -int PlayMetaFile(HANDLE hdc,HANDLE hmf); -int PlayMetaFileRecord(HANDLE hdc,HANDLETABLE &handle_table,METARECORD &lpMR,uint objs); -int PlgBlt(HANDLE dest,POINT &point,HANDLE src,int src,int src,int width,int height,HANDLE mask,int mask,int mask); -int PolyBezier(HANDLE hdc,POINT &apt,uint cpt); -int PolyBezierTo(HANDLE hdc,POINT &apt,uint cpt); -int PolyDraw(HANDLE hdc,const POINT &apt,const uchar &aj[],int cpt); -int Polygon(HANDLE hdc,const POINT &apt,int cpt); -int Polyline(HANDLE hdc,const POINT &apt,int cpt); -int PolylineTo(HANDLE hdc,const POINT &apt,uint cpt); -int PolyPolygon(HANDLE hdc,const POINT &apt,int &asz[],int csz); -int PolyPolyline(HANDLE hdc,const POINT &apt,uint &asz[],uint csz); -int PolyTextOutW(HANDLE hdc,POLYTEXTW &ppt,int nstrings); -int PtInRegion(HANDLE hrgn,int x,int y); -int PtVisible(HANDLE hdc,int x,int y); -uint RealizePalette(HANDLE hdc); -int Rectangle(HANDLE hdc,int left,int top,int right,int bottom); -int RectInRegion(HANDLE hrgn,RECT &lprect); -int RectVisible(HANDLE hdc,RECT &lprect); -int RemoveFontMemResourceEx(HANDLE h); -int RemoveFontResourceExW(const string name,uint fl,PVOID pdv); -int RemoveFontResourceW(const string file_name); -HANDLE ResetDCW(HANDLE hdc,DEVMODEW &lpdm); -int ResizePalette(HANDLE hpal,uint n); -int RestoreDC(HANDLE hdc,int nSavedDC); -int RoundRect(HANDLE hdc,int left,int top,int right,int bottom,int width,int height); -int SaveDC(HANDLE hdc); -int ScaleViewportExtEx(HANDLE hdc,int xn,int dx,int yn,int yd,SIZE &lpsz); -int ScaleWindowExtEx(HANDLE hdc,int xn,int xd,int yn,int yd,SIZE &lpsz); -int SelectClipPath(HANDLE hdc,int mode); -int SelectClipRgn(HANDLE hdc,HANDLE hrgn); -PVOID SelectObject(HANDLE hdc,PVOID h); -HANDLE SelectPalette(HANDLE hdc,HANDLE pal,int force_bkgd); -int SetAbortProc(HANDLE hdc,PVOID proc); -int SetArcDirection(HANDLE hdc,int dir); -int SetBitmapBits(HANDLE hbm,uint cb,const uchar &bits[]); -int SetBitmapDimensionEx(HANDLE hbm,int w,int h,SIZE &lpsz); -uint SetBkColor(HANDLE hdc,uint clr); -int SetBkMode(HANDLE hdc,int mode); -uint SetBoundsRect(HANDLE hdc,RECT &lprect,uint flags); -int SetBrushOrgEx(HANDLE hdc,int x,int y,POINT &lppt); -int SetColorAdjustment(HANDLE hdc,COLORADJUSTMENT &lpca); -HANDLE SetColorSpace(HANDLE hdc,HANDLE hcs); -uint SetDCBrushColor(HANDLE hdc,uint clr); -uint SetDCPenColor(HANDLE hdc,uint clr); -int SetDeviceGammaRamp(HANDLE hdc,PVOID ramp); -uint SetDIBColorTable(HANDLE hdc,uint start,uint entries,RGBQUAD &prgbq); -int SetDIBits(HANDLE hdc,HANDLE hbm,uint start,uint lines,PVOID bits,BITMAPINFO &lpbmi,uint ColorUse); -int SetDIBitsToDevice(HANDLE hdc,int dest,int dest,uint w,uint h,int src,int src,uint StartScan,uint lines,PVOID bits,BITMAPINFO &lpbmi,uint ColorUse); -HANDLE SetEnhMetaFileBits(uint size,const uchar &pb[]); -int SetGraphicsMode(HANDLE hdc,int mode); -int SetICMMode(HANDLE hdc,int mode); -int SetICMProfileW(HANDLE hdc,string file_name); -uint SetLayout(HANDLE hdc,uint l); -int SetMapMode(HANDLE hdc,int mode); -uint SetMapperFlags(HANDLE hdc,uint flags); -HANDLE SetMetaFileBitsEx(uint buffer,const uchar &data[]); -int SetMetaRgn(HANDLE hdc); -int SetMiterLimit(HANDLE hdc,float limit,float &old); -uint SetPaletteEntries(HANDLE hpal,uint start,uint entries,PALETTEENTRY &pal_entries); -uint SetPixel(HANDLE hdc,int x,int y,uint clr); -int SetPixelFormat(HANDLE hdc,int format,PIXELFORMATDESCRIPTOR &ppfd); -int SetPixelV(HANDLE hdc,int x,int y,uint clr); -int SetPolyFillMode(HANDLE hdc,int mode); -int SetRectRgn(HANDLE hrgn,int left,int top,int right,int bottom); -int SetROP2(HANDLE hdc,int rop2); -int SetStretchBltMode(HANDLE hdc,int mode); -uint SetSystemPaletteUse(HANDLE hdc,uint use); -uint SetTextAlign(HANDLE hdc,uint align); -int SetTextCharacterExtra(HANDLE hdc,int extra); -uint SetTextColor(HANDLE hdc,uint clr); -int SetTextJustification(HANDLE hdc,int extra,int count); -int SetViewportExtEx(HANDLE hdc,int x,int y,SIZE &lpsz); -int SetViewportOrgEx(HANDLE hdc,int x,int y,POINT &lppt); -int SetWindowExtEx(HANDLE hdc,int x,int y,SIZE &lpsz); -int SetWindowOrgEx(HANDLE hdc,int x,int y,POINT &lppt); -HANDLE SetWinMetaFileBits(uint size,const uchar &lpMeta16Data[],HANDLE ref,const METAFILEPICT &lpMFP); -int SetWorldTransform(HANDLE hdc,XFORM &lpxf); -int StartDocW(HANDLE hdc,DOCINFOW &lpdi); -int StartPage(HANDLE hdc); -int StretchBlt(HANDLE dest,int dest,int dest,int dest,int dest,HANDLE src,int src,int src,int src,int src,uint rop); -int StretchDIBits(HANDLE hdc,int dest,int dest,int DestWidth,int DestHeight,int src,int src,int SrcWidth,int SrcHeight,PVOID bits,BITMAPINFO &lpbmi,uint usage,uint rop); -int StrokeAndFillPath(HANDLE hdc); -int StrokePath(HANDLE hdc); -int SwapBuffers(HANDLE); -int TextOutW(HANDLE hdc,int x,int y,const string str,int c); -int TranslateCharsetInfo(PVOID src,CHARSETINFO &cs,uint flags); -int UnrealizeObject(PVOID h); -int UpdateColors(HANDLE hdc); -int UpdateICMRegKeyW(uint reserved,string lpszCMID,string file_name,uint command); -int WidenPath(HANDLE hdc); -#import - -#import "Opengl32.dll" -int wglCopyContext(HANDLE,HANDLE,uint); -HANDLE wglCreateContext(HANDLE); -HANDLE wglCreateLayerContext(HANDLE,int); -int wglDeleteContext(HANDLE); -int wglDescribeLayerPlane(HANDLE,int,int,uint,LAYERPLANEDESCRIPTOR &); -HANDLE wglGetCurrentContext(void); -HANDLE wglGetCurrentDC(void); -int wglGetLayerPaletteEntries(HANDLE,int,int,int,const uint &[]); -PVOID wglGetProcAddress(string); -int wglMakeCurrent(HANDLE,HANDLE); -int wglRealizeLayerPalette(HANDLE,int,int); -int wglSetLayerPaletteEntries(HANDLE,int,int,int,const uint &[]); -int wglShareLists(HANDLE,HANDLE); -int wglSwapLayerBuffers(HANDLE,uint); -uint wglSwapMultipleBuffers(uint,WGLSWAP &); -int wglUseFontBitmapsW(HANDLE,uint,uint,uint); -int wglUseFontOutlinesW(HANDLE,uint,uint,uint,float,float,int,GLYPHMETRICSFLOAT &); -#import -//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/Include/WinAPI/winnt.mqh b/Include/WinAPI/winnt.mqh deleted file mode 100644 index a282c00..0000000 --- a/Include/WinAPI/winnt.mqh +++ /dev/null @@ -1,3642 +0,0 @@ -//+------------------------------------------------------------------+ -//| winnt.mqh | -//| Copyright 2018, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include - -//--- -#define UNWIND_HISTORY_TABLE_SIZE 12 -#define SIZE_OF_80387_REGISTERS 80 -#define MAXIMUM_SUPPORTED_EXTENSION 512 -#define WOW64_SIZE_OF_80387_REGISTERS 80 -#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512 -#define SID_HASH_SIZE 32 -#define POLICY_AUDIT_SUBCATEGORY_COUNT 59 -#define TOKEN_SOURCE_LENGTH 8 -#define MAXIMUM_XSTATE_FEATURES 64 -#define POWER_SYSTEM_MAXIMUM 7 -#define NUM_DISCHARGE_POLICIES 4 -#define HIBERFILE_TYPE_MAX 0x03 -#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 -#define IMAGE_SIZEOF_SHORT_NAME 8 -#define IMAGE_ENCLAVE_LONG_ID_LENGTH 32 -#define IMAGE_ENCLAVE_SHORT_ID_LENGTH 16 -#define RTL_CORRELATION_VECTOR_STRING_LENGTH 129 - -//--- -enum SID_NAME_USE - { - SidTypeUser=1, - SidTypeGroup, - SidTypeDomain, - SidTypeAlias, - SidTypeWellKnownGroup, - SidTypeDeletedAccount, - SidTypeInvalid, - SidTypeUnknown, - SidTypeComputer, - SidTypeLabel, - SidTypeLogonSession - }; -//--- -enum ACL_INFORMATION_CLASS - { - AclRevisionInformation=1, - AclSizeInformation - }; -//--- -enum AUDIT_EVENT_TYPE - { - AuditEventObjectAccess, - AuditEventDirectoryServiceAccess - }; -//--- -enum ACCESS_REASON_TYPE - { - AccessReasonNone=0x00000000, - AccessReasonAllowedAce=0x00010000, - AccessReasonDeniedAce=0x00020000, - AccessReasonAllowedParentAce=0x00030000, - AccessReasonDeniedParentAce=0x00040000, - AccessReasonNotGrantedByCape=0x00050000, - AccessReasonNotGrantedByParentCape=0x00060000, - AccessReasonNotGrantedToAppContainer=0x00070000, - AccessReasonMissingPrivilege=0x00100000, - AccessReasonFromPrivilege=0x00200000, - AccessReasonIntegrityLevel=0x00300000, - AccessReasonOwnership=0x00400000, - AccessReasonNullDacl=0x00500000, - AccessReasonEmptyDacl=0x00600000, - AccessReasonNoSD=0x00700000, - AccessReasonNoGrant=0x00800000, - AccessReasonTrustLabel=0x00900000, - AccessReasonFilterAce=0x00a00000 - }; -//--- -enum SECURITY_IMPERSONATION_LEVEL - { - SecurityAnonymous, - SecurityIdentification, - SecurityImpersonation, - SecurityDelegation - }; -//--- -enum TOKEN_TYPE - { - TokenPrimary=1, - TokenImpersonation - }; -//--- -enum TOKEN_ELEVATION_TYPE - { - TokenElevationTypeDefault=1, - TokenElevationTypeFull, - TokenElevationTypeLimited - }; -//--- -enum TOKEN_INFORMATION_CLASS - { - TokenUser=1, - TokenGroups, - TokenPrivileges, - TokenOwner, - TokenPrimaryGroup, - TokenDefaultDacl, - TokenSource, - TokenType, - TokenImpersonationLevel, - TokenStatistics, - TokenRestrictedSids, - TokenSessionId, - TokenGroupsAndPrivileges, - TokenSessionReference, - TokenSandBoxInert, - TokenAuditPolicy, - TokenOrigin, - TokenElevationType, - TokenLinkedToken, - TokenElevation, - TokenHasRestrictions, - TokenAccessInformation, - TokenVirtualizationAllowed, - TokenVirtualizationEnabled, - TokenIntegrityLevel, - TokenUIAccess, - TokenMandatoryPolicy, - TokenLogonSid, - TokenIsAppContainer, - TokenCapabilities, - TokenAppContainerSid, - TokenAppContainerNumber, - TokenUserClaimAttributes, - TokenDeviceClaimAttributes, - TokenRestrictedUserClaimAttributes, - TokenRestrictedDeviceClaimAttributes, - TokenDeviceGroups, - TokenRestrictedDeviceGroups, - TokenSecurityAttributes, - TokenIsRestricted, - TokenProcessTrustLevel, - TokenPrivateNameSpace, - TokenSingletonAttributes, - TokenBnoIsolation, - TokenChildProcessFlags, - MaxTokenInfoClass - }; -//--- -enum MANDATORY_LEVEL - { - MandatoryLevelUntrusted=0, - MandatoryLevelLow, - MandatoryLevelMedium, - MandatoryLevelHigh, - MandatoryLevelSystem, - MandatoryLevelSecureProcess, - MandatoryLevelCount - }; -//--- -enum SE_IMAGE_SIGNATURE_TYPE - { - SeImageSignatureNone=0, - SeImageSignatureEmbedded, - SeImageSignatureCache, - SeImageSignatureCatalogCached, - SeImageSignatureCatalogNotCached, - SeImageSignatureCatalogHint, - SeImageSignaturePackageCatalog - }; -//--- -enum SE_LEARNING_MODE_DATA_TYPE - { - SeLearningModeInvalidType=0, - SeLearningModeSettings, - SeLearningModeMax - }; -//--- -enum HARDWARE_COUNTER_TYPE - { - PMCCounter, - MaxHardwareCounterType - }; -//--- -enum PROCESS_MITIGATION_POLICY - { - ProcessDEPPolicy, - ProcessASLRPolicy, - ProcessDynamicCodePolicy, - ProcessStrictHandleCheckPolicy, - ProcessSystemCallDisablePolicy, - ProcessMitigationOptionsMask, - ProcessExtensionPointDisablePolicy, - ProcessControlFlowGuardPolicy, - ProcessSignaturePolicy, - ProcessFontDisablePolicy, - ProcessImageLoadPolicy, - ProcessSystemCallFilterPolicy, - ProcessPayloadRestrictionPolicy, - ProcessChildProcessPolicy, - MaxProcessMitigationPolicy - }; -//--- -enum JOBOBJECT_RATE_CONTROL_TOLERANCE - { - ToleranceLow=1, - ToleranceMedium, - ToleranceHigh - }; -//--- -enum JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL - { - ToleranceIntervalShort=1, - ToleranceIntervalMedium, - ToleranceIntervalLong - }; -//--- -enum JOB_OBJECT_NET_RATE_CONTROL_FLAGS - { - JOB_OBJECT_NET_RATE_CONTROL_ENABLE=0x1, - JOB_OBJECT_NET_RATE_CONTROL_MAX_BANDWIDTH=0x2, - JOB_OBJECT_NET_RATE_CONTROL_DSCP_TAG=0x4, - JOB_OBJECT_NET_RATE_CONTROL_VALID_FLAGS=0x7 - }; -//--- -enum JOB_OBJECT_IO_RATE_CONTROL_FLAGS - { - JOB_OBJECT_IO_RATE_CONTROL_ENABLE=0x1, - JOB_OBJECT_IO_RATE_CONTROL_STANDALONE_VOLUME=0x2, - JOB_OBJECT_IO_RATE_CONTROL_FORCE_UNIT_ACCESS_ALL=0x4, - JOB_OBJECT_IO_RATE_CONTROL_FORCE_UNIT_ACCESS_ON_SOFT_CAP=0x8, - JOB_OBJECT_IO_RATE_CONTROL_VALID_FLAGS=JOB_OBJECT_IO_RATE_CONTROL_ENABLE| - JOB_OBJECT_IO_RATE_CONTROL_STANDALONE_VOLUME| - JOB_OBJECT_IO_RATE_CONTROL_FORCE_UNIT_ACCESS_ALL| - JOB_OBJECT_IO_RATE_CONTROL_FORCE_UNIT_ACCESS_ON_SOFT_CAP - }; -//--- -enum JOBOBJECT_IO_ATTRIBUTION_CONTROL_FLAGS - { - JOBOBJECT_IO_ATTRIBUTION_CONTROL_ENABLE=0x1, - JOBOBJECT_IO_ATTRIBUTION_CONTROL_DISABLE=0x2, - JOBOBJECT_IO_ATTRIBUTION_CONTROL_VALID_FLAGS=0x3 - }; -//--- -enum JOBOBJECTINFOCLASS - { - JobObjectBasicAccountingInformation=1, - JobObjectBasicLimitInformation, - JobObjectBasicProcessIdList, - JobObjectBasicUIRestrictions, - JobObjectSecurityLimitInformation, - JobObjectEndOfJobTimeInformation, - JobObjectAssociateCompletionPortInformation, - JobObjectBasicAndIoAccountingInformation, - JobObjectExtendedLimitInformation, - JobObjectJobSetInformation, - JobObjectGroupInformation, - JobObjectNotificationLimitInformation, - JobObjectLimitViolationInformation, - JobObjectGroupInformationEx, - JobObjectCpuRateControlInformation, - JobObjectCompletionFilter, - JobObjectCompletionCounter, - JobObjectReserved1Information=18, - JobObjectReserved2Information, - JobObjectReserved3Information, - JobObjectReserved4Information, - JobObjectReserved5Information, - JobObjectReserved6Information, - JobObjectReserved7Information, - JobObjectReserved8Information, - JobObjectReserved9Information, - JobObjectReserved10Information, - JobObjectReserved11Information, - JobObjectReserved12Information, - JobObjectReserved13Information, - JobObjectReserved14Information=31, - JobObjectNetRateControlInformation, - JobObjectNotificationLimitInformation2, - JobObjectLimitViolationInformation2, - JobObjectCreateSilo, - JobObjectSiloBasicInformation, - JobObjectReserved15Information=37, - JobObjectReserved16Information=38, - JobObjectReserved17Information=39, - JobObjectReserved18Information=40, - JobObjectReserved19Information=41, - JobObjectReserved20Information=42, - JobObjectReserved21Information=43, - JobObjectReserved22Information=44, - JobObjectReserved23Information=45, - JobObjectReserved24Information=46, - JobObjectReserved25Information=47, - MaxJobObjectInfoClass - }; -//--- -enum SERVERSILO_STATE - { - SERVERSILO_INITING=0, - SERVERSILO_STARTED, - SERVERSILO_SHUTTING_DOWN, - SERVERSILO_TERMINATING, - SERVERSILO_TERMINATED - }; -//--- -enum FIRMWARE_TYPE - { - FirmwareTypeUnknown, - FirmwareTypeBios, - FirmwareTypeUefi, - FirmwareTypeMax - }; -//--- -enum LOGICAL_PROCESSOR_RELATIONSHIP - { - RelationProcessorCore, - RelationNumaNode, - RelationCache, - RelationProcessorPackage, - RelationGroup, - RelationAll=0xffff - }; -//--- -enum PROCESSOR_CACHE_TYPE - { - CacheUnified, - CacheInstruction, - CacheData, - CacheTrace - }; -//--- -enum CPU_SET_INFORMATION_TYPE - { - CpuSetInformation - }; -//--- -enum MEM_EXTENDED_PARAMETER_TYPE - { - MemExtendedParameterInvalidType=0, - MemExtendedParameterAddressRequirements, - MemExtendedParameterNumaNode, - MemExtendedParameterPartitionHandle, - MemExtendedParameterMax - }; -//--- -enum SharedVirtualDiskSupportType - { - SharedVirtualDisksUnsupported=0, - SharedVirtualDisksSupported=1, - SharedVirtualDiskSnapshotsSupported=3, - SharedVirtualDiskCDPSnapshotsSupported=7 - }; -//--- -enum SharedVirtualDiskHandleState - { - SharedVirtualDiskHandleStateNone=0, - SharedVirtualDiskHandleStateFileShared=1, - SharedVirtualDiskHandleStateHandleShared=3 - }; -//--- -enum SYSTEM_POWER_STATE - { - PowerSystemUnspecified=0, - PowerSystemWorking=1, - PowerSystemSleeping1=2, - PowerSystemSleeping2=3, - PowerSystemSleeping3=4, - PowerSystemHibernate=5, - PowerSystemShutdown=6, - PowerSystemMaximum=7 - }; -//--- -enum DEVICE_POWER_STATE - { - PowerDeviceUnspecified=0, - PowerDeviceD0, - PowerDeviceD1, - PowerDeviceD2, - PowerDeviceD3, - PowerDeviceMaximum - }; -//--- -enum MONITOR_DISPLAY_STATE - { - PowerMonitorOff=0, - PowerMonitorOn, - PowerMonitorDim - }; -//--- -enum USER_ACTIVITY_PRESENCE - { - PowerUserPresent=0, - PowerUserNotPresent, - PowerUserInactive, - PowerUserMaximum, - PowerUserInvalid=PowerUserMaximum - }; -//--- -enum POWER_REQUEST_TYPE - { - PowerRequestDisplayRequired, - PowerRequestSystemRequired, - PowerRequestAwayModeRequired, - PowerRequestExecutionRequired - }; -//--- -enum POWER_MONITOR_REQUEST_TYPE - { - MonitorRequestTypeOff, - MonitorRequestTypeOnAndPresent, - MonitorRequestTypeToggleOn - }; -//--- -enum POWER_PLATFORM_ROLE - { - PlatformRoleUnspecified=0, - PlatformRoleDesktop, - PlatformRoleMobile, - PlatformRoleWorkstation, - PlatformRoleEnterpriseServer, - PlatformRoleSOHOServer, - PlatformRoleAppliancePC, - PlatformRolePerformanceServer, - PlatformRoleSlate, - PlatformRoleMaximum - }; -//--- -enum HIBERFILE_BUCKET_SIZE - { - HiberFileBucket1GB=0, - HiberFileBucket2GB, - HiberFileBucket4GB, - HiberFileBucket8GB, - HiberFileBucket16GB, - HiberFileBucket32GB, - HiberFileBucketUnlimited, - HiberFileBucketMax - }; -//--- -enum IMAGE_AUX_SYMBOL_TYPE - { - IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF=1 - }; -//--- -enum IMPORT_OBJECT_TYPE - { - IMPORT_OBJECT_CODE=0, - IMPORT_OBJECT_DATA=1, - IMPORT_OBJECT_CONST=2 - }; -//--- -enum IMPORT_OBJECT_NAME_TYPE - { - IMPORT_OBJECT_ORDINAL=0, - IMPORT_OBJECT_NAME=1, - IMPORT_OBJECT_NAME_NO_PREFIX=2, - IMPORT_OBJECT_NAME_UNDECORATE=3, - IMPORT_OBJECT_NAME_EXPORTAS=4 - }; -//--- -enum ReplacesCorHdrNumericDefines - { - COMIMAGE_FLAGS_ILONLY=0x00000001, - COMIMAGE_FLAGS_32BITREQUIRED=0x00000002, - COMIMAGE_FLAGS_IL_LIBRARY=0x00000004, - COMIMAGE_FLAGS_STRONGNAMESIGNED=0x00000008, - COMIMAGE_FLAGS_NATIVE_ENTRYPOINT=0x00000010, - COMIMAGE_FLAGS_TRACKDEBUGDATA=0x00010000, - COMIMAGE_FLAGS_32BITPREFERRED=0x00020000, - COR_VERSION_MAJOR_V2=2, - COR_VERSION_MAJOR=COR_VERSION_MAJOR_V2, - COR_VERSION_MINOR=5, - COR_DELETED_NAME_LENGTH=8, - COR_VTABLEGAP_NAME_LENGTH=8, - NATIVE_TYPE_MAX_CB=1, - COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE=0xFF, - IMAGE_COR_MIH_METHODRVA=0x01, - IMAGE_COR_MIH_EHRVA=0x02, - IMAGE_COR_MIH_BASICBLOCK=0x08, - COR_VTABLE_32BIT=0x01, - COR_VTABLE_64BIT=0x02, - COR_VTABLE_FROM_UNMANAGED=0x04, - COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN=0x08, - COR_VTABLE_CALL_MOST_DERIVED=0x10, - IMAGE_COR_EATJ_THUNK_SIZE=32, - MAX_CLASS_NAME=1024, - MAX_PACKAGE_NAME=1024 - }; -//--- -enum RTL_UMS_THREAD_INFO_CLASS - { - UmsThreadInvalidInfoClass=0, - UmsThreadUserContext, - UmsThreadPriority, - UmsThreadAffinity, - UmsThreadTeb, - UmsThreadIsSuspended, - UmsThreadIsTerminated, - UmsThreadMaxInfoClass - }; -//--- -enum RTL_UMS_SCHEDULER_REASON - { - UmsSchedulerStartup=0, - UmsSchedulerThreadBlocked, - UmsSchedulerThreadYield - }; -//--- -enum OS_DEPLOYEMENT_STATE_VALUES - { - OS_DEPLOYMENT_STANDARD=1, - OS_DEPLOYMENT_COMPACT - }; -//--- -enum IMAGE_POLICY_ENTRY_TYPE - { - ImagePolicyEntryTypeNone=0, - ImagePolicyEntryTypeBool, - ImagePolicyEntryTypeInt8, - ImagePolicyEntryTypeUInt8, - ImagePolicyEntryTypeInt16, - ImagePolicyEntryTypeUInt16, - ImagePolicyEntryTypeInt32, - ImagePolicyEntryTypeUInt32, - ImagePolicyEntryTypeInt64, - ImagePolicyEntryTypeUInt64, - ImagePolicyEntryTypeAnsiString, - ImagePolicyEntryTypeUnicodeString, - ImagePolicyEntryTypeOverride, - ImagePolicyEntryTypeMaximum - }; -//--- -enum IMAGE_POLICY_ID - { - ImagePolicyIdNone=0, - ImagePolicyIdEtw, - ImagePolicyIdDebug, - ImagePolicyIdCrashDump, - ImagePolicyIdCrashDumpKey, - ImagePolicyIdCrashDumpKeyGuid, - ImagePolicyIdParentSd, - ImagePolicyIdParentSdRev, - ImagePolicyIdSvn, - ImagePolicyIdDeviceId, - ImagePolicyIdCapability, - ImagePolicyIdScenarioId, - ImagePolicyIdMaximum - }; -//--- -enum HEAP_INFORMATION_CLASS - { - HeapCompatibilityInformation=0, - HeapEnableTerminationOnCorruption=1, - HeapOptimizeResources=3 - }; -//--- -enum ACTIVATION_CONTEXT_INFO_CLASS - { - ActivationContextBasicInformation=1, - ActivationContextDetailedInformation=2, - AssemblyDetailedInformationInActivationContext=3, - FileInformationInAssemblyOfAssemblyInActivationContext=4, - RunlevelInformationInActivationContext=5, - CompatibilityInformationInActivationContext=6, - ActivationContextManifestResourceName=7, - MaxActivationContextInfoClass, - AssemblyDetailedInformationInActivationContxt=3, - FileInformationInAssemblyOfAssemblyInActivationContxt=4 - }; -//--- -enum SERVICE_NODE_TYPE - { - DriverType=0x00000001, - FileSystemType=0x00000002, - Win32ServiceOwnProcess=0x00000010, - Win32ServiceShareProcess=0x00000020, - AdapterType=0x00000004, - RecognizerType=0x00000008 - }; -//--- -enum SERVICE_LOAD_TYPE - { - BootLoad=0x00000000, - SystemLoad=0x00000001, - AutoLoad=0x00000002, - DemandLoad=0x00000003, - DisableLoad=0x00000004 - }; -//--- -enum SERVICE_ERROR_TYPE - { - IgnoreError=0x00000000, - NormalError=0x00000001, - SevereError=0x00000002, - CriticalError=0x00000003 - }; -//--- -enum TAPE_DRIVE_PROBLEM_TYPE - { - TapeDriveProblemNone, - TapeDriveReadWriteWarning, - TapeDriveReadWriteError, - TapeDriveReadWarning, - TapeDriveWriteWarning, - TapeDriveReadError, - TapeDriveWriteError, - TapeDriveHardwareError, - TapeDriveUnsupportedMedia, - TapeDriveScsiConnectionError, - TapeDriveTimetoClean, - TapeDriveCleanDriveNow, - TapeDriveMediaLifeExpired, - TapeDriveSnappedTape - }; -//--- -enum TRANSACTION_OUTCOME - { - TransactionOutcomeUndetermined=1, - TransactionOutcomeCommitted, - TransactionOutcomeAborted - }; -//--- -enum TRANSACTION_STATE - { - TransactionStateNormal=1, - TransactionStateIndoubt, - TransactionStateCommittedNotify - }; -//--- -enum TRANSACTION_INFORMATION_CLASS - { - TransactionBasicInformation, - TransactionPropertiesInformation, - TransactionEnlistmentInformation, - TransactionSuperiorEnlistmentInformation, - TransactionBindInformation, - TransactionDTCPrivateInformation - }; -//--- -enum TRANSACTIONMANAGER_INFORMATION_CLASS - { - TransactionManagerBasicInformation, - TransactionManagerLogInformation, - TransactionManagerLogPathInformation, - TransactionManagerRecoveryInformation=4, - TransactionManagerOnlineProbeInformation=3, - TransactionManagerOldestTransactionInformation=5 - }; -//--- -enum RESOURCEMANAGER_INFORMATION_CLASS - { - ResourceManagerBasicInformation, - ResourceManagerCompletionInformation - }; -//--- -enum ENLISTMENT_INFORMATION_CLASS - { - EnlistmentBasicInformation, - EnlistmentRecoveryInformation, - EnlistmentCrmInformation - }; -//--- -enum KTMOBJECT_TYPE - { - KTMOBJECT_TRANSACTION, - KTMOBJECT_TRANSACTION_MANAGER, - KTMOBJECT_RESOURCE_MANAGER, - KTMOBJECT_ENLISTMENT, - KTMOBJECT_INVALID - }; -//--- -enum TP_CALLBACK_PRIORITY - { - TP_CALLBACK_PRIORITY_HIGH, - TP_CALLBACK_PRIORITY_NORMAL, - TP_CALLBACK_PRIORITY_LOW, - TP_CALLBACK_PRIORITY_INVALID, - TP_CALLBACK_PRIORITY_COUNT=TP_CALLBACK_PRIORITY_INVALID - }; -//--- -enum POWER_USER_PRESENCE_TYPE - { - UserNotPresent=0, - UserPresent=1, - UserUnknown=0xff - }; -//--- -enum POWER_MONITOR_REQUEST_REASON - { - MonitorRequestReasonUnknown, - MonitorRequestReasonPowerButton, - MonitorRequestReasonRemoteConnection, - MonitorRequestReasonScMonitorpower, - MonitorRequestReasonUserInput, - MonitorRequestReasonAcDcDisplayBurst, - MonitorRequestReasonUserDisplayBurst, - MonitorRequestReasonPoSetSystemState, - MonitorRequestReasonSetThreadExecutionState, - MonitorRequestReasonFullWake, - MonitorRequestReasonSessionUnlock, - MonitorRequestReasonScreenOffRequest, - MonitorRequestReasonIdleTimeout, - MonitorRequestReasonPolicyChange, - MonitorRequestReasonSleepButton, - MonitorRequestReasonLid, - MonitorRequestReasonBatteryCountChange, - MonitorRequestReasonGracePeriod, - MonitorRequestReasonPnP, - MonitorRequestReasonDP, - MonitorRequestReasonSxTransition, - MonitorRequestReasonSystemIdle, - MonitorRequestReasonNearProximity, - MonitorRequestReasonThermalStandby, - MonitorRequestReasonResumePdc, - MonitorRequestReasonResumeS4, - MonitorRequestReasonTerminal, - MonitorRequestReasonPdcSignal, - MonitorRequestReasonAcDcDisplayBurstSuppressed, - MonitorRequestReasonSystemStateEntered, - MonitorRequestReasonWinrt, - MonitorRequestReasonUserInputKeyboard, - MonitorRequestReasonUserInputMouse, - MonitorRequestReasonUserInputTouch, - MonitorRequestReasonUserInputPen, - MonitorRequestReasonUserInputAccelerometer, - MonitorRequestReasonUserInputHid, - MonitorRequestReasonUserInputPoUserPresent, - MonitorRequestReasonUserInputSessionSwitch, - MonitorRequestReasonUserInputInitialization, - MonitorRequestReasonPdcSignalWindowsMobilePwrNotif, - MonitorRequestReasonPdcSignalWindowsMobileShell, - MonitorRequestReasonPdcSignalHeyCortana, - MonitorRequestReasonPdcSignalHolographicShell, - MonitorRequestReasonPdcSignalFingerprint, - MonitorRequestReasonMax - }; -//--- -enum POWER_ACTION - { - PowerActionNone=0, - PowerActionReserved, - PowerActionSleep, - PowerActionHibernate, - PowerActionShutdown, - PowerActionShutdownReset, - PowerActionShutdownOff, - PowerActionWarmEject, - PowerActionDisplayOff - }; -//--- -enum ACTCTX_REQUESTED_RUN_LEVEL - { - ACTCTX_RUN_LEVEL_UNSPECIFIED=0, - ACTCTX_RUN_LEVEL_AS_INVOKER, - ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE, - ACTCTX_RUN_LEVEL_REQUIRE_ADMIN, - ACTCTX_RUN_LEVEL_NUMBERS - }; -//--- -enum ACTCTX_COMPATIBILITY_ELEMENT_TYPE - { - ACTCTX_COMPATIBILITY_ELEMENT_TYPE_UNKNOWN=0, - ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS, - ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MITIGATION - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -//--- -struct PROCESSOR_NUMBER - { - ushort Group; - uchar Number; - uchar Reserved; - }; -//--- -struct GROUP_AFFINITY - { - ulong Mask; - ushort Group; - ushort Reserved[3]; - }; -//--- -struct FLOAT128 - { - long LowPart; - long HighPart; - }; -//--- -struct LARGE_INTEGER - { - long QuadPart; - }; -//--- -struct ULARGE_INTEGER - { - ulong QuadPart; - }; -//--- -struct LUID - { - uint LowPart; - int HighPart; - }; -//--- -struct LIST_ENTRY - { - PVOID Flink; - PVOID Blink; - }; -//--- -struct SINGLE_LIST_ENTRY - { - PVOID Next; - }; -//--- -struct LIST_ENTRY32 - { - uint Flink; - uint Blink; - }; -//--- -struct LIST_ENTRY64 - { - ulong Flink; - ulong Blink; - }; -//--- -struct OBJECTID - { - GUID Lineage; - uint Uniquifier; - }; -//--- -struct M128A - { - ulong Low; - long High; - }; -//--- -struct XSAVE_FORMAT - { - ushort Controlushort; - ushort Statusushort; - uchar Tagushort; - uchar Reserved1; - ushort ErrorOpcode; - uint ErrorOffset; - ushort ErrorSelector; - ushort Reserved2; - uint DataOffset; - ushort DataSelector; - ushort Reserved3; - uint MxCsr; - uint MxCsr_Mask; - M128A FloatRegisters[8]; - M128A XmmRegisters[16]; - uchar Reserved4[96]; - }; -//--- -struct XSAVE_AREA_HEADER - { - ulong Mask; - ulong CompactionMask; - ulong Reserved2[6]; - }; -//--- -struct XSAVE_AREA - { - XSAVE_FORMAT LegacyState; - XSAVE_AREA_HEADER Header; - }; -//--- -struct XSTATE_CONTEXT - { - ulong Mask; - uint Length; - uint Reserved1; - PVOID Area; - uint Reserved2; - PVOID Buffer; - uint Reserved3; - }; -//--- -struct SCOPE_TABLE_AMD64 - { - uint Count; - uint BeginAddress; - uint EndAddress; - uint HandlerAddress; - uint JumpTarget; - }; -//--- -struct UNWIND_HISTORY_TABLE_ENTRY - { - ulong ImageBase; - PVOID FunctionEntry; - }; -//--- -struct UNWIND_HISTORY_TABLE - { - uint Count; - uchar LocalHint; - uchar GlobalHint; - uchar Search; - uchar Once; - ulong LowAddress; - ulong HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; - }; -//--- -struct SCOPE_TABLE_ARM64 - { - uint Count; - uint BeginAddress; - uint EndAddress; - uint HandlerAddress; - uint JumpTarget; - }; -//--- -struct NEON128 - { - ulong Low; - long High; - }; -//--- -struct DISPATCHER_CONTEXT - { - uint ControlPc; - uint ImageBase; - PVOID FunctionEntry; - uint EstablisherFrame; - uint TargetPc; - PVOID ContextRecord; - PVOID LanguageHandler; - PVOID HandlerData; - PVOID HistoryTable; - uint ScopeIndex; - uchar ControlPcIsUnwound; - PVOID NonVolatileRegisters; - uint Reserved; - }; -//--- -struct KNONVOLATILE_CONTEXT_POINTERS - { - PVOID FloatingContext[16]; - PVOID IntegerContext[16]; - }; -//--- -struct SCOPE_TABLE_ARM - { - uint Count; - uint BeginAddress; - uint EndAddress; - uint HandlerAddress; - uint JumpTarget; - }; -//--- -struct DISPATCHER_CONTEXT_ARM64 - { - ulong ControlPc; - ulong ImageBase; - PVOID FunctionEntry; - ulong EstablisherFrame; - ulong TargetPc; - PVOID ContextRecord; - PVOID LanguageHandler; - PVOID HandlerData; - PVOID HistoryTable; - uint ScopeIndex; - uchar ControlPcIsUnwound; - PVOID NonVolatileRegisters; - }; -//--- -struct KNONVOLATILE_CONTEXT_POINTERS_ARM64 - { - PVOID X19; - PVOID X20; - PVOID X21; - PVOID X22; - PVOID X23; - PVOID X24; - PVOID X25; - PVOID X26; - PVOID X27; - PVOID X28; - PVOID Fp; - PVOID Lr; - PVOID D8; - PVOID D9; - PVOID D10; - PVOID D11; - PVOID D12; - PVOID D13; - PVOID D14; - PVOID D15; - }; -//--- -struct FLOATING_SAVE_AREA - { - uint Controlushort; - uint Statusushort; - uint Tagushort; - uint ErrorOffset; - uint ErrorSelector; - uint DataOffset; - uint DataSelector; - uchar RegisterArea[SIZE_OF_80387_REGISTERS]; - uint Spare0; - }; -//--- -struct CONTEXT - { - ulong P1Home; - ulong P2Home; - ulong P3Home; - ulong P4Home; - ulong P5Home; - ulong P6Home; - uint ContextFlags; - uint MxCsr; - ushort SegCs; - ushort SegDs; - ushort SegEs; - ushort SegFs; - ushort SegGs; - ushort SegSs; - uint EFlags; - ulong Dr0; - ulong Dr1; - ulong Dr2; - ulong Dr3; - ulong Dr6; - ulong Dr7; - ulong Rax; - ulong Rcx; - ulong Rdx; - ulong Rbx; - ulong Rsp; - ulong Rbp; - ulong Rsi; - ulong Rdi; - ulong R8; - ulong R9; - ulong R10; - ulong R11; - ulong R12; - ulong R13; - ulong R14; - ulong R15; - ulong Rip; - M128A Header[2]; - M128A Legacy[8]; - M128A Xmm0; - M128A Xmm1; - M128A Xmm2; - M128A Xmm3; - M128A Xmm4; - M128A Xmm5; - M128A Xmm6; - M128A Xmm7; - M128A Xmm8; - M128A Xmm9; - M128A Xmm10; - M128A Xmm11; - M128A Xmm12; - M128A Xmm13; - M128A Xmm14; - M128A Xmm15; - M128A VectorRegister[26]; - ulong VectorControl; - ulong DebugControl; - ulong LastBranchToRip; - ulong LastBranchFromRip; - ulong LastExceptionToRip; - ulong LastExceptionFromRip; - }; -//--- -struct WOW64_FLOATING_SAVE_AREA - { - uint Controlushort; - uint Statusushort; - uint Tagushort; - uint ErrorOffset; - uint ErrorSelector; - uint DataOffset; - uint DataSelector; - uchar RegisterArea[WOW64_SIZE_OF_80387_REGISTERS]; - uint Cr0NpxState; - }; -//--- -struct WOW64_CONTEXT - { - uint ContextFlags; - uint Dr0; - uint Dr1; - uint Dr2; - uint Dr3; - uint Dr6; - uint Dr7; - WOW64_FLOATING_SAVE_AREA FloatSave; - uint SegGs; - uint SegFs; - uint SegEs; - uint SegDs; - uint Edi; - uint Esi; - uint Ebx; - uint Edx; - uint Ecx; - uint Eax; - uint Ebp; - uint Eip; - uint SegCs; - uint EFlags; - uint Esp; - uint SegSs; - uchar ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION]; - }; -//--- -struct WOW64_LDT_ENTRY - { - uint LimitLow; - uint BaseLow; - uchar BaseMid; - uchar Flags1; - uchar Flags2; - uchar BaseHi; - }; -//--- -struct WOW64_DESCRIPTOR_TABLE_ENTRY - { - uint Selector; - WOW64_LDT_ENTRY Descriptor; - }; -//--- -struct EXCEPTION_RECORD - { - uint ExceptionCode; - uint ExceptionFlags; - PVOID ExceptionRecord; - PVOID ExceptionAddress; - uint NumberParameters; - PVOID ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; - }; -//--- -struct EXCEPTION_RECORD32 - { - uint ExceptionCode; - uint ExceptionFlags; - uint ExceptionRecord; - uint ExceptionAddress; - uint NumberParameters; - uint ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; - }; -//--- -struct EXCEPTION_RECORD64 - { - uint ExceptionCode; - uint ExceptionFlags; - ulong ExceptionRecord; - ulong ExceptionAddress; - uint NumberParameters; - uint __unusedAlignment; - ulong ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; - }; -//--- -struct EXCEPTION_POINTERS - { - PVOID ExceptionRecord; - PVOID ContextRecord; - }; -//--- -struct GENERIC_MAPPING - { - uint GenericRead; - uint GenericWrite; - uint GenericExecute; - uint GenericAll; - }; -//--- -struct LUID_AND_ATTRIBUTES - { - LUID Luid; - uint Attributes; - }; -//--- -struct SID_IDENTIFIER_AUTHORITY - { - uchar Value[6]; - }; -//--- -//--- -struct SID - { - uchar Revision; - uchar SubAuthorityCount; - SID_IDENTIFIER_AUTHORITY IdentifierAuthority; - uint SubAuthority[ANYSIZE_ARRAY]; - }; -//--- -struct SID_AND_ATTRIBUTES - { - SID Sid; - uint Attributes; - }; -//--- -struct SID_AND_ATTRIBUTES_HASH - { - uint SidCount; - PVOID SidAttr; - ulong Hash[SID_HASH_SIZE]; - }; -//--- -struct ACL - { - uchar AclRevision; - uchar Sbz1; - ushort AclSize; - ushort AceCount; - ushort Sbz2; - }; -//--- -struct ACE_HEADER - { - uchar AceType; - uchar AceFlags; - ushort AceSize; - }; -//--- -struct ACCESS_ALLOWED_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct ACCESS_DENIED_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_AUDIT_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_ALARM_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_RESOURCE_ATTRIBUTE_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_SCOPED_POLICY_ID_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_MANDATORY_LABEL_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_PROCESS_TRUST_LABEL_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_ACCESS_FILTER_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct ACCESS_ALLOWED_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct ACCESS_DENIED_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct SYSTEM_AUDIT_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct SYSTEM_ALARM_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct ACCESS_ALLOWED_CALLBACK_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct ACCESS_DENIED_CALLBACK_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_AUDIT_CALLBACK_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct SYSTEM_ALARM_CALLBACK_ACE - { - ACE_HEADER Header; - uint Mask; - uint SidStart; - }; -//--- -struct ACCESS_ALLOWED_CALLBACK_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct ACCESS_DENIED_CALLBACK_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct SYSTEM_AUDIT_CALLBACK_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct SYSTEM_ALARM_CALLBACK_OBJECT_ACE - { - ACE_HEADER Header; - uint Mask; - uint Flags; - GUID ObjectType; - GUID InheritedObjectType; - uint SidStart; - }; -//--- -struct ACL_REVISION_INFORMATION - { - uint AclRevision; - }; -//--- -struct ACL_SIZE_INFORMATION - { - uint AceCount; - uint AclBytesInUse; - uint AclBytesFree; - }; -//--- -struct SECURITY_DESCRIPTOR_RELATIVE - { - uchar Revision; - uchar Sbz1; - ushort Control; - uint Owner; - uint Group; - uint Sacl; - uint Dacl; - }; -//--- -struct SECURITY_DESCRIPTOR - { - uchar Revision; - uchar Sbz1; - ushort Control; - uchar offset[4]; - PVOID Owner; - PVOID Group; - PVOID Sacl; - PVOID Dacl; - }; -//--- -struct SECURITY_OBJECT_AI_PARAMS - { - uint Size; - uint ConstraintMask; - }; -//--- -struct OBJECT_TYPE_LIST - { - ushort Level; - ushort Sbz; - GUID ObjectType; - }; -//--- -struct PRIVILEGE_SET - { - uint PrivilegeCount; - uint Control; - LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY]; - }; -//--- -struct ACCESS_REASONS - { - uint Data[32]; - }; -//--- -struct SE_SECURITY_DESCRIPTOR - { - uint Size; - uint Flags; - PVOID SecurityDescriptor; - }; -//--- -struct SE_ACCESS_REQUEST - { - uint Size; - PVOID SeSecurityDescriptor; - uint DesiredAccess; - uint PreviouslyGrantedAccess; - PVOID PrincipalSelfSid; - PVOID GenericMapping; - uint ObjectTypeListCount; - PVOID ObjectTypeList; - }; -//--- -struct SE_ACCESS_REPLY - { - uint Size; - uint ResultListCount; - PVOID GrantedAccess; - uint AccessStatus; - PVOID AccessReason; - PVOID Privileges; - }; -//--- -struct TOKEN_USER - { - SID_AND_ATTRIBUTES User; - }; -//--- -struct SE_TOKEN_USER - { - TOKEN_USER TokenUser; - SID Sid; - }; -//--- -struct TOKEN_GROUPS - { - uint GroupCount; - SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; - }; -//--- -struct TOKEN_PRIVILEGES - { - uint PrivilegeCount; - LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; - }; -//--- -struct TOKEN_OWNER - { - PVOID Owner; - }; -//--- -struct TOKEN_PRIMARY_GROUP - { - PVOID PrimaryGroup; - }; -//--- -struct TOKEN_DEFAULT_DACL - { - PVOID DefaultDacl; - }; -//--- -struct TOKEN_USER_CLAIMS - { - PVOID UserClaims; - }; -//--- -struct TOKEN_DEVICE_CLAIMS - { - PVOID DeviceClaims; - }; -//--- -struct TOKEN_GROUPS_AND_PRIVILEGES - { - uint SidCount; - uint SidLength; - PVOID Sids; - uint RestrictedSidCount; - uint RestrictedSidLength; - PVOID RestrictedSids; - uint PrivilegeCount; - uint PrivilegeLength; - PVOID Privileges; - LUID AuthenticationId; - }; -//--- -struct TOKEN_LINKED_TOKEN - { - HANDLE LinkedToken; - }; -//--- -struct TOKEN_ELEVATION - { - uint TokenIsElevated; - }; -//--- -struct TOKEN_MANDATORY_LABEL - { - SID_AND_ATTRIBUTES Label; - }; -//--- -struct TOKEN_MANDATORY_POLICY - { - uint Policy; - }; -//--- -struct TOKEN_ACCESS_INFORMATION - { - PVOID SidHash; - PVOID RestrictedSidHash; - PVOID Privileges; - LUID AuthenticationId; - TOKEN_TYPE TokenType; - SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; - TOKEN_MANDATORY_POLICY MandatoryPolicy; - uint Flags; - uint AppContainerNumber; - PVOID PackageSid; - PVOID CapabilitiesHash; - PVOID TrustLevelSid; - PVOID SecurityAttributes; - }; -//--- -struct TOKEN_AUDIT_POLICY - { - uchar PerUserPolicy[((POLICY_AUDIT_SUBCATEGORY_COUNT)>>1)+1]; - }; -//--- -struct TOKEN_SOURCE - { - char SourceName[TOKEN_SOURCE_LENGTH]; - LUID SourceIdentifier; - }; -//--- -struct TOKEN_STATISTICS - { - LUID TokenId; - LUID AuthenticationId; - long ExpirationTime; - TOKEN_TYPE TokenType; - SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; - uint DynamicCharged; - uint DynamicAvailable; - uint GroupCount; - uint PrivilegeCount; - LUID ModifiedId; - }; -//--- -struct TOKEN_CONTROL - { - LUID TokenId; - LUID AuthenticationId; - LUID ModifiedId; - TOKEN_SOURCE TokenSource; - }; -//--- -struct TOKEN_ORIGIN - { - LUID OriginatingLogonSession; - }; -//--- -struct TOKEN_APPCONTAINER_INFORMATION - { - PVOID TokenAppContainer; - }; -//--- -struct TOKEN_SID_INFORMATION - { - PVOID Sid; - }; -//--- -struct TOKEN_BNO_ISOLATION_INFORMATION - { - string IsolationPrefix; - uchar IsolationEnabled; - }; -//--- -struct CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE - { - ulong Version; - string Name; - }; -//--- -struct CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE - { - PVOID pValue; - uint ValueLength; - }; -//--- -struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 - { - uint Name; - ushort ValueType; - ushort Reserved; - uint Flags; - uint ValueCount; - uint pInt64[ANYSIZE_ARRAY]; - }; -//--- -struct Attribute - { - ushort Version; - ushort Reserved; - uint AttributeCount; - PVOID pAttributeV1; - }; -//--- -struct SECURITY_QUALITY_OF_SERVICE - { - uint Length; - SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; - uchar ContextTrackingMode; - uchar EffectiveOnly; - }; -//--- -struct SE_IMPERSONATION_STATE - { - PVOID Token; - uchar CopyOnOpen; - uchar EffectiveOnly; - SECURITY_IMPERSONATION_LEVEL Level; - }; -//--- -struct SECURITY_CAPABILITIES - { - PVOID AppContainerSid; - PVOID Capabilities; - uint CapabilityCount; - uint Reserved; - }; -//--- -struct JOB_SET_ARRAY - { - HANDLE JobHandle; - uint MemberLevel; - uint Flags; - }; -//--- -struct EXCEPTION_REGISTRATION_RECORD - { - PVOID Next; - PVOID Handler; - }; -//--- -struct NT_TIB - { - PVOID ExceptionList; - PVOID StackBase; - PVOID StackLimit; - PVOID SubSystemTib; - PVOID FiberData; - PVOID ArbitraryUserPointer; - PVOID Self; - }; -//--- -struct UMS_CREATE_THREAD_ATTRIBUTES - { - uint UmsVersion; - PVOID UmsContext; - PVOID UmsCompletionList; - }; -//--- -struct WOW64_ARCHITECTURE_INFORMATION - { - uint Info; - }; -//--- -struct QUOTA_LIMITS - { - ulong PagedPoolLimit; - ulong NonPagedPoolLimit; - ulong MinimumWorkingSetSize; - ulong MaximumWorkingSetSize; - ulong PagefileLimit; - long TimeLimit; - }; -//--- -struct QUOTA_LIMITS_EX - { - ulong PagedPoolLimit; - ulong NonPagedPoolLimit; - ulong MinimumWorkingSetSize; - ulong MaximumWorkingSetSize; - ulong PagefileLimit; - long TimeLimit; - ulong WorkingSetLimit; - ulong Reserved2; - ulong Reserved3; - ulong Reserved4; - uint Flags; - uint CpuRateLimit; - }; -//--- -struct IO_COUNTERS - { - ulong ReadOperationCount; - ulong WriteOperationCount; - ulong OtherOperationCount; - ulong ReadTransferCount; - ulong WriteTransferCount; - ulong OtherTransferCount; - }; -//--- -struct JOBOBJECT_BASIC_ACCOUNTING_INFORMATION - { - long TotalUserTime; - long TotalKernelTime; - long ThisPeriodTotalUserTime; - long ThisPeriodTotalKernelTime; - uint TotalPageFaultCount; - uint TotalProcesses; - uint ActiveProcesses; - uint TotalTerminatedProcesses; - }; -//--- -struct JOBOBJECT_BASIC_LIMIT_INFORMATION - { - long PerProcessUserTimeLimit; - long PerJobUserTimeLimit; - uint LimitFlags; - ulong MinimumWorkingSetSize; - ulong MaximumWorkingSetSize; - uint ActiveProcessLimit; - ulong Affinity; - uint PriorityClass; - uint SchedulingClass; - }; -//--- -struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION - { - JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; - IO_COUNTERS IoInfo; - ulong ProcessMemoryLimit; - ulong JobMemoryLimit; - ulong PeakProcessMemoryUsed; - ulong PeakJobMemoryUsed; - }; -//--- -struct JOBOBJECT_BASIC_PROCESS_ID_LIST - { - uint NumberOfAssignedProcesses; - uint NumberOfProcessIdsInList; - ulong ProcessIdList[1]; - }; -//--- -struct JOBOBJECT_BASIC_UI_RESTRICTIONS - { - uint UIRestrictionsClass; - }; -//--- -struct JOBOBJECT_SECURITY_LIMIT_INFORMATION - { - uint SecurityLimitFlags; - HANDLE JobToken; - PVOID SidsToDisable; - PVOID PrivilegesToDelete; - PVOID RestrictedSids; - }; -//--- -struct JOBOBJECT_END_OF_JOB_TIME_INFORMATION - { - uint EndOfJobTimeAction; - }; -//--- -struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT - { - PVOID CompletionKey; - HANDLE CompletionPort; - }; -//--- -struct JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION - { - JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicInfo; - IO_COUNTERS IoInfo; - }; -//--- -struct JOBOBJECT_JOBSET_INFORMATION - { - uint MemberLevel; - }; -//--- -struct JOBOBJECT_NOTIFICATION_LIMIT_INFORMATION - { - ulong IoReadBytesLimit; - ulong IoWriteBytesLimit; - long PerJobUserTimeLimit; - ulong JobMemoryLimit; - JOBOBJECT_RATE_CONTROL_TOLERANCE RateControlTolerance; - JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL RateControlToleranceInterval; - uint LimitFlags; - }; -//--- -struct JOBOBJECT_LIMIT_VIOLATION_INFORMATION - { - uint LimitFlags; - uint ViolationLimitFlags; - ulong IoReadBytes; - ulong IoReadBytesLimit; - ulong IoWriteBytes; - ulong IoWriteBytesLimit; - long PerJobUserTime; - long PerJobUserTimeLimit; - ulong JobMemory; - ulong JobMemoryLimit; - JOBOBJECT_RATE_CONTROL_TOLERANCE RateControlTolerance; - JOBOBJECT_RATE_CONTROL_TOLERANCE RateControlToleranceLimit; - }; -//--- -struct JOBOBJECT_NET_RATE_CONTROL_INFORMATION - { - ulong MaxBandwidth; - JOB_OBJECT_NET_RATE_CONTROL_FLAGS ControlFlags; - uchar DscpTag; - }; -//--- -struct JOBOBJECT_IO_RATE_CONTROL_INFORMATION_NATIVE - { - long MaxIops; - long MaxBandwidth; - long ReservationIops; - string VolumeName; - uint BaseIoSize; - JOB_OBJECT_IO_RATE_CONTROL_FLAGS ControlFlags; - ushort VolumeNameLength; - }; -//--- -struct JOBOBJECT_IO_RATE_CONTROL_INFORMATION_NATIVE_V2 - { - long MaxIops; - long MaxBandwidth; - long ReservationIops; - string VolumeName; - uint BaseIoSize; - JOB_OBJECT_IO_RATE_CONTROL_FLAGS ControlFlags; - ushort VolumeNameLength; - long CriticalReservationIops; - long ReservationBandwidth; - long CriticalReservationBandwidth; - long MaxTimePercent; - long ReservationTimePercent; - long CriticalReservationTimePercent; - }; -//--- -struct JOBOBJECT_IO_RATE_CONTROL_INFORMATION_NATIVE_V3 - { - long MaxIops; - long MaxBandwidth; - long ReservationIops; - string VolumeName; - uint BaseIoSize; - JOB_OBJECT_IO_RATE_CONTROL_FLAGS ControlFlags; - ushort VolumeNameLength; - long CriticalReservationIops; - long ReservationBandwidth; - long CriticalReservationBandwidth; - long MaxTimePercent; - long ReservationTimePercent; - long CriticalReservationTimePercent; - long SoftMaxIops; - long SoftMaxBandwidth; - long SoftMaxTimePercent; - long LimitExcessNotifyIops; - long LimitExcessNotifyBandwidth; - long LimitExcessNotifyTimePercent; - }; -//--- -struct JOBOBJECT_IO_ATTRIBUTION_STATS - { - ulong IoCount; - ulong TotalNonOverlappedQueueTime; - ulong TotalNonOverlappedServiceTime; - ulong TotalSize; - }; -//--- -struct JOBOBJECT_IO_ATTRIBUTION_INFORMATION - { - uint ControlFlags; - JOBOBJECT_IO_ATTRIBUTION_STATS ReadStats; - JOBOBJECT_IO_ATTRIBUTION_STATS WriteStats; - }; -//--- -struct SILOOBJECT_BASIC_INFORMATION - { - uint SiloId; - uint SiloParentId; - uint NumberOfProcesses; - uchar IsInServerSilo; - uchar Reserved[3]; - }; -//--- -struct SERVERSILO_BASIC_INFORMATION - { - uint ServiceSessionId; - SERVERSILO_STATE State; - uint ExitStatus; - }; -//--- -struct CACHE_DESCRIPTOR - { - uchar Level; - uchar Associativity; - ushort LineSize; - uint Size; - PROCESSOR_CACHE_TYPE Type; - }; -//--- -struct ProcessorCore - { - ulong ProcessorMask; - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - uchar Flags; - }; -//--- -struct PROCESSOR_RELATIONSHIP - { - uchar Flags; - uchar EfficiencyClass; - uchar Reserved[20]; - ushort GroupCount; - GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; - }; -//--- -struct NUMA_NODE_RELATIONSHIP - { - uint NodeNumber; - uchar Reserved[20]; - GROUP_AFFINITY GroupMask; - }; -//--- -struct CACHE_RELATIONSHIP - { - uchar Level; - uchar Associativity; - ushort LineSize; - uint CacheSize; - PROCESSOR_CACHE_TYPE Type; - uchar Reserved[20]; - GROUP_AFFINITY GroupMask; - }; -//--- -struct PROCESSOR_GROUP_INFO - { - uchar MaximumProcessorCount; - uchar ActiveProcessorCount; - uchar Reserved[38]; - ulong ActiveProcessorMask; - }; -//--- -struct GROUP_RELATIONSHIP - { - ushort MaximumGroupCount; - ushort ActiveGroupCount; - uchar Reserved[20]; - PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; - }; -//--- -struct SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION - { - ulong CycleTime; - }; -//--- -struct XSTATE_FEATURE - { - uint Offset; - uint Size; - }; -//--- -struct XSTATE_CONFIGURATION - { - ulong EnabledFeatures; - ulong EnabledVolatileFeatures; - uint Size; - uint ControlFlags; - XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; - ulong EnabledSupervisorFeatures; - ulong AlignedFeatures; - uint AllFeatureSize; - uint AllFeatures[MAXIMUM_XSTATE_FEATURES]; - }; -//--- -struct MEMORY_BASIC_INFORMATION - { - PVOID BaseAddress; - PVOID AllocationBase; - uint AllocationProtect; - ulong RegionSize; - uint State; - uint Protect; - uint Type; - }; -//--- -struct MEMORY_BASIC_INFORMATION32 - { - uint BaseAddress; - uint AllocationBase; - uint AllocationProtect; - uint RegionSize; - uint State; - uint Protect; - uint Type; - }; -//--- -struct MEMORY_BASIC_INFORMATION64 - { - ulong BaseAddress; - ulong AllocationBase; - uint AllocationProtect; - uint __alignment1; - ulong RegionSize; - uint State; - uint Protect; - uint Type; - uint __alignment2; - }; -//--- -struct CFG_CALL_TARGET_INFO - { - ulong Offset; - ulong Flags; - }; -//--- -struct MEM_ADDRESS_REQUIREMENTS - { - PVOID LowestStartingAddress; - PVOID HighestEndingAddress; - ulong Alignment; - }; -//--- -struct ENCLAVE_CREATE_INFO_SGX - { - uchar Secs[4096]; - }; -//--- -struct ENCLAVE_INIT_INFO_SGX - { - uchar SigStruct[1808]; - uchar Reserved1[240]; - uchar EInitToken[304]; - uchar Reserved2[1744]; - }; -//--- -struct ENCLAVE_CREATE_INFO_VBS - { - uint Flags; - uchar OwnerID[32]; - }; -//--- -struct ENCLAVE_INIT_INFO_VBS - { - uint Length; - uint ThreadCount; - }; -//--- -struct FILE_ID_128 - { - uchar Identifier[16]; - }; -//--- -struct FILE_NOTIFY_INFORMATION - { - uint NextEntryOffset; - uint Action; - uint FileNameLength; - short FileName[1]; - }; -//--- -struct FILE_NOTIFY_EXTENDED_INFORMATION - { - uint NextEntryOffset; - uint Action; - long CreationTime; - long LastModificationTime; - long LastChangeTime; - long LastAccessTime; - long AllocatedLength; - long FileSize; - uint FileAttributes; - uint ReparsePointTag; - long FileId; - long ParentFileId; - uint FileNameLength; - short FileName[1]; - }; -//--- -struct GenericReparseBuffer - { - uint ReparseTag; - ushort ReparseDataLength; - ushort Reserved; - GUID ReparseGuid; - uchar DataBuffer[1]; - }; -//--- -struct SCRUB_DATA_INPUT - { - uint Size; - uint Flags; - uint MaximumIos; - uint ObjectId[4]; - uint Reserved[13]; - uchar ResumeContext[816]; - }; -//--- -struct SCRUB_PARITY_EXTENT - { - long Offset; - ulong Length; - }; -//--- -struct SCRUB_PARITY_EXTENT_DATA - { - ushort Size; - ushort Flags; - ushort NumberOfParityExtents; - ushort MaximumNumberOfParityExtents; - SCRUB_PARITY_EXTENT ParityExtents[ANYSIZE_ARRAY]; - }; -//--- -struct SCRUB_DATA_OUTPUT - { - uint Size; - uint Flags; - uint Status; - ulong ErrorFileOffset; - ulong ErrorLength; - ulong NumberOfBytesRepaired; - ulong NumberOfBytesFailed; - ulong InternalFileReference; - ushort ResumeContextLength; - ushort ParityExtentDataOffset; - uint Reserved[5]; - uchar ResumeContext[816]; - }; -//--- -struct SHARED_VIRTUAL_DISK_SUPPORT - { - SharedVirtualDiskSupportType SharedVirtualDiskSupport; - SharedVirtualDiskHandleState HandleState; - }; -//--- -struct NETWORK_APP_INSTANCE_EA - { - GUID AppInstanceID; - uint CsvFlags; - }; -//--- -struct CM_POWER_DATA - { - uint PD_Size; - DEVICE_POWER_STATE PD_MostRecentPowerState; - uint PD_Capabilities; - uint PD_D1Latency; - uint PD_D2Latency; - uint PD_D3Latency; - DEVICE_POWER_STATE PD_PowerStateMapping[POWER_SYSTEM_MAXIMUM]; - SYSTEM_POWER_STATE PD_DeepestSystemWake; - }; -//--- -struct POWER_USER_PRESENCE - { - POWER_USER_PRESENCE_TYPE UserPresence; - }; -//--- -struct POWER_SESSION_CONNECT - { - uchar Connected; - uchar Console; - }; -//--- -struct POWER_SESSION_TIMEOUTS - { - uint InputTimeout; - uint DisplayTimeout; - }; -//--- -struct POWER_SESSION_RIT_STATE - { - uchar Active; - uint LastInputTime; - }; -//--- -struct POWER_SESSION_WINLOGON - { - uint SessionId; - uchar Console; - uchar Locked; - }; -//--- -struct POWER_IDLE_RESILIENCY - { - uint CoalescingTimeout; - uint IdleResiliencyPeriod; - }; -//--- -struct POWER_MONITOR_INVOCATION - { - uchar Console; - POWER_MONITOR_REQUEST_REASON RequestReason; - }; -//--- -struct RESUME_PERFORMANCE - { - uint PostTimeMs; - ulong TotalResumeTimeMs; - ulong ResumeCompleteTimestamp; - }; -//--- -struct APPLICATIONLAUNCH_SETTING_VALUE - { - long ActivationTime; - uint Flags; - uint ButtonInstanceID; - }; -//--- -struct POWER_PLATFORM_INFORMATION - { - uchar AoAc; - }; -//--- -struct POWER_ACTION_POLICY - { - POWER_ACTION Action; - uint Flags; - uint EventCode; - }; -//--- -struct SYSTEM_POWER_LEVEL - { - uchar Enable; - uchar Spare[3]; - uint BatteryLevel; - POWER_ACTION_POLICY PowerPolicy; - SYSTEM_POWER_STATE MinSystemState; - }; -//--- -struct SYSTEM_POWER_POLICY - { - uint Revision; - POWER_ACTION_POLICY PowerButton; - POWER_ACTION_POLICY SleepButton; - POWER_ACTION_POLICY LidClose; - SYSTEM_POWER_STATE LidOpenWake; - uint Reserved; - POWER_ACTION_POLICY Idle; - uint IdleTimeout; - uchar IdleSensitivity; - uchar DynamicThrottle; - uchar Spare2[2]; - SYSTEM_POWER_STATE MinSleep; - SYSTEM_POWER_STATE MaxSleep; - SYSTEM_POWER_STATE ReducedLatencySleep; - uint WinLogonFlags; - uint Spare3; - uint DozeS4Timeout; - uint BroadcastCapacityResolution; - SYSTEM_POWER_LEVEL DischargePolicy[NUM_DISCHARGE_POLICIES]; - uint VideoTimeout; - uchar VideoDimDisplay; - uint VideoReserved[3]; - uint SpindownTimeout; - uchar OptimizeForPower; - uchar FanThrottleTolerance; - uchar ForcedThrottle; - uchar MinThrottle; - POWER_ACTION_POLICY OverThrottled; - }; -//--- -struct PROCESSOR_POWER_POLICY_INFO - { - uint TimeCheck; - uint DemoteLimit; - uint PromoteLimit; - uchar DemotePercent; - uchar PromotePercent; - uchar Spare[2]; - uint Flags; - }; -//--- -struct PROCESSOR_POWER_POLICY - { - uint Revision; - uchar DynamicThrottle; - uchar Spare[3]; - uint Flags; - uint PolicyCount; - PROCESSOR_POWER_POLICY_INFO Policy[3]; - }; -//--- -struct ADMINISTRATOR_POWER_POLICY - { - SYSTEM_POWER_STATE MinSleep; - SYSTEM_POWER_STATE MaxSleep; - uint MinVideoTimeout; - uint MaxVideoTimeout; - uint MinSpindownTimeout; - uint MaxSpindownTimeout; - }; -//--- -struct HIBERFILE_BUCKET - { - ulong MaxPhysicalMemory; - uint PhysicalMemoryPercent[HIBERFILE_TYPE_MAX]; - }; -//--- -struct IMAGE_DOS_HEADER - { - ushort e_magic; - ushort e_cblp; - ushort e_cp; - ushort e_crlc; - ushort e_cparhdr; - ushort e_minalloc; - ushort e_maxalloc; - ushort e_ss; - ushort e_sp; - ushort e_csum; - ushort e_ip; - ushort e_cs; - ushort e_lfarlc; - ushort e_ovno; - ushort e_res[4]; - ushort e_oemid; - ushort e_oeminfo; - ushort e_res2[10]; - int e_lfanew; - }; -//--- -struct IMAGE_OS2_HEADER - { - ushort ne_magic; - char ne_ver; - char ne_rev; - ushort ne_enttab; - ushort ne_cbenttab; - int ne_crc; - ushort ne_flags; - ushort ne_autodata; - ushort ne_heap; - ushort ne_stack; - int ne_csip; - int ne_sssp; - ushort ne_cseg; - ushort ne_cmod; - ushort ne_cbnrestab; - ushort ne_segtab; - ushort ne_rsrctab; - ushort ne_restab; - ushort ne_modtab; - ushort ne_imptab; - int ne_nrestab; - ushort ne_cmovent; - ushort ne_align; - ushort ne_cres; - uchar ne_exetyp; - uchar ne_flagsothers; - ushort ne_pretthunks; - ushort ne_psegrefbytes; - ushort ne_swaparea; - ushort ne_expver; - }; -//--- -struct IMAGE_VXD_HEADER - { - ushort e32_magic; - uchar e32_border; - uchar e32_ushorter; - uint e32_level; - ushort e32_cpu; - ushort e32_os; - uint e32_ver; - uint e32_mflags; - uint e32_mpages; - uint e32_startobj; - uint e32_eip; - uint e32_stackobj; - uint e32_esp; - uint e32_pagesize; - uint e32_lastpagesize; - uint e32_fixupsize; - uint e32_fixupsum; - uint e32_ldrsize; - uint e32_ldrsum; - uint e32_objtab; - uint e32_objcnt; - uint e32_objmap; - uint e32_itermap; - uint e32_rsrctab; - uint e32_rsrccnt; - uint e32_restab; - uint e32_enttab; - uint e32_dirtab; - uint e32_dircnt; - uint e32_fpagetab; - uint e32_frectab; - uint e32_impmod; - uint e32_impmodcnt; - uint e32_impproc; - uint e32_pagesum; - uint e32_datapage; - uint e32_preload; - uint e32_nrestab; - uint e32_cbnrestab; - uint e32_nressum; - uint e32_autodata; - uint e32_debuginfo; - uint e32_debuglen; - uint e32_instpreload; - uint e32_instdemand; - uint e32_heapsize; - uchar e32_res3[12]; - uint e32_winresoff; - uint e32_winreslen; - ushort e32_devid; - ushort e32_ddkver; - }; -//--- -struct IMAGE_FILE_HEADER - { - ushort Machine; - ushort NumberOfSections; - uint TimeDateStamp; - uint PointerToSymbolTable; - uint NumberOfSymbols; - ushort SizeOfOptionalHeader; - ushort Characteristics; - }; -//--- -struct IMAGE_DATA_DIRECTORY - { - uint VirtualAddress; - uint Size; - }; -//--- -struct IMAGE_OPTIONAL_HEADER32 - { - ushort Magic; - uchar MajorLinkerVersion; - uchar MinorLinkerVersion; - uint SizeOfCode; - uint SizeOfInitializedData; - uint SizeOfUninitializedData; - uint AddressOfEntryPoint; - uint BaseOfCode; - uint BaseOfData; - uint ImageBase; - uint SectionAlignment; - uint FileAlignment; - ushort MajorOperatingSystemVersion; - ushort MinorOperatingSystemVersion; - ushort MajorImageVersion; - ushort MinorImageVersion; - ushort MajorSubsystemVersion; - ushort MinorSubsystemVersion; - uint Win32VersionValue; - uint SizeOfImage; - uint SizeOfHeaders; - uint CheckSum; - ushort Subsystem; - ushort DllCharacteristics; - uint SizeOfStackReserve; - uint SizeOfStackCommit; - uint SizeOfHeapReserve; - uint SizeOfHeapCommit; - uint LoaderFlags; - uint NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - }; -//--- -struct IMAGE_ROM_OPTIONAL_HEADER - { - ushort Magic; - uchar MajorLinkerVersion; - uchar MinorLinkerVersion; - uint SizeOfCode; - uint SizeOfInitializedData; - uint SizeOfUninitializedData; - uint AddressOfEntryPoint; - uint BaseOfCode; - uint BaseOfData; - uint BaseOfBss; - uint GprMask; - uint CprMask[4]; - uint GpValue; - }; -//--- -struct IMAGE_OPTIONAL_HEADER64 - { - ushort Magic; - uchar MajorLinkerVersion; - uchar MinorLinkerVersion; - uint SizeOfCode; - uint SizeOfInitializedData; - uint SizeOfUninitializedData; - uint AddressOfEntryPoint; - uint BaseOfCode; - ulong ImageBase; - uint SectionAlignment; - uint FileAlignment; - ushort MajorOperatingSystemVersion; - ushort MinorOperatingSystemVersion; - ushort MajorImageVersion; - ushort MinorImageVersion; - ushort MajorSubsystemVersion; - ushort MinorSubsystemVersion; - uint Win32VersionValue; - uint SizeOfImage; - uint SizeOfHeaders; - uint CheckSum; - ushort Subsystem; - ushort DllCharacteristics; - ulong SizeOfStackReserve; - ulong SizeOfStackCommit; - ulong SizeOfHeapReserve; - ulong SizeOfHeapCommit; - uint LoaderFlags; - uint NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - }; -//--- -struct IMAGE_NT_HEADERS64 - { - uint Signature; - IMAGE_FILE_HEADER FileHeader; - IMAGE_OPTIONAL_HEADER64 OptionalHeader; - }; -//--- -struct IMAGE_NT_HEADERS32 - { - uint Signature; - IMAGE_FILE_HEADER FileHeader; - IMAGE_OPTIONAL_HEADER32 OptionalHeader; - }; -//--- -struct IMAGE_ROM_HEADERS - { - IMAGE_FILE_HEADER FileHeader; - IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; - }; -//--- -struct ANON_OBJECT_HEADER - { - ushort Sig1; - ushort Sig2; - ushort Version; - ushort Machine; - uint TimeDateStamp; - GUID ClassID; - uint SizeOfData; - }; -//--- -struct ANON_OBJECT_HEADER_V2 - { - ushort Sig1; - ushort Sig2; - ushort Version; - ushort Machine; - uint TimeDateStamp; - GUID ClassID; - uint SizeOfData; - uint Flags; - uint MetaDataSize; - uint MetaDataOffset; - }; -//--- -struct ANON_OBJECT_HEADER_BIGOBJ - { - ushort Sig1; - ushort Sig2; - ushort Version; - ushort Machine; - uint TimeDateStamp; - GUID ClassID; - uint SizeOfData; - uint Flags; - uint MetaDataSize; - uint MetaDataOffset; - uint NumberOfSections; - uint PointerToSymbolTable; - uint NumberOfSymbols; - }; -//--- -struct IMAGE_SECTION_HEADER - { - uchar Name[IMAGE_SIZEOF_SHORT_NAME]; - uint PhysicalAddress; - uint VirtualAddress; - uint SizeOfRawData; - uint PointerToRawData; - uint PointerToRelocations; - uint PointerToLinenumbers; - ushort NumberOfRelocations; - ushort NumberOfLinenumbers; - uint Characteristics; - }; -//--- -struct IMAGE_SYMBOL - { - uchar ShortName[8]; - uint Value; - short SectionNumber; - ushort Type; - uchar StorageClass; - uchar NumberOfAuxSymbols; - }; -//--- -struct IMAGE_SYMBOL_EX - { - uchar ShortName[8]; - uint Value; - int SectionNumber; - ushort Type; - uchar StorageClass; - uchar NumberOfAuxSymbols; - }; -//--- -struct IMAGE_AUX_SYMBOL_TOKEN_DEF - { - uchar bAuxType; - uchar bReserved; - uint SymbolTableIndex; - uchar rgbReserved[12]; - }; -//--- -struct IMAGE_LINENUMBER - { - uint VirtualAddress; - ushort Linenumber; - }; -//--- -struct IMAGE_BASE_RELOCATION - { - uint VirtualAddress; - uint SizeOfBlock; - }; -//--- -struct IMAGE_ARCHIVE_MEMBER_HEADER - { - uchar Name[16]; - uchar Date[12]; - uchar UserID[6]; - uchar GroupID[6]; - uchar Mode[8]; - uchar Size[10]; - uchar EndHeader[2]; - }; -//--- -struct IMAGE_EXPORT_DIRECTORY - { - uint Characteristics; - uint TimeDateStamp; - ushort MajorVersion; - ushort MinorVersion; - uint Name; - uint Base; - uint NumberOfFunctions; - uint NumberOfNames; - uint AddressOfFunctions; - uint AddressOfNames; - uint AddressOfNameOrdinals; - }; -//--- -struct IMAGE_IMPORT_BY_NAME - { - ushort Hint; - char Name[1]; - }; -//--- -struct IMAGE_THUNK_DATA64 - { - ulong Data; - }; -//--- -struct IMAGE_THUNK_DATA32 - { - uint Data; - }; -//--- -struct IMAGE_BOUND_IMPORT_DESCRIPTOR - { - uint TimeDateStamp; - ushort OffsetModuleName; - ushort NumberOfModuleForwarderRefs; - }; -//--- -struct IMAGE_BOUND_FORWARDER_REF - { - uint TimeDateStamp; - ushort OffsetModuleName; - ushort Reserved; - }; -//--- -struct IMAGE_RESOURCE_DIRECTORY - { - uint Characteristics; - uint TimeDateStamp; - ushort MajorVersion; - ushort MinorVersion; - ushort NumberOfNamedEntries; - ushort NumberOfIdEntries; - }; -//--- -struct IMAGE_RESOURCE_DIRECTORY_STRING - { - ushort Length; - char NameString[1]; - }; -//--- -struct IMAGE_RESOURCE_DIR_STRING_U - { - ushort Length; - short NameString[1]; - }; -//--- -struct IMAGE_RESOURCE_DATA_ENTRY - { - uint OffsetToData; - uint Size; - uint CodePage; - uint Reserved; - }; -//--- -struct IMAGE_LOAD_CONFIG_CODE_INTEGRITY - { - ushort Flags; - ushort Catalog; - uint CatalogOffset; - uint Reserved; - }; -//--- -struct IMAGE_DYNAMIC_RELOCATION_TABLE - { - uint Version; - uint Size; - }; -//--- -struct IMAGE_DYNAMIC_RELOCATION32 - { - uint Symbol; - uint BaseRelocSize; - }; -//--- -struct IMAGE_DYNAMIC_RELOCATION64 - { - ulong Symbol; - uint BaseRelocSize; - }; -//--- -struct IMAGE_DYNAMIC_RELOCATION32_V2 - { - uint HeaderSize; - uint FixupInfoSize; - uint Symbol; - uint SymbolGroup; - uint Flags; - }; -//--- -struct IMAGE_DYNAMIC_RELOCATION64_V2 - { - uint HeaderSize; - uint FixupInfoSize; - ulong Symbol; - uint SymbolGroup; - uint Flags; - }; -//--- -struct IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER - { - uchar PrologueByteCount; - }; -//--- -struct IMAGE_EPILOGUE_DYNAMIC_RELOCATION_HEADER - { - uint EpilogueCount; - uchar EpilogueByteCount; - uchar BranchDescriptorElementSize; - ushort BranchDescriptorCount; - }; -//--- -struct IMAGE_LOAD_CONFIG_DIRECTORY32 - { - uint Size; - uint TimeDateStamp; - ushort MajorVersion; - ushort MinorVersion; - uint GlobalFlagsClear; - uint GlobalFlagsSet; - uint CriticalSectionDefaultTimeout; - uint DeCommitFreeBlockThreshold; - uint DeCommitTotalFreeThreshold; - uint LockPrefixTable; - uint MaximumAllocationSize; - uint VirtualMemoryThreshold; - uint ProcessHeapFlags; - uint ProcessAffinityMask; - ushort CSDVersion; - ushort DependentLoadFlags; - uint EditList; - uint SecurityCookie; - uint SEHandlerTable; - uint SEHandlerCount; - uint GuardCFCheckFunctionPointer; - uint GuardCFDispatchFunctionPointer; - uint GuardCFFunctionTable; - uint GuardCFFunctionCount; - uint GuardFlags; - IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; - uint GuardAddressTakenIatEntryTable; - uint GuardAddressTakenIatEntryCount; - uint GuardLongJumpTargetTable; - uint GuardLongJumpTargetCount; - uint DynamicValueRelocTable; - uint CHPEMetadataPointer; - uint GuardRFFailureRoutine; - uint GuardRFFailureRoutineFunctionPointer; - uint DynamicValueRelocTableOffset; - ushort DynamicValueRelocTableSection; - ushort Reserved2; - uint GuardRFVerifyStackPointerFunctionPointer; - uint HotPatchTableOffset; - uint Reserved3; - uint EnclaveConfigurationPointer; - }; -//--- -struct IMAGE_LOAD_CONFIG_DIRECTORY64 - { - uint Size; - uint TimeDateStamp; - ushort MajorVersion; - ushort MinorVersion; - uint GlobalFlagsClear; - uint GlobalFlagsSet; - uint CriticalSectionDefaultTimeout; - ulong DeCommitFreeBlockThreshold; - ulong DeCommitTotalFreeThreshold; - ulong LockPrefixTable; - ulong MaximumAllocationSize; - ulong VirtualMemoryThreshold; - ulong ProcessAffinityMask; - uint ProcessHeapFlags; - ushort CSDVersion; - ushort DependentLoadFlags; - ulong EditList; - ulong SecurityCookie; - ulong SEHandlerTable; - ulong SEHandlerCount; - ulong GuardCFCheckFunctionPointer; - ulong GuardCFDispatchFunctionPointer; - ulong GuardCFFunctionTable; - ulong GuardCFFunctionCount; - uint GuardFlags; - IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; - ulong GuardAddressTakenIatEntryTable; - ulong GuardAddressTakenIatEntryCount; - ulong GuardLongJumpTargetTable; - ulong GuardLongJumpTargetCount; - ulong DynamicValueRelocTable; - ulong CHPEMetadataPointer; - ulong GuardRFFailureRoutine; - ulong GuardRFFailureRoutineFunctionPointer; - uint DynamicValueRelocTableOffset; - ushort DynamicValueRelocTableSection; - ushort Reserved2; - ulong GuardRFVerifyStackPointerFunctionPointer; - uint HotPatchTableOffset; - uint Reserved3; - ulong EnclaveConfigurationPointer; - }; -//--- -struct IMAGE_HOT_PATCH_INFO - { - uint Version; - uint Size; - uint SequenceNumber; - uint BaseImageList; - uint BaseImageCount; - uint BufferOffset; - }; -//--- -struct IMAGE_HOT_PATCH_BASE - { - uint SequenceNumber; - uint Flags; - uint OriginalTimeDateStamp; - uint OriginalCheckSum; - uint CodeIntegrityInfo; - uint CodeIntegritySize; - uint PatchTable; - uint BufferOffset; - }; -//--- -struct IMAGE_HOT_PATCH_HASHES - { - uchar SHA256[32]; - uchar SHA1[20]; - }; -//--- -struct IMAGE_CE_RUNTIME_FUNCTION_ENTRY - { - uint FuncStart; - uint Flags; - }; -//--- -struct IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY - { - ulong BeginAddress; - ulong EndAddress; - ulong ExceptionHandler; - ulong HandlerData; - ulong PrologEndAddress; - }; -//--- -struct IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY - { - uint BeginAddress; - uint EndAddress; - uint ExceptionHandler; - uint HandlerData; - uint PrologEndAddress; - }; -//--- -struct IMAGE_ENCLAVE_CONFIG32 - { - uint Size; - uint MinimumRequiredConfigSize; - uint PolicyFlags; - uint NumberOfImports; - uint ImportList; - uint ImportEntrySize; - uchar FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uchar ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uint ImageVersion; - uint SecurityVersion; - uint EnclaveSize; - uint NumberOfThreads; - uint EnclaveFlags; - }; -//--- -struct IMAGE_ENCLAVE_CONFIG64 - { - uint Size; - uint MinimumRequiredConfigSize; - uint PolicyFlags; - uint NumberOfImports; - uint ImportList; - uint ImportEntrySize; - uchar FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uchar ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uint ImageVersion; - uint SecurityVersion; - ulong EnclaveSize; - uint NumberOfThreads; - uint EnclaveFlags; - }; -//--- -struct IMAGE_ENCLAVE_IMPORT - { - uint MatchType; - uint MinimumSecurityVersion; - uchar UniqueOrAuthorID[IMAGE_ENCLAVE_LONG_ID_LENGTH]; - uchar FamilyID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uchar ImageID[IMAGE_ENCLAVE_SHORT_ID_LENGTH]; - uint ImportName; - uint Reserved; - }; -//--- -struct IMAGE_DEBUG_DIRECTORY - { - uint Characteristics; - uint TimeDateStamp; - ushort MajorVersion; - ushort MinorVersion; - uint Type; - uint SizeOfData; - uint AddressOfRawData; - uint PointerToRawData; - }; -//--- -struct IMAGE_COFF_SYMBOLS_HEADER - { - uint NumberOfSymbols; - uint LvaToFirstSymbol; - uint NumberOfLinenumbers; - uint LvaToFirstLinenumber; - uint RvaToFirstByteOfCode; - uint RvaToLastByteOfCode; - uint RvaToFirstByteOfData; - uint RvaToLastByteOfData; - }; -//--- -struct FPO_DATA - { - uint ulOffStart; - uint cbProcSize; - uint cdwLocals; - ushort cdwParams; - ushort data; - }; -//--- -struct IMAGE_DEBUG_MISC - { - uint DataType; - uint Length; - uchar Unicode; - uchar Reserved[3]; - uchar Data[1]; - }; -//--- -struct IMAGE_FUNCTION_ENTRY - { - uint StartingAddress; - uint EndingAddress; - uint EndOfPrologue; - }; -//--- -struct IMAGE_SEPARATE_DEBUG_HEADER - { - ushort Signature; - ushort Flags; - ushort Machine; - ushort Characteristics; - uint TimeDateStamp; - uint CheckSum; - uint ImageBase; - uint SizeOfImage; - uint NumberOfSections; - uint ExportedNamesSize; - uint DebugDirectorySize; - uint SectionAlignment; - uint Reserved[2]; - }; -//--- -struct NON_PAGED_DEBUG_INFO - { - ushort Signature; - ushort Flags; - uint Size; - ushort Machine; - ushort Characteristics; - uint TimeDateStamp; - uint CheckSum; - uint SizeOfImage; - ulong ImageBase; - }; -//--- -struct IMAGE_ARCHITECTURE_HEADER - { - int mask; - uint FirstEntryRVA; - }; -//--- -struct IMAGE_ARCHITECTURE_ENTRY - { - uint FixupInstRVA; - uint NewInst; - }; -//--- -struct SLIST_ENTRY - { - PVOID Next; - }; -//--- -struct RTL_BARRIER - { - uint Reserved1; - uint Reserved2; - ulong Reserved3[2]; - uint Reserved4; - uint Reserved5; - }; -//--- -struct MESSAGE_RESOURCE_ENTRY - { - ushort Length; - ushort Flags; - uchar Text[1]; - }; -//--- -struct MESSAGE_RESOURCE_BLOCK - { - uint LowId; - uint HighId; - uint OffsetToEntries; - }; -//--- -struct MESSAGE_RESOURCE_DATA - { - uint NumberOfBlocks; - MESSAGE_RESOURCE_BLOCK Blocks[1]; - }; -//--- -struct OSVERSIONINFOW - { - uint dwOSVersionInfoSize; - uint dwMajorVersion; - uint dwMinorVersion; - uint dwBuildNumber; - uint dwPlatformId; - ushort szCSDVersion[128]; - }; -//--- -struct OSVERSIONINFOEXW - { - uint dwOSVersionInfoSize; - uint dwMajorVersion; - uint dwMinorVersion; - uint dwBuildNumber; - uint dwPlatformId; - short szCSDVersion[128]; - ushort wServicePackMajor; - ushort wServicePackMinor; - ushort wSuiteMask; - uchar wProductType; - uchar wReserved; - }; -//--- -struct NV_MEMORY_RANGE - { - PVOID BaseAddress; - ulong Length; - }; -//--- -struct CORRELATION_VECTOR - { - char Version; - char Vector[RTL_CORRELATION_VECTOR_STRING_LENGTH]; - }; -//--- -struct CUSTOM_SYSTEM_EVENT_TRIGGER_CONFIG - { - uint Size; - const string TriggerId; - }; -//--- -struct IMAGE_POLICY_ENTRY - { - IMAGE_POLICY_ENTRY_TYPE Type; - IMAGE_POLICY_ID PolicyId; - PVOID Value; - }; -//--- -struct IMAGE_POLICY_METADATA - { - uchar Version; - uchar Reserved0[7]; - ulong ApplicationId; - IMAGE_POLICY_ENTRY Policies[]; - }; -//--- -struct RTL_CRITICAL_SECTION_DEBUG - { - ushort Type; - ushort CreatorBackTraceIndex; - PVOID CriticalSection; - LIST_ENTRY ProcessLocksList; - uint EntryCount; - uint ContentionCount; - uint Flags; - ushort CreatorBackTraceIndexHigh; - ushort Spareushort; - }; -//--- -struct RTL_CRITICAL_SECTION - { - PVOID DebugInfo; - int LockCount; - int RecursionCount; - HANDLE OwningThread; - HANDLE LockSemaphore; - ulong SpinCount; - }; -//--- -struct RTL_SRWLOCK - { - PVOID Ptr; - }; -//--- -struct RTL_CONDITION_VARIABLE - { - PVOID Ptr; - }; -//--- -struct HEAP_OPTIMIZE_RESOURCES_INFORMATION - { - uint Version; - uint Flags; - }; -//--- -struct ACTIVATION_CONTEXT_QUERY_INDEX - { - uint ulAssemblyIndex; - uint ulFileIndexInAssembly; - }; -//--- -struct ASSEMBLY_FILE_DETAILED_INFORMATION - { - uint ulFlags; - uint ulFilenameLength; - uint ulPathLength; - const string lpFileName; - const string lpFilePath; - }; -//--- -struct ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION - { - uint ulFlags; - uint ulEncodedAssemblyIdentityLength; - uint ulManifestPathType; - uint ulManifestPathLength; - long liManifestLastWriteTime; - uint ulPolicyPathType; - uint ulPolicyPathLength; - long liPolicyLastWriteTime; - uint ulMetadataSatelliteRosterIndex; - uint ulManifestVersionMajor; - uint ulManifestVersionMinor; - uint ulPolicyVersionMajor; - uint ulPolicyVersionMinor; - uint ulAssemblyDirectoryNameLength; - const string lpAssemblyEncodedAssemblyIdentity; - const string lpAssemblyManifestPath; - const string lpAssemblyPolicyPath; - const string lpAssemblyDirectoryName; - uint ulFileCount; - }; -//--- -struct ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION - { - uint ulFlags; - ACTCTX_REQUESTED_RUN_LEVEL RunLevel; - uint UiAccess; - }; -//--- -struct COMPATIBILITY_CONTEXT_ELEMENT - { - GUID Id; - ACTCTX_COMPATIBILITY_ELEMENT_TYPE Type; - }; -//--- -struct ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION - { - uint ElementCount; - COMPATIBILITY_CONTEXT_ELEMENT Elements[]; - }; -//--- -struct SUPPORTED_OS_INFO - { - ushort MajorVersion; - ushort MinorVersion; - }; -//--- -struct ACTIVATION_CONTEXT_DETAILED_INFORMATION - { - uint dwFlags; - uint ulFormatVersion; - uint ulAssemblyCount; - uint ulRootManifestPathType; - uint ulRootManifestPathChars; - uint ulRootConfigurationPathType; - uint ulRootConfigurationPathChars; - uint ulAppDirPathType; - uint ulAppDirPathChars; - const string lpRootManifestPath; - const string lpRootConfigurationPath; - const string lpAppDirPath; - }; -//--- -struct HARDWARE_COUNTER_DATA - { - HARDWARE_COUNTER_TYPE Type; - uint Reserved; - ulong Value; - }; -//--- -struct PERFORMANCE_DATA - { - ushort Size; - uchar Version; - uchar HwCountersCount; - uint ContextSwitchCount; - ulong WaitReasonBitMap; - ulong CycleTime; - uint RetryCount; - uint Reserved; - HARDWARE_COUNTER_DATA HwCounters[MAX_HW_COUNTERS]; - }; -//--- -struct EVENTLOGRECORD - { - uint Length; - uint Reserved; - uint RecordNumber; - uint TimeGenerated; - uint TimeWritten; - uint EventID; - ushort EventType; - ushort NumStrings; - ushort EventCategory; - ushort ReservedFlags; - uint ClosingRecordNumber; - uint StringOffset; - uint UserSidLength; - uint UserSidOffset; - uint DataLength; - uint DataOffset; - }; -//--- -struct TAPE_ERASE - { - uint Type; - uchar Immediate; - }; -//--- -struct TAPE_PREPARE - { - uint Operation; - uchar Immediate; - }; -//--- -struct TAPE_WRITE_MARKS - { - uint Type; - uint Count; - uchar Immediate; - }; -//--- -struct TAPE_GET_POSITION - { - uint Type; - uint Partition; - long Offset; - }; -//--- -struct TAPE_SET_POSITION - { - uint Method; - uint Partition; - long Offset; - uchar Immediate; - }; -//--- -struct TAPE_GET_DRIVE_PARAMETERS - { - uchar ECC; - uchar Compression; - uchar DataPadding; - uchar ReportSetmarks; - uint DefaultBlockSize; - uint MaximumBlockSize; - uint MinimumBlockSize; - uint MaximumPartitionCount; - uint FeaturesLow; - uint FeaturesHigh; - uint EOTWarningZoneSize; - }; -//--- -struct TAPE_SET_DRIVE_PARAMETERS - { - uchar ECC; - uchar Compression; - uchar DataPadding; - uchar ReportSetmarks; - uint EOTWarningZoneSize; - }; -//--- -struct TAPE_GET_MEDIA_PARAMETERS - { - long Capacity; - long Remaining; - uint BlockSize; - uint PartitionCount; - uchar WriteProtected; - }; -//--- -struct TAPE_SET_MEDIA_PARAMETERS - { - uint BlockSize; - }; -//--- -struct TAPE_CREATE_PARTITION - { - uint Method; - uint Count; - uint Size; - }; -//--- -struct TAPE_WMI_OPERATIONS - { - uint Method; - uint DataBufferSize; - PVOID DataBuffer; - }; -//--- -struct TRANSACTION_BASIC_INFORMATION - { - GUID TransactionId; - uint State; - uint Outcome; - }; -//--- -struct TRANSACTIONMANAGER_BASIC_INFORMATION - { - GUID TmIdentity; - long VirtualClock; - }; -//--- -struct TRANSACTIONMANAGER_LOG_INFORMATION - { - GUID LogIdentity; - }; -//--- -struct TRANSACTIONMANAGER_LOGPATH_INFORMATION - { - uint LogPathLength; - short LogPath[1]; - }; -//--- -struct TRANSACTIONMANAGER_RECOVERY_INFORMATION - { - ulong LastRecoveredLsn; - }; -//--- -struct TRANSACTIONMANAGER_OLDEST_INFORMATION - { - GUID OldestTransactionGuid; - }; -//--- -struct TRANSACTION_PROPERTIES_INFORMATION - { - uint IsolationLevel; - uint IsolationFlags; - long Timeout; - uint Outcome; - uint DescriptionLength; - short Description[1]; - }; -//--- -struct TRANSACTION_BIND_INFORMATION - { - HANDLE TmHandle; - }; -//--- -struct TRANSACTION_ENLISTMENT_PAIR - { - GUID EnlistmentId; - GUID ResourceManagerId; - }; -//--- -struct TRANSACTION_ENLISTMENTS_INFORMATION - { - uint NumberOfEnlistments; - TRANSACTION_ENLISTMENT_PAIR EnlistmentPair[1]; - }; -//--- -struct TRANSACTION_SUPERIOR_ENLISTMENT_INFORMATION - { - TRANSACTION_ENLISTMENT_PAIR SuperiorEnlistmentPair; - }; -//--- -struct RESOURCEMANAGER_BASIC_INFORMATION - { - GUID ResourceManagerId; - uint DescriptionLength; - short Description[1]; - }; -//--- -struct RESOURCEMANAGER_COMPLETION_INFORMATION - { - HANDLE IoCompletionPortHandle; - ulong CompletionKey; - }; -//--- -struct ENLISTMENT_BASIC_INFORMATION - { - GUID EnlistmentId; - GUID TransactionId; - GUID ResourceManagerId; - }; -//--- -struct ENLISTMENT_CRM_INFORMATION - { - GUID CrmTransactionManagerId; - GUID CrmResourceManagerId; - GUID CrmEnlistmentId; - }; -//--- -struct TRANSACTION_LIST_ENTRY - { - GUID UOW; - }; -//--- -struct TRANSACTION_LIST_INFORMATION - { - uint NumberOfTransactions; - TRANSACTION_LIST_ENTRY TransactionInformation[1]; - }; -//--- -struct KTMOBJECT_CURSOR - { - GUID LastQuery; - uint ObjectIdCount; - GUID ObjectIds[1]; - }; -//--- -struct TP_POOL_STACK_INFORMATION - { - ulong StackReserve; - ulong StackCommit; - }; -//--- -struct TP_CALLBACK_ENVIRON_V3 - { - uint Version; - PVOID Pool; - PVOID CleanupGroup; - PVOID CleanupGroupCancelCallback; - PVOID RaceDll; - PVOID ActivationContext; - PVOID FinalizationCallback; - uint Flags; - TP_CALLBACK_PRIORITY CallbackPriority; - uint Size; - }; -//--- -struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION - { - ulong ProcessorMask; - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - uchar offset[4]; - ulong Reserved[2]; - }; -//--- -struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX - { - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - uint Size; - uchar info[72]; - }; -//--- -struct SYSTEM_CPU_SET_INFORMATION - { - uint Size; - CPU_SET_INFORMATION_TYPE Type; - uint Id; - ushort Group; - uchar LogicalProcessorIndex; - uchar CoreIndex; - uchar LastLevelCacheIndex; - uchar NumaNodeIndex; - uchar EfficiencyClass; - uchar AllFlags; - uint Reserved; - ulong AllocationTag; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "kernel32.dll" -ushort RtlCaptureStackBackTrace(uint frames_to_skip,uint frames_to_capture,PVOID &back_trace[],uint &back_trace_hash); -ulong RtlCompareMemory(const uchar &source1[],const uchar &source2[],ulong length); -ulong VerSetConditionMask(ulong condition_mask,uint type_mask,uchar condition); -#import - -#import "Win32k.sys" -void RtlCaptureContext(PVOID context_record); -void RtlUnwind(PVOID target_frame,PVOID target_ip,EXCEPTION_RECORD &exception_record,PVOID return_value); -PVOID RtlLookupFunctionEntry(ulong control_pc,PVOID image_base,UNWIND_HISTORY_TABLE &history_table); -void RtlUnwindEx(PVOID target_frame,PVOID target_ip,EXCEPTION_RECORD &exception_record,PVOID return_value,PVOID context_record,UNWIND_HISTORY_TABLE &history_table); -PVOID RtlVirtualUnwind(uint handler_type,ulong image_base,ulong control_pc,PVOID function_entry,PVOID context_record,PVOID &handler_data,PVOID establisher_frame,KNONVOLATILE_CONTEXT_POINTERS &context_pointers); -PVOID RtlLookupFunctionEntry(ulong control_pc,uint &image_base,UNWIND_HISTORY_TABLE &history_table); -void RtlUnwindEx(PVOID target_frame,PVOID target_ip,EXCEPTION_RECORD &exception_record,PVOID return_value,PVOID context_record,UNWIND_HISTORY_TABLE &history_table); -PVOID RtlVirtualUnwind(uint handler_type,uint image_base,uint control_pc,PVOID function_entry,PVOID context_record,PVOID &handler_data,uint &establisher_frame,KNONVOLATILE_CONTEXT_POINTERS &context_pointers); -PVOID RtlLookupFunctionEntry(ulong control_pc,PVOID image_base,UNWIND_HISTORY_TABLE &history_table); -void RtlUnwindEx(PVOID target_frame,PVOID target_ip,EXCEPTION_RECORD &exception_record,PVOID return_value,PVOID context_record,UNWIND_HISTORY_TABLE &history_table); -PVOID RtlVirtualUnwind(uint handler_type,ulong image_base,ulong control_pc,PVOID function_entry,PVOID context_record,PVOID &handler_data,PVOID establisher_frame,KNONVOLATILE_CONTEXT_POINTERS &context_pointers); -void RtlUnwindEx(PVOID target_frame,PVOID target_ip,EXCEPTION_RECORD &exception_record,PVOID return_value,PVOID context_record,PVOID history_table); -PVOID RtlPcToFileHeader(PVOID pc_value,PVOID &base_of_image); -#import -//+------------------------------------------------------------------+ diff --git a/Include/WinAPI/winreg.mqh b/Include/WinAPI/winreg.mqh deleted file mode 100644 index 0e8b820..0000000 --- a/Include/WinAPI/winreg.mqh +++ /dev/null @@ -1,77 +0,0 @@ -//+------------------------------------------------------------------+ -//| winreg.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//--- -struct VALENTW - { - PVOID ve_valuename; - uint ve_valuelen; - uchar offset1[4]; - PVOID ve_valueptr; - uint ve_type; - uchar offset2[4]; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "advapi32.dll" -int AbortSystemShutdownW(string machine_name); -uint CheckForHiberboot(uchar &hiberboot,uchar clear_flag); -uint InitiateShutdownW(string machine_name,string message,uint grace_period,uint shutdown_flags,uint reason); -int InitiateSystemShutdownExW(string machine_name,string message,uint timeout,int force_apps_closed,int reboot_after_shutdown,uint reason); -int InitiateSystemShutdownW(string machine_name,string message,uint timeout,int force_apps_closed,int reboot_after_shutdown); -int RegCloseKey(HANDLE key); -int RegConnectRegistryExW(const string machine_name,HANDLE key,uint Flags,HANDLE &result); -int RegConnectRegistryW(const string machine_name,HANDLE key,HANDLE &result); -int RegCopyTreeW(HANDLE key_src,const string sub_key,HANDLE key_dest); -int RegCreateKeyExW(HANDLE key,const string sub_key,PVOID reserved,string class_name,uint options,uint desired,PVOID security_attributes,HANDLE &result,uint &disposition); -int RegCreateKeyTransactedW(HANDLE key,const string sub_key,PVOID reserved,string class_name,uint options,uint desired,PVOID security_attributes,HANDLE &result,uint &disposition,HANDLE transaction,PVOID extended_parameter); -int RegCreateKeyW(HANDLE key,const string sub_key,HANDLE &result); -int RegDeleteKeyExW(HANDLE key,const string sub_key,uint desired,PVOID reserved); -int RegDeleteKeyTransactedW(HANDLE key,const string sub_key,uint desired,PVOID reserved,HANDLE transaction,PVOID extended_parameter); -int RegDeleteKeyValueW(HANDLE key,const string sub_key,const string value_name); -int RegDeleteKeyW(HANDLE key,const string sub_key); -int RegDeleteTreeW(HANDLE key,const string sub_key); -int RegDeleteValueW(HANDLE key,const string value_name); -int RegDisablePredefinedCache(void); -int RegDisablePredefinedCacheEx(void); -int RegDisableReflectionKey(HANDLE base); -int RegEnableReflectionKey(HANDLE base); -int RegEnumKeyExW(HANDLE key,uint index,ushort &name[],uint &name_size,PVOID reserved,ushort &class_name[],uint &class_size,FILETIME &last_write_time); -int RegEnumKeyW(HANDLE key,uint index,ushort &name[],uint &name_size); -int RegEnumValueW(HANDLE key,uint index,ushort &value_name[],uint &value_name_size,PVOID reserved,uint &type,uchar &data[],uint &data_size); -int RegFlushKey(HANDLE key); -int RegGetKeySecurity(HANDLE key,uint SecurityInformation,SECURITY_DESCRIPTOR &security_descriptor,uint &security_descriptor_size); -int RegGetValueW(HANDLE key,const string sub_key,const string value,uint flags,uint &type,uchar &data[],uint &data_size); -int RegLoadAppKeyW(const string file,HANDLE &result,uint desired,uint options,PVOID reserved); -int RegLoadKeyW(HANDLE key,const string sub_key,const string file); -int RegLoadMUIStringW(HANDLE key,const string value,ushort &out_buf[],uint &out_buf_size,uint &data,uint flags,const string directory); -int RegNotifyChangeKeyValue(HANDLE key,int watch_subtree,uint notify_filter,HANDLE event,int asynchronous); -int RegOpenCurrentUser(uint desired,HANDLE &result); -int RegOpenKeyExW(HANDLE key,const string sub_key,uint options,uint desired,HANDLE &result); -int RegOpenKeyTransactedW(HANDLE key,const string sub_key,uint options,uint desired,HANDLE &result,HANDLE transaction,PVOID extended_paremeter); -int RegOpenKeyW(HANDLE key,const string sub_key,HANDLE &result); -int RegOpenUserClassesRoot(HANDLE token,uint options,uint desired,HANDLE &result); -int RegOverridePredefKey(HANDLE key,HANDLE new_key); -int RegQueryInfoKeyW(HANDLE key,string class_name,uint &class_size,PVOID reserved,uint &sub_keys,uint &max_sub_key_len,uint &max_class_len,uint &values,uint &max_value_name_len,uint &max_value_len,uint &security_descriptor,FILETIME &last_write_time); -int RegQueryMultipleValuesW(HANDLE key,VALENTW &val_list[],uint num_vals,ushort &value_buf[],uint &totsize); -int RegQueryReflectionKey(HANDLE base,int &is_reflection_disabled); -int RegQueryValueExW(HANDLE key,const string value_name,PVOID reserved,uint &type,uchar &data[],uint &data_size); -int RegQueryValueW(HANDLE key,const string sub_key,uchar &data[],uint &data_size); -int RegRenameKey(HANDLE key,const string sub_key_name,const string new_key_name); -int RegReplaceKeyW(HANDLE key,const string sub_key,const string new_file,const string old_file); -int RegRestoreKeyW(HANDLE key,const string file,uint flags); -int RegSaveKeyExW(HANDLE key,const string file,PVOID security_attributes,uint flags); -int RegSaveKeyW(HANDLE key,const string file,PVOID security_attributes); -int RegSetKeySecurity(HANDLE key,uint SecurityInformation,SECURITY_DESCRIPTOR &security_descriptor); -int RegSetKeyValueW(HANDLE key,const string sub_key,const string value_name,uint type,const uchar &data[],uint data); -int RegSetValueExW(HANDLE key,const string value_name,PVOID reserved,uint type,const uchar &data[],uint data_size); -int RegSetValueW(HANDLE key,const string sub_key,uint type,const ushort &data[],uint data_size); -int RegUnLoadKeyW(HANDLE key,const string sub_key); -#import -//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/Include/WinAPI/winuser.mqh b/Include/WinAPI/winuser.mqh deleted file mode 100644 index f80c1ff..0000000 --- a/Include/WinAPI/winuser.mqh +++ /dev/null @@ -1,1825 +0,0 @@ -//+------------------------------------------------------------------+ -//| WinUser.mqh | -//| Copyright 2020, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -//--- -#define POINTER_DEVICE_PRODUCT_STRING_MAX 520 -#define KL_NAMELENGTH 9 - -//--- -enum AR_STATE - { - AR_ENABLED=0x0, - AR_DISABLED=0x1, - AR_SUPPRESSED=0x2, - AR_REMOTESESSION=0x4, - AR_MULTIMON=0x8, - AR_NOSENSOR=0x10, - AR_NOT_SUPPORTED=0x20, - AR_DOCKED=0x40, - AR_LAPTOP=0x80 - }; -//--- -enum DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS - { - DCDC_DEFAULT=0x0000, - DCDC_DISABLE_FONT_UPDATE=0x0001, - DCDC_DISABLE_RELAYOUT=0x0002 - }; -//--- -enum DIALOG_DPI_CHANGE_BEHAVIORS - { - DDC_DEFAULT=0x0000, - DDC_DISABLE_ALL=0x0001, - DDC_DISABLE_RESIZE=0x0002, - DDC_DISABLE_CONTROL_RELAYOUT=0x0004 - }; -//--- -enum EDIT_CONTROL_FEATURE - { - EDIT_CONTROL_FEATURE_ENTERPRISE_DATA_PROTECTION_PASTE_SUPPORT=0, - EDIT_CONTROL_FEATURE_PASTE_NOTIFICATIONS=1 - }; -//--- -enum FEEDBACK_TYPE - { - FEEDBACK_TOUCH_CONTACTVISUALIZATION=1, - FEEDBACK_PEN_BARRELVISUALIZATION=2, - FEEDBACK_PEN_TAP=3, - FEEDBACK_PEN_DOUBLETAP=4, - FEEDBACK_PEN_PRESSANDHOLD=5, - FEEDBACK_PEN_RIGHTTAP=6, - FEEDBACK_TOUCH_TAP=7, - FEEDBACK_TOUCH_DOUBLETAP=8, - FEEDBACK_TOUCH_PRESSANDHOLD=9, - FEEDBACK_TOUCH_RIGHTTAP=10, - FEEDBACK_GESTURE_PRESSANDTAP=11, - FEEDBACK_MAX=0xFFFFFFFF - }; -//--- -enum HANDEDNESS - { - HANDEDNESS_LEFT=0, - HANDEDNESS_RIGHT - }; -//--- -enum INPUT_MESSAGE_DEVICE_TYPE - { - IMDT_UNAVAILABLE=0x00000000, - IMDT_KEYBOARD=0x00000001, - IMDT_MOUSE=0x00000002, - IMDT_TOUCH=0x00000004, - IMDT_PEN=0x00000008, - IMDT_TOUCHPAD=0x00000010 - }; -//--- -enum INPUT_MESSAGE_ORIGIN_ID - { - IMO_UNAVAILABLE=0x00000000, - IMO_HARDWARE=0x00000001, - IMO_INJECTED=0x00000002, - IMO_SYSTEM=0x00000004 - }; -//--- -enum ORIENTATION_PREFERENCE - { - ORIENTATION_PREFERENCE_NONE=0x0, - ORIENTATION_PREFERENCE_LANDSCAPE=0x1, - ORIENTATION_PREFERENCE_PORTRAIT=0x2, - ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED=0x4, - ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED=0x8 - }; -//--- -enum POINTER_BUTTON_CHANGE_TYPE - { - POINTER_CHANGE_NONE, - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_UP - }; -//--- -enum POINTER_DEVICE_CURSOR_TYPE - { - POINTER_DEVICE_CURSOR_TYPE_UNKNOWN=0x00000000, - POINTER_DEVICE_CURSOR_TYPE_TIP=0x00000001, - POINTER_DEVICE_CURSOR_TYPE_ERASER=0x00000002, - POINTER_DEVICE_CURSOR_TYPE_MAX=0xFFFFFFFF - }; -//--- -enum POINTER_DEVICE_TYPE - { - POINTER_DEVICE_TYPE_INTEGRATED_PEN=0x00000001, - POINTER_DEVICE_TYPE_EXTERNAL_PEN=0x00000002, - POINTER_DEVICE_TYPE_TOUCH=0x00000003, - POINTER_DEVICE_TYPE_TOUCH_PAD=0x00000004, - POINTER_DEVICE_TYPE_MAX=0xFFFFFFFF - }; -//--- -struct ACCEL - { - uchar fVirt; - ushort key; - ushort cmd; - }; -//--- -struct ACCESSTIMEOUT - { - uint cbSize; - uint dwFlags; - uint iTimeOutMSec; - }; -//--- -struct ALTTABINFO - { - uint cbSize; - int cItems; - int cColumns; - int cRows; - int iColFocus; - int iRowFocus; - int cxItem; - int cyItem; - POINT ptStart; - }; -//--- -struct ANIMATIONINFO - { - uint cbSize; - int iMinAnimate; - }; -//--- -struct AUDIODESCRIPTION - { - uint cbSize; - int Enabled; - uint Locale; - }; -//--- -struct BSMINFO - { - uint cbSize; - HANDLE hdesk; - HANDLE hwnd; - LUID luid; - }; -//--- -struct CBT_CREATEWNDA - { - HANDLE hwndInsertAfter; - }; -//--- -struct CBT_CREATEWNDW - { - HANDLE hwndInsertAfter; - }; -//--- -struct CBTACTIVATESTRUCT - { - int fMouse; - HANDLE hWndActive; - }; -//--- -struct CHANGEFILTERSTRUCT - { - uint cbSize; - uint ExtStatus; - }; -//--- -struct CLIENTCREATESTRUCT - { - HANDLE hWindowMenu; - uint idFirstChild; - }; -//--- -struct COMBOBOXINFO - { - uint cbSize; - RECT rcItem; - RECT rcButton; - uint stateButton; - HANDLE hwndCombo; - HANDLE hwndItem; - HANDLE hwndList; - }; -//--- -struct COMPAREITEMSTRUCT - { - uint CtlType; - uint CtlID; - HANDLE hwndItem; - uint itemID1; - ulong itemData1; - uint itemID2; - ulong itemData2; - uint dwLocaleId; - }; -//--- -struct COPYDATASTRUCT - { - ulong dwData; - uint cbData; - }; -//--- -struct CREATESTRUCTW pack(8) - { - PVOID lpCreateParams; - HANDLE hInstance; - HANDLE hMenu; - HANDLE hwndParent; - int cy; - int cx; - int y; - int x; - int style; - PVOID lpszName; - PVOID lpszClass; - uint dwExStyle; - }; -//--- -struct CURSORINFO - { - uint cbSize; - uint flags; - HANDLE hCursor; - POINT ptScreenPos; - }; -//--- -struct CURSORSHAPE - { - int xHotSpot; - int yHotSpot; - int cx; - int cy; - int cbWidth; - uchar Planes; - uchar BitsPixel; - }; -//--- -struct CWPRETSTRUCT - { - PVOID lResult; - PVOID lParam; - PVOID wParam; - uint message; - HANDLE hwnd; - }; -//--- -struct CWPSTRUCT - { - PVOID lParam; - PVOID wParam; - uint message; - HANDLE hwnd; - }; -//--- -struct DEBUGHOOKINFO - { - uint idThread; - uint idThreadInstaller; - PVOID lParam; - PVOID wParam; - int code; - }; -//--- -struct DELETEITEMSTRUCT - { - uint CtlType; - uint CtlID; - uint itemID; - HANDLE hwndItem; - ulong itemData; - }; -//--- -struct DLGITEMTEMPLATE - { - uint style; - uint dwExtendedStyle; - short x; - short y; - short cx; - short cy; - ushort id; - }; -//--- -struct DLGTEMPLATE - { - uint style; - uint dwExtendedStyle; - ushort cdit; - short x; - short y; - short cx; - short cy; - }; -//--- -struct DRAWITEMSTRUCT - { - uint CtlType; - uint CtlID; - uint itemID; - uint itemAction; - uint itemState; - HANDLE hwndItem; - HANDLE hDC; - RECT rcItem; - ulong itemData; - }; -//--- -struct DRAWTEXTPARAMS - { - uint cbSize; - int iTabLength; - int iLeftMargin; - int iRightMargin; - uint uiLengthDrawn; - }; -//--- -struct DROPSTRUCT - { - HANDLE hwndSource; - HANDLE hwndSink; - uint wFmt; - ulong dwData; - POINT ptDrop; - uint dwControlData; - }; -//--- -struct EVENTMSG - { - uint message; - uint paramL; - uint paramH; - uint time; - HANDLE hwnd; - }; -//--- -struct FILTERKEYS - { - uint cbSize; - uint dwFlags; - uint iWaitMSec; - uint iDelayMSec; - uint iRepeatMSec; - uint iBounceMSec; - }; -//--- -struct FLASHWINFO - { - uint cbSize; - HANDLE hwnd; - uint dwFlags; - uint uCount; - uint dwTimeout; - }; -//--- -struct GESTURECONFIG - { - uint dwID; - uint dwWant; - uint dwBlock; - }; -//--- -struct GESTUREINFO - { - uint cbSize; - uint dwFlags; - uint dwID; - HANDLE hwndTarget; - POINTS ptsLocation; - uint dwInstanceID; - uint dwSequenceID; - ulong ullArguments; - uint cbExtraArgs; - }; -//--- -struct GESTURENOTIFYSTRUCT - { - uint cbSize; - uint dwFlags; - HANDLE hwndTarget; - POINTS ptsLocation; - uint dwInstanceID; - }; -//--- -struct GUITHREADINFO - { - uint cbSize; - uint flags; - HANDLE hwndActive; - HANDLE hwndFocus; - HANDLE hwndCapture; - HANDLE hwndMenuOwner; - HANDLE hwndMoveSize; - HANDLE hwndCaret; - RECT rcCaret; - }; -//--- -struct HARDWAREHOOKSTRUCT - { - HANDLE hwnd; - uint message; - PVOID wParam; - PVOID lParam; - }; -//--- -struct HARDWAREINPUT - { - uint uMsg; - ushort wParamL; - ushort wParamH; - }; -//--- -struct HELPINFO - { - uint cbSize; - int iContextType; - int iCtrlId; - HANDLE hItemHandle; - uint dwContextId; - POINT MousePos; - }; -//--- -struct HELPWININFOA - { - int wStructSize; - int x; - int y; - int dx; - int dy; - int wMax; - char rgchMember[2]; - }; -//--- -struct HELPWININFOW - { - int wStructSize; - int x; - int y; - int dx; - int dy; - int wMax; - short rgchMember[2]; - }; -//--- -struct HIGHCONTRASTW - { - uint cbSize; - uint dwFlags; - string lpszDefaultScheme; - }; -//--- -struct ICONINFO - { - int fIcon; - uint xHotspot; - uint yHotspot; - HANDLE hbmMask; - HANDLE hbmColor; - }; -//--- -struct ICONINFOEXW - { - uint cbSize; - int fIcon; - uint xHotspot; - uint yHotspot; - HANDLE hbmMask; - HANDLE hbmColor; - ushort wResID; - short szModName[MAX_PATH]; - short szResName[MAX_PATH]; - }; -//--- -struct ICONMETRICSW - { - uint cbSize; - int iHorzSpacing; - int iVertSpacing; - int iTitleWrap; - LOGFONTW lfFont; - }; -//--- -struct INPUT_INJECTION_VALUE - { - ushort page; - ushort usage; - int value; - ushort index; - }; -//--- -struct INPUT_MESSAGE_SOURCE - { - INPUT_MESSAGE_DEVICE_TYPE deviceType; - INPUT_MESSAGE_ORIGIN_ID originId; - }; -//--- -struct KBDLLHOOKSTRUCT - { - uint vkCode; - uint scanCode; - uint flags; - uint time; - ulong dwExtraInfo; - }; -//--- -struct KEYBDINPUT - { - ushort wVk; - ushort wScan; - uint dwFlags; - uint time; - ulong dwExtraInfo; - }; -//--- -struct LASTINPUTINFO - { - uint cbSize; - uint dwTime; - }; -//--- -struct MDICREATESTRUCTW - { - PVOID szClass; - PVOID szTitle; - HANDLE hOwner; - int x; - int y; - int cx; - int cy; - uint style; - PVOID lParam; - }; -//--- -struct MDINEXTMENU - { - HANDLE hmenuIn; - HANDLE hmenuNext; - HANDLE hwndNext; - }; -//--- -struct MEASUREITEMSTRUCT - { - uint CtlType; - uint CtlID; - uint itemID; - uint itemWidth; - uint itemHeight; - ulong itemData; - }; -//--- -struct MENUBARINFO - { - uint cbSize; - RECT rcBar; - HANDLE hMenu; - HANDLE hwndMenu; - int Focused; - }; -//--- -struct MENUGETOBJECTINFO - { - uint dwFlags; - uint uPos; - HANDLE hmenu; - PVOID riid; - PVOID pvObj; - }; -//--- -struct MENUINFO - { - uint cbSize; - uint fMask; - uint dwStyle; - uint cyMax; - HANDLE hbrBack; - uint dwContextHelpID; - ulong dwMenuData; - }; -//--- -struct MENUITEMINFOW - { - uint cbSize; - uint fMask; - uint fType; - uint fState; - uint wID; - HANDLE hSubMenu; - HANDLE hbmpChecked; - HANDLE hbmpUnchecked; - ulong dwItemData; - string dwTypeData; - uint cch; - HANDLE hbmpItem; - }; -//--- -struct MENUITEMTEMPLATE - { - ushort mtOption; - ushort mtID; - short mtString[1]; - }; -//--- -struct MENUITEMTEMPLATEHEADER - { - ushort versionNumber; - ushort offset; - }; -//--- -struct MINIMIZEDMETRICS - { - uint cbSize; - int iWidth; - int iHorzGap; - int iVertGap; - int iArrange; - }; -//--- -struct MINMAXINFO - { - POINT ptReserved; - POINT ptMaxSize; - POINT ptMaxPosition; - POINT ptMinTrackSize; - POINT ptMaxTrackSize; - }; -//--- -struct MONITORINFO - { - uint cbSize; - RECT rcMonitor; - RECT rcWork; - uint dwFlags; - }; -//--- -struct MOUSEHOOKSTRUCT - { - POINT pt; - HANDLE hwnd; - uint wHitTestCode; - ulong dwExtraInfo; - }; -//--- -struct MOUSEHOOKSTRUCTEX: public MONITORINFO - { - uint mouseData; - }; -//--- -struct MOUSEINPUT pack(8) - { - int dx; - int dy; - uint mouseData; - uint dwFlags; - uint time; - ulong dwExtraInfo; - }; -//--- -struct MOUSEKEYS - { - uint cbSize; - uint dwFlags; - uint iMaxSpeed; - uint iTimeToMaxSpeed; - uint iCtrlSpeed; - uint dwReserved1; - uint dwReserved2; - }; -//--- -struct MOUSEMOVEPOINT - { - int x; - int y; - uint time; - ulong dwExtraInfo; - }; -//--- -struct MSG - { - HANDLE hwnd; - uint message; - PVOID wParam; - PVOID lParam; - uint time; - POINT pt; - uint lPrivate; - }; -//--- -struct MSGBOXPARAMSW - { - uint cbSize; - HANDLE hwndOwner; - HANDLE hInstance; - PVOID lpszText; - PVOID lpszCaption; - uint dwStyle; - PVOID lpszIcon; - uint dwContextHelpId; - PVOID lpfnMsgBoxCallback; - uint dwLanguageId; - }; -//--- -struct MSLLHOOKSTRUCT - { - POINT pt; - uint mouseData; - uint flags; - uint time; - ulong dwExtraInfo; - }; -//--- -struct MULTIKEYHELPW - { - short mkKeylist; - short szKeyphrase[1]; - }; -//--- -struct NCCALCSIZE_PARAMS - { - RECT rgrc[3]; - PVOID lppos; - }; -//--- -struct NMHDR - { - HANDLE hwndFrom; - ulong idFrom; - uint code; - }; -//--- -struct NONCLIENTMETRICSW - { - uint cbSize; - int iBorderWidth; - int iScrollWidth; - int iScrollHeight; - int iCaptionWidth; - int iCaptionHeight; - LOGFONTW lfCaptionFont; - int iSmCaptionWidth; - int iSmCaptionHeight; - LOGFONTW lfSmCaptionFont; - int iMenuWidth; - int iMenuHeight; - LOGFONTW lfMenuFont; - LOGFONTW lfStatusFont; - LOGFONTW lfMessageFont; - int iPaddedBorderWidth; - }; -//--- -struct PAINTSTRUCT - { - HANDLE hdc; - int fErase; - RECT rcPaint; - int fRestore; - int fIncUpdate; - uchar rgbReserved[32]; - }; -//--- -struct POINTER_DEVICE_CURSOR_INFO - { - uint cursorId; - POINTER_DEVICE_CURSOR_TYPE cursor; - }; -//--- -struct POINTER_DEVICE_INFO pack(8) - { - uint displayOrientation; - HANDLE device; - POINTER_DEVICE_TYPE pointerDeviceType; - HANDLE monitor; - uint startingCursorId; - ushort maxActiveContacts; - short productString[POINTER_DEVICE_PRODUCT_STRING_MAX]; - }; -//--- -struct POINTER_DEVICE_PROPERTY - { - int logicalMin; - int logicalMax; - int physicalMin; - int physicalMax; - uint unit; - uint unitExponent; - ushort usagePageId; - ushort usageId; - }; -//--- -struct POINTER_INFO - { - uint pointerType; - uint pointerId; - uint frameId; - uint pointerFlags; - HANDLE sourceDevice; - HANDLE hwndTarget; - POINT ptPixelLocation; - POINT ptHimetricLocation; - POINT ptPixelLocationRaw; - POINT ptHimetricLocationRaw; - uint dwTime; - uint historyCount; - int InputData; - uint dwKeyStates; - ulong PerformanceCount; - POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; - }; -//--- -struct POINTER_PEN_INFO - { - POINTER_INFO pointerInfo; - uint penFlags; - uint penMask; - uint pressure; - uint rotation; - int tiltX; - int tiltY; - }; -//--- -struct POINTER_TOUCH_INFO - { - POINTER_INFO pointerInfo; - uint touchFlags; - uint touchMask; - RECT rcContact; - RECT rcContactRaw; - uint orientation; - uint pressure; - }; -//--- -struct POWERBROADCAST_SETTING - { - GUID PowerSetting; - uint DataLength; - uchar Data[1]; - }; -//--- -struct RAWINPUTDEVICE - { - ushort usUsagePage; - ushort usUsage; - uint dwFlags; - HANDLE hwndTarget; - }; -//--- -struct RAWINPUTDEVICELIST - { - HANDLE hDevice; - uint dwType; - }; -//--- -struct RAWINPUTHEADER - { - uint dwType; - uint dwSize; - HANDLE hDevice; - PVOID wParam; - }; -//--- -struct RID_DEVICE_INFO_HID - { - uint dwVendorId; - uint dwProductId; - uint dwVersionNumber; - ushort usUsagePage; - ushort usUsage; - }; -//--- -struct RID_DEVICE_INFO_KEYBOARD - { - uint dwType; - uint dwSubType; - uint dwKeyboardMode; - uint dwNumberOfFunctionKeys; - uint dwNumberOfIndicators; - uint dwNumberOfKeysTotal; - }; -//--- -struct RID_DEVICE_INFO_MOUSE - { - uint dwId; - uint dwNumberOfButtons; - uint dwSampleRate; - int fHasHorizontalWheel; - }; -//--- -struct SCROLLBARINFO - { - uint cbSize; - RECT rcScrollBar; - int dxyLineButton; - int xyThumbTop; - int xyThumbBottom; - int reserved; - }; -//--- -struct SCROLLINFO - { - uint cbSize; - uint fMask; - int nMin; - int nMax; - uint nPage; - int nPos; - int nTrackPos; - }; -//--- -struct SERIALKEYSW - { - uint cbSize; - uint dwFlags; - string lpszActivePort; - string lpszPort; - uint iBaudRate; - uint iPortState; - uint iActive; - }; -//--- -struct SHELLHOOKINFO - { - HANDLE hwnd; - RECT rc; - }; -//--- -struct SOUNDSENTRYW - { - uint cbSize; - uint dwFlags; - uint iFSTextEffect; - uint iFSTextEffectMSec; - uint iFSTextEffectColorBits; - uint iFSGrafEffect; - uint iFSGrafEffectMSec; - uint iFSGrafEffectColor; - uint iWindowsEffect; - uint iWindowsEffectMSec; - string lpszWindowsEffectDLL; - uint iWindowsEffectOrdinal; - }; -//--- -struct STICKYKEYS - { - uint cbSize; - uint dwFlags; - }; -//--- -struct STYLESTRUCT - { - uint styleOld; - uint styleNew; - }; -//--- -struct TITLEBARINFO - { - uint cbSize; - RECT rcTitleBar; - }; -//--- -struct TITLEBARINFOEX - { - uint cbSize; - RECT rcTitleBar; - }; -//--- -struct TOGGLEKEYS - { - uint cbSize; - uint dwFlags; - }; -//--- -struct TOUCH_HIT_TESTING_INPUT - { - uint pointerId; - POINT point; - RECT boundingBox; - RECT nonOccludedBoundingBox; - uint orientation; - }; -//--- -struct TOUCH_HIT_TESTING_PROXIMITY_EVALUATION - { - ushort score; - POINT adjustedPoint; - }; -//--- -struct TOUCHINPUT - { - int x; - int y; - HANDLE hSource; - uint dwID; - uint dwFlags; - uint dwMask; - uint dwTime; - ulong dwExtraInfo; - uint cxContact; - uint cyContact; - }; -//--- -struct TOUCHPREDICTIONPARAMETERS - { - uint cbSize; - uint dwLatency; - uint dwSampleTime; - uint bUseHWTimeStamp; - }; -//--- -struct TPMPARAMS - { - uint cbSize; - RECT rcExclude; - }; -//--- -struct TRACKMOUSEEVENT - { - uint cbSize; - uint dwFlags; - HANDLE hwndTrack; - uint dwHoverTime; - }; -//--- -struct UPDATELAYEREDWINDOWINFO - { - uint cbSize; - HANDLE hdcDst; - HANDLE hdcSrc; - uint crKey; - uint dwFlags; - }; -//--- -struct USAGE_PROPERTIES - { - ushort level; - ushort page; - ushort usage; - int logicalMinimum; - int logicalMaximum; - ushort unit; - ushort exponent; - uchar count; - int physicalMinimum; - int physicalMaximum; - }; -//--- -struct USEROBJECTFLAGS - { - int fInherit; - int fReserved; - uint dwFlags; - }; -//--- -struct WINDOWINFO - { - uint cbSize; - RECT rcWindow; - RECT rcClient; - uint dwStyle; - uint dwExStyle; - uint dwWindowStatus; - uint cxWindowBorders; - uint cyWindowBorders; - ushort atomWindowType; - ushort wCreatorVersion; - }; -//--- -struct WINDOWPLACEMENT - { - uint length; - uint flags; - uint showCmd; - POINT ptMinPosition; - POINT ptMaxPosition; - RECT rcNormalPosition; - RECT rcDevice; - }; -//--- -struct WINDOWPOS - { - HANDLE hwnd; - HANDLE hwndInsertAfter; - int x; - int y; - int cx; - int cy; - uint flags; - }; -//--- -struct WNDCLASSEXW pack(8) - { - uint cbSize; - uint style; - PVOID lpfnWndProc; - int cbClsExtra; - int cbWndExtra; - HANDLE hInstance; - HANDLE hIcon; - HANDLE hCursor; - HANDLE hbrBackground; - PVOID lpszMenuName; - PVOID lpszClassName; - HANDLE hIconSm; - }; -//--- -struct WNDCLASSW pack(8) - { - uint style; - PVOID lpfnWndProc; - int cbClsExtra; - int cbWndExtra; - HANDLE hInstance; - HANDLE hIcon; - HANDLE hCursor; - HANDLE hbrBackground; - PVOID lpszMenuName; - PVOID lpszClassName; - }; -//--- -struct WTSSESSION_NOTIFICATION - { - uint cbSize; - uint dwSessionId; - }; -//--- -struct RAWMOUSE pack(4) - { - ushort usFlags; - uint ulButtons; - uint ulRawButtons; - int lLastX; - int lLastY; - uint ulExtraInformation; - }; -//--- -struct RAWKEYBOARD - { - ushort MakeCode; - ushort Flags; - ushort Reserved; - ushort VKey; - uint Message; - uint ExtraInformation; - }; -//--- -struct RAWHID - { - uint dwSizeHid; - uint dwCount; - uchar bRawData[1]; - }; -//--- -union RAWFORMAT - { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - }; -//--- -struct RAWINPUT - { - RAWINPUTHEADER header; - RAWFORMAT data; - }; -//--- -struct INPUT_TRANSFORM - { - float _11; - float _12; - float _13; - float _14; - float _21; - float _22; - float _23; - float _24; - float _31; - float _32; - float _33; - float _34; - float _41; - float _42; - float _43; - float _44; - }; -//--- -struct MENUITEMINFO - { - uint cbSize; - uint fMask; - uint fType; - uint fState; - uint wID; - HANDLE hSubMenu; - HANDLE hbmpChecked; - HANDLE hbmpUnchecked; - uint dwItemData; - string dwTypeData; - uint cch; - }; -//--- -union INPUT_TYPE - { - MOUSEINPUT mi; - KEYBDINPUT ki; - HARDWAREINPUT hi; - }; -//--- -struct INPUT - { - uint type; - INPUT_TYPE in; - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -#import "user32.dll" -HANDLE ActivateKeyboardLayout(HANDLE hkl,uint Flags); -int AddClipboardFormatListener(HANDLE hwnd); -int AdjustWindowRect(RECT &rect,uint style,int menu); -int AdjustWindowRectEx(RECT &rect,uint style,int menu,uint ex_style); -int AdjustWindowRectExForDpi(RECT &rect,uint style,int menu,uint ex_style,uint dpi); -int AllowSetForegroundWindow(uint process_id); -int AnimateWindow(HANDLE wnd,uint time,uint flags); -int AnyPopup(void); -int AppendMenuW(HANDLE menu,uint flags,ulong uIDNewItem,const string new_item); -int AreDpiAwarenessContextsEqual(HANDLE dpiContextA,HANDLE dpiContextB); -uint ArrangeIconicWindows(HANDLE wnd); -int AttachThreadInput(uint attach,uint attach_to,int attach); -HANDLE BeginDeferWindowPos(int num_windows); -HANDLE BeginPaint(HANDLE wnd,PAINTSTRUCT &paint); -int BlockInput(int block_it); -int BringWindowToTop(HANDLE wnd); -int BroadcastSystemMessage(uint flags,uint &info,uint Msg,PVOID param,PVOID param); -int BroadcastSystemMessageExW(uint flags,uint &info,uint Msg,PVOID param,PVOID param,BSMINFO &info); -int BroadcastSystemMessageW(uint flags,uint &info,uint Msg,PVOID param,PVOID param); -int CalculatePopupWindowPosition(const POINT &point,const SIZE &size,uint flags,RECT &rect,RECT &window_position); -int CallMsgFilterW(MSG &msg,int code); -PVOID CallNextHookEx(HANDLE hhk,int code,PVOID param,PVOID param); -PVOID CallWindowProcW(PVOID prev_wnd_func,HANDLE wnd,uint Msg,PVOID param,PVOID param); -int CancelShutdown(void); -ushort CascadeWindows(HANDLE parent,uint how,const RECT &rect,uint kids,const HANDLE &kids[]); -int ChangeClipboardChain(HANDLE wnd_remove,HANDLE wnd_new_next); -int ChangeDisplaySettingsExW(const string device_name,DEVMODEW &dev_mode,HANDLE hwnd,uint dwflags,PVOID param); -int ChangeDisplaySettingsW(DEVMODEW &dev_mode,uint flags); -int ChangeMenuW(HANDLE menu,uint cmd,const string new_item,uint insert,uint flags); -int ChangeWindowMessageFilter(uint message,uint flag); -int ChangeWindowMessageFilterEx(HANDLE hwnd,uint message,uint action,CHANGEFILTERSTRUCT &change_filter_struct); -uint CharLowerBuffW(string &lpsz,uint length); -PVOID CharLowerW(string &lpsz); -PVOID CharNextW(PVOID lpsz); -PVOID CharNextW(string lpsz); -PVOID CharPrevW(const PVOID start,const PVOID current); -PVOID CharPrevW(const string start,const string current); -int CharToOemBuffW(const string src,char &dst[],uint dst_length); -int CharToOemW(const string src,char &dst[]); -uint CharUpperBuffW(string &lpsz,uint length); -PVOID CharUpperW(string &lpsz); -int CheckDlgButton(HANDLE dlg,int nIDButton,uint check); -uint CheckMenuItem(HANDLE menu,uint uIDCheckItem,uint check); -int CheckMenuRadioItem(HANDLE hmenu,uint first,uint last,uint check,uint flags); -int CheckRadioButton(HANDLE dlg,int nIDFirstButton,int nIDLastButton,int nIDCheckButton); -HANDLE ChildWindowFromPoint(HANDLE wnd_parent,POINT &point); -HANDLE ChildWindowFromPointEx(HANDLE hwnd,POINT &pt,uint flags); -int ClientToScreen(HANDLE wnd,POINT &point); -int ClipCursor(RECT &rect); -int CloseClipboard(void); -int CloseDesktop(HANDLE desktop); -int CloseGestureInfoHandle(HANDLE gesture_info); -int CloseTouchInputHandle(HANDLE touch_input); -int CloseWindow(HANDLE wnd); -int CloseWindowStation(HANDLE win_sta); -int CopyAcceleratorTableW(HANDLE accel_src,ACCEL &accel_dst,int accel_entries); -HANDLE CopyIcon(HANDLE icon); -HANDLE CopyImage(HANDLE h,uint type,int cx,int cy,uint flags); -int CopyRect(RECT &dst,RECT &src); -int CountClipboardFormats(void); -HANDLE CreateAcceleratorTableW(ACCEL &paccel,int accel); -int CreateCaret(HANDLE wnd,HANDLE bitmap,int width,int height); -HANDLE CreateCursor(HANDLE inst,int hot_spot,int hot_spot,int width,int height,PVOID pvANDPlane,PVOID pvXORPlane); -HANDLE CreateDesktopExW(const string desktop,const PVOID device,PVOID devmode,uint flags,uint desired_access,PVOID lpsa,uint heap_size,PVOID pvoid); -HANDLE CreateDesktopExW(const string desktop,const string device,PVOID devmode,uint flags,uint desired_access,PVOID lpsa,uint heap_size,PVOID pvoid); -HANDLE CreateDesktopExW(const string desktop,const PVOID device,DEVMODEW &devmode,uint flags,uint desired_access,PVOID lpsa,uint heap_size,PVOID pvoid); -HANDLE CreateDesktopExW(const string desktop,const string device,DEVMODEW &devmode,uint flags,uint desired_access,PVOID lpsa,uint heap_size,PVOID pvoid); -HANDLE CreateDesktopW(const string desktop,const PVOID device,PVOID devmode,uint flags,uint desired_access,PVOID lpsa); -HANDLE CreateDesktopW(const string desktop,const string device,PVOID devmode,uint flags,uint desired_access,PVOID lpsa); -HANDLE CreateDesktopW(const string desktop,const PVOID device,DEVMODEW &devmode,uint flags,uint desired_access,PVOID lpsa); -HANDLE CreateDesktopW(const string desktop,const string device,DEVMODEW &devmode,uint flags,uint desired_access,PVOID lpsa); -HANDLE CreateDialogIndirectParamW(HANDLE instance,const DLGTEMPLATE &dlg_template,HANDLE wnd_parent,PVOID dialog_func,PVOID init_param); -HANDLE CreateDialogParamW(HANDLE instance,const string template_name,HANDLE wnd_parent,PVOID dialog_func,PVOID init_param); -HANDLE CreateIcon(HANDLE instance,int width,int height,uchar planes,uchar bits_pixel,const uchar &lpbANDbits[],const uchar &lpbXORbits[]); -HANDLE CreateIconFromResource(uchar &presbits,uint res_size,int icon,uint ver); -HANDLE CreateIconFromResourceEx(uchar &presbits,uint res_size,int icon,uint ver,int desired,int desired,uint Flags); -HANDLE CreateIconIndirect(ICONINFO &piconinfo); -HANDLE CreateMDIWindowW(const string class_name,const string window_name,uint style,int X,int Y,int width,int height,HANDLE wnd_parent,HANDLE instance,PVOID param); -HANDLE CreateMenu(void); -HANDLE CreatePopupMenu(void); -HANDLE CreateWindowExW(uint ex_style,const PVOID class_name,const PVOID window_name,uint style,int X,int Y,int width,int height,HANDLE wnd_parent,HANDLE menu,HANDLE instance,PVOID param); -HANDLE CreateWindowExW(uint ex_style,const string class_name,const string window_name,uint style,int X,int Y,int width,int height,HANDLE wnd_parent,HANDLE menu,HANDLE instance,PVOID param); -HANDLE CreateWindowStationW(const string lpwinsta,uint flags,uint desired_access,PVOID lpsa); -PVOID DefDlgProcW(HANDLE dlg,uint Msg,PVOID param,PVOID param); -HANDLE DeferWindowPos(HANDLE win_pos_info,HANDLE wnd,HANDLE wnd_insert_after,int x,int y,int cx,int cy,uint flags); -PVOID DefFrameProcW(HANDLE wnd,HANDLE hWndMDIClient,uint msg,PVOID param,PVOID param); -PVOID DefMDIChildProcW(HANDLE wnd,uint msg,PVOID param,PVOID param); -PVOID DefRawInputProc(RAWINPUT &raw_input[],int inp,uint size_header); -PVOID DefWindowProcW(HANDLE wnd,uint Msg,PVOID param,PVOID param); -int DeleteMenu(HANDLE menu,uint position,uint flags); -int DeregisterShellHookWindow(HANDLE hwnd); -int DestroyAcceleratorTable(HANDLE accel); -int DestroyCaret(void); -int DestroyCursor(HANDLE cursor); -int DestroyIcon(HANDLE icon); -int DestroyMenu(HANDLE menu); -int DestroyWindow(HANDLE wnd); -long DialogBoxIndirectParamW(HANDLE instance,DLGTEMPLATE &dialog_template,HANDLE wnd_parent,PVOID dialog_func,PVOID init_param); -long DialogBoxParamW(HANDLE instance,const string template_name,HANDLE wnd_parent,PVOID dialog_func,PVOID init_param); -void DisableProcessWindowsGhosting(void); -PVOID DispatchMessageW(MSG &msg); -int DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER &packet); -int DisplayConfigSetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER &packet); -int DlgDirListComboBoxW(HANDLE dlg,string path_spec,int nIDComboBox,int nIDStaticPath,uint filetype); -int DlgDirListW(HANDLE dlg,string path_spec,int nIDListBox,int nIDStaticPath,uint file_type); -int DlgDirSelectComboBoxExW(HANDLE dlg,string str,int out,int combo_box); -int DlgDirSelectExW(HANDLE dlg,string str,int count,int list_box); -int DragDetect(HANDLE hwnd,POINT &pt); -uint DragObject(HANDLE parent,HANDLE from,uint fmt,ulong data,HANDLE hcur); -int DrawAnimatedRects(HANDLE hwnd,int ani,RECT &from,RECT &to); -int DrawCaption(HANDLE hwnd,HANDLE hdc,RECT &lprect,uint flags); -int DrawEdge(HANDLE hdc,RECT &qrc,uint edge,uint flags); -int DrawFocusRect(HANDLE hDC,RECT &lprc); -int DrawFrameControl(HANDLE,RECT &,uint,uint); -int DrawIcon(HANDLE hDC,int X,int Y,HANDLE icon); -int DrawIconEx(HANDLE hdc,int left,int top,HANDLE icon,int width,int width,uint if_ani_cur,HANDLE flicker_free_draw,uint flags); -int DrawMenuBar(HANDLE wnd); -int DrawStateW(HANDLE hdc,HANDLE fore,PVOID call_back,PVOID data,PVOID data,int x,int y,int cx,int cy,uint flags); -int DrawTextExW(HANDLE hdc,string text,int text,RECT &lprc,uint format,DRAWTEXTPARAMS &lpdtp); -int DrawTextW(HANDLE hdc,const string text,int text,RECT &lprc,uint format); -int EmptyClipboard(void); -int EnableMenuItem(HANDLE menu,uint uIDEnableItem,uint enable); -int EnableMouseInPointer(int enable); -int EnableNonClientDpiScaling(HANDLE hwnd); -int EnableScrollBar(HANDLE wnd,uint wSBflags,uint arrows); -int EnableWindow(HANDLE wnd,int enable); -int EndDeferWindowPos(HANDLE win_pos_info); -int EndDialog(HANDLE dlg,long result); -int EndMenu(void); -int EndPaint(HANDLE wnd,PAINTSTRUCT &paint); -int EndTask(HANDLE wnd,int shut_down,int force); -int EnumChildWindows(HANDLE wnd_parent,PVOID enum_func,PVOID param); -uint EnumClipboardFormats(uint format); -int EnumDesktopsW(HANDLE hwinsta,PVOID enum_func,PVOID param); -int EnumDesktopWindows(HANDLE desktop,PVOID lpfn,PVOID param); -int EnumDisplayDevicesW(const string device,uint dev_num,DISPLAY_DEVICEW &display_device,uint flags); -int EnumDisplayMonitors(HANDLE hdc,const RECT &clip,PVOID enum_obj,PVOID data); -int EnumDisplaySettingsExW(const string device_name,uint mode_num,DEVMODEW &dev_mode,uint flags); -int EnumDisplaySettingsW(const string device_name,uint mode_num,DEVMODEW &dev_mode); -int EnumPropsExW(HANDLE wnd,PVOID enum_func,PVOID param); -int EnumPropsW(HANDLE wnd,PVOID enum_func); -int EnumThreadWindows(uint thread_id,PVOID lpfn,PVOID param); -int EnumWindows(PVOID enum_func,PVOID param); -int EnumWindowStationsW(PVOID enum_func,PVOID param); -int EqualRect(RECT &lprc1,RECT &lprc2); -int EvaluateProximityToPolygon(uint vertices,const POINT &polygon[],const TOUCH_HIT_TESTING_INPUT &hit_testing_input[],TOUCH_HIT_TESTING_PROXIMITY_EVALUATION &proximity_eval); -int EvaluateProximityToRect(const RECT &bounding_box[],const TOUCH_HIT_TESTING_INPUT &hit_testing_input[],TOUCH_HIT_TESTING_PROXIMITY_EVALUATION &proximity_eval); -int ExcludeUpdateRgn(HANDLE hDC,HANDLE wnd); -int ExitWindowsEx(uint flags,uint reason); -int FillRect(HANDLE hDC,RECT &lprc,HANDLE hbr); -HANDLE FindWindowExW(HANDLE wnd_parent,HANDLE wnd_child_after,const string class_name,const string window); -HANDLE FindWindowW(const string class_name,const string window_name); -int FlashWindow(HANDLE wnd,int invert); -int FlashWindowEx(FLASHWINFO &pfwi); -int FrameRect(HANDLE hDC,RECT &lprc,HANDLE hbr); -HANDLE GetActiveWindow(void); -int GetAltTabInfoW(HANDLE hwnd,int item,ALTTABINFO &pati,string item_text,uint item_text); -HANDLE GetAncestor(HANDLE hwnd,uint flags); -short GetAsyncKeyState(int key); -int GetAutoRotationState(AR_STATE &state); -DPI_AWARENESS GetAwarenessFromDpiAwarenessContext(HANDLE value); -HANDLE GetCapture(void); -uint GetCaretBlinkTime(void); -int GetCaretPos(POINT &point); -int GetCIMSSM(INPUT_MESSAGE_SOURCE &message_source); -int GetClassInfoExW(HANDLE instance,const string class_name,WNDCLASSEXW &lpwcx); -int GetClassInfoW(HANDLE instance,const string class_name,WNDCLASSW &wnd_class); -ulong GetClassLongPtrW(HANDLE wnd,int index); -uint GetClassLongW(HANDLE wnd,int index); -int GetClassNameW(HANDLE wnd,ushort &class_name[],int max_count); -ushort GetClassWord(HANDLE wnd,int index); -int GetClientRect(HANDLE wnd,RECT &rect); -HANDLE GetClipboardData(uint format); -int GetClipboardFormatNameW(uint format,ushort &format_name[],int max_count); -HANDLE GetClipboardOwner(void); -uint GetClipboardSequenceNumber(void); -HANDLE GetClipboardViewer(void); -int GetClipCursor(RECT &rect); -int GetComboBoxInfo(HANDLE combo,COMBOBOXINFO &pcbi); -int GetCurrentInputMessageSource(INPUT_MESSAGE_SOURCE &message_source); -HANDLE GetCursor(void); -int GetCursorInfo(CURSORINFO &pci); -int GetCursorPos(POINT &point); -HANDLE GetDC(HANDLE wnd); -HANDLE GetDCEx(HANDLE wnd,HANDLE clip,uint flags); -HANDLE GetDesktopWindow(void); -int GetDialogBaseUnits(void); -DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS GetDialogControlDpiChangeBehavior(HANDLE wnd); -DIALOG_DPI_CHANGE_BEHAVIORS GetDialogDpiChangeBehavior(HANDLE dlg); -int GetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE &orientation); -int GetDisplayConfigBufferSizes(uint flags,uint &path_array_elements,uint &mode_info_array_elements); -int GetDlgCtrlID(HANDLE wnd); -HANDLE GetDlgItem(HANDLE dlg,int nIDDlgItem); -uint GetDlgItemInt(HANDLE dlg,int nIDDlgItem,int &translated,int signed); -uint GetDlgItemTextW(HANDLE dlg,int nIDDlgItem,string str,int max); -uint GetDoubleClickTime(void); -uint GetDpiForSystem(void); -uint GetDpiForWindow(HANDLE hwnd); -uint GetDpiFromDpiAwarenessContext(HANDLE value); -HANDLE GetFocus(void); -HANDLE GetForegroundWindow(void); -int GetGestureConfig(HANDLE hwnd,uint reserved,uint flags,uint &pcIDs,GESTURECONFIG &gesture_config[],uint size); -int GetGestureExtraArgs(HANDLE gesture_info,uint extra_args,uchar &extra_args); -int GetGestureInfo(HANDLE gesture_info,GESTUREINFO &gesture_info); -uint GetGuiResources(HANDLE process,uint flags); -int GetGUIThreadInfo(uint thread,GUITHREADINFO &pgui); -int GetIconInfo(HANDLE icon,ICONINFO &piconinfo); -int GetIconInfoExW(HANDLE hicon,ICONINFOEXW &piconinfo); -int GetInputState(void); -uint GetKBCodePage(void); -HANDLE GetKeyboardLayout(uint thread); -int GetKeyboardLayoutList(int buff,HANDLE &list[]); -int GetKeyboardLayoutNameW(ushort &pwszKLID[]); -int GetKeyboardState(uchar &key_state[]); -int GetKeyboardType(int type_flag); -int GetKeyNameTextW(long param,ushort &str[],int size); -short GetKeyState(int virt_key); -HANDLE GetLastActivePopup(HANDLE wnd); -int GetLastInputInfo(LASTINPUTINFO &plii); -int GetLayeredWindowAttributes(HANDLE hwnd,uint &key,uchar &alpha,uint &flags); -uint GetListBoxInfo(HANDLE hwnd); -HANDLE GetMenu(HANDLE wnd); -int GetMenuBarInfo(HANDLE hwnd,int object,int item,MENUBARINFO &pmbi); -int GetMenuCheckMarkDimensions(void); -uint GetMenuContextHelpId(HANDLE); -uint GetMenuDefaultItem(HANDLE menu,uint by_pos,uint flags); -int GetMenuInfo(HANDLE,MENUINFO &); -int GetMenuItemCount(HANDLE menu); -uint GetMenuItemID(HANDLE menu,int pos); -int GetMenuItemInfoW(HANDLE hmenu,uint item,int by_position,MENUITEMINFOW &lpmii); -int GetMenuItemRect(HANDLE wnd,HANDLE menu,uint item,RECT &item); -uint GetMenuState(HANDLE menu,uint id,uint flags); -int GetMenuStringW(HANDLE menu,uint uIDItem,string str,int max,uint flags); -PVOID GetMessageExtraInfo(void); -uint GetMessagePos(void); -int GetMessageTime(void); -int GetMessageW(MSG &msg,HANDLE wnd,uint msg_filter_min,uint msg_filter_max); -int GetMonitorInfoW(HANDLE monitor,MONITORINFO &lpmi); -int GetMouseMovePointsEx(uint size,MOUSEMOVEPOINT &lppt,MOUSEMOVEPOINT &buf,int buf_points,uint resolution); -HANDLE GetNextDlgGroupItem(HANDLE dlg,HANDLE ctl,int previous); -HANDLE GetNextDlgTabItem(HANDLE dlg,HANDLE ctl,int previous); -HANDLE GetOpenClipboardWindow(void); -HANDLE GetParent(HANDLE wnd); -int GetPhysicalCursorPos(POINT &point); -int GetPointerCursorId(uint pointer_id,uint &cursor_id); -int GetPointerDevice(HANDLE device,POINTER_DEVICE_INFO &device); -int GetPointerDeviceCursors(HANDLE device,uint &count,POINTER_DEVICE_CURSOR_INFO &cursors[]); -int GetPointerDeviceProperties(HANDLE device,uint &count,POINTER_DEVICE_PROPERTY &properties[]); -int GetPointerDeviceRects(HANDLE device,RECT &device_rect,RECT &rect); -int GetPointerDevices(uint &count,POINTER_DEVICE_INFO &devices[]); -int GetPointerFrameInfo(uint id,uint &count,POINTER_INFO &info[]); -int GetPointerFrameInfoHistory(uint id,uint &count,uint &count,POINTER_INFO &info[]); -int GetPointerFramePenInfo(uint id,uint &count,POINTER_PEN_INFO &info[]); -int GetPointerFramePenInfoHistory(uint id,uint &count,uint &count,POINTER_PEN_INFO &info[]); -int GetPointerFrameTouchInfo(uint id,uint &count,POINTER_TOUCH_INFO &info[]); -int GetPointerFrameTouchInfoHistory(uint id,uint &count,uint &count,POINTER_TOUCH_INFO &info[]); -int GetPointerInfo(uint id,POINTER_INFO &info[]); -int GetPointerInfoHistory(uint id,uint &count,POINTER_INFO &info[]); -int GetPointerInputTransform(uint id,uint count,INPUT_TRANSFORM &transform); -int GetPointerPenInfo(uint id,POINTER_PEN_INFO &info); -int GetPointerPenInfoHistory(uint id,uint &count,POINTER_PEN_INFO &info); -int GetPointerTouchInfo(uint id,POINTER_TOUCH_INFO &info[]); -int GetPointerTouchInfoHistory(uint id,uint &count,POINTER_TOUCH_INFO &info[]); -int GetPointerType(uint id,uint &type); -int GetPriorityClipboardFormat(uint &format_priority_list[],int formats); -int GetProcessDefaultLayout(uint &default_layout); -HANDLE GetProcessWindowStation(void); -HANDLE GetPropW(HANDLE wnd,const string str); -uint GetQueueStatus(uint flags); -uint GetRawInputBuffer(RAWINPUT &data,uint &size,uint size_header); -uint GetRawInputData(HANDLE raw_input,uint command,PVOID data,uint &size,uint size_header); -uint GetRawInputDeviceInfoW(HANDLE device,uint command,PVOID data,uint &size); -uint GetRawInputDeviceList(RAWINPUTDEVICELIST &raw_input_device_list,uint &num_devices,uint size); -int GetRawPointerDeviceData(uint id,uint count,uint count,POINTER_DEVICE_PROPERTY &properties[],int &values[]); -uint GetRegisteredRawInputDevices(RAWINPUTDEVICE &raw_input_devices,uint &num_devices,uint size); -int GetScrollBarInfo(HANDLE hwnd,int object,SCROLLBARINFO &psbi); -int GetScrollInfo(HANDLE hwnd,int bar,SCROLLINFO &lpsi); -int GetScrollPos(HANDLE wnd,int bar); -int GetScrollRange(HANDLE wnd,int bar,int &min_pos,int &max_pos); -HANDLE GetShellWindow(void); -HANDLE GetSubMenu(HANDLE menu,int pos); -uint GetSysColor(int index); -HANDLE GetSysColorBrush(int index); -uint GetSystemDpiForProcess(HANDLE process); -HANDLE GetSystemMenu(HANDLE wnd,int revert); -int GetSystemMetrics(int index); -int GetSystemMetricsForDpi(int index,uint dpi); -uint GetTabbedTextExtentW(HANDLE hdc,const string str,int count,int tab_positions,const int &tab_stop_positions[]); -HANDLE GetThreadDesktop(uint thread_id); -HANDLE GetThreadDpiAwarenessContext(void); -DPI_HOSTING_BEHAVIOR GetThreadDpiHostingBehavior(void); -int GetTitleBarInfo(HANDLE hwnd,TITLEBARINFO &pti); -HANDLE GetTopWindow(HANDLE wnd); -int GetTouchInputInfo(HANDLE touch_input,uint inputs,TOUCHINPUT &inputs,int size); -uint GetUnpredictedMessagePos(void); -int GetUpdatedClipboardFormats(uint &formats[],uint formats_number,uint &formats_out); -int GetUpdateRect(HANDLE wnd,RECT &rect,int erase); -int GetUpdateRgn(HANDLE wnd,HANDLE rgn,int erase); -int GetUserObjectInformationW(HANDLE obj,int index,PVOID info,uint length,uint &length_needed); -int GetUserObjectSecurity(HANDLE obj,uint &pSIRequested,SECURITY_DESCRIPTOR &pSID,uint length,uint &length_needed); -HANDLE GetWindow(HANDLE wnd,uint cmd); -uint GetWindowContextHelpId(HANDLE); -HANDLE GetWindowDC(HANDLE wnd); -int GetWindowDisplayAffinity(HANDLE wnd,uint &affinity); -HANDLE GetWindowDpiAwarenessContext(HANDLE hwnd); -DPI_HOSTING_BEHAVIOR GetWindowDpiHostingBehavior(HANDLE hwnd); -int GetWindowFeedbackSetting(HANDLE hwnd,FEEDBACK_TYPE feedback,uint flags,uint size,int &config); -int GetWindowInfo(HANDLE hwnd,WINDOWINFO &pwi); -long GetWindowLongPtrW(HANDLE wnd,int index); -int GetWindowLongW(HANDLE wnd,int index); -uint GetWindowModuleFileNameW(HANDLE hwnd,ushort &file_name[],uint file_name_max); -int GetWindowPlacement(HANDLE wnd,WINDOWPLACEMENT &lpwndpl); -int GetWindowRect(HANDLE wnd,RECT &rect); -int GetWindowRgn(HANDLE wnd,HANDLE rgn); -int GetWindowRgnBox(HANDLE wnd,RECT &lprc); -int GetWindowTextLengthW(HANDLE wnd); -int GetWindowTextW(HANDLE wnd,ushort &str[],int max_count); -uint GetWindowThreadProcessId(HANDLE wnd,uint &process_id); -ushort GetWindowWord(HANDLE wnd,int index); -int GrayStringW(HANDLE hDC,HANDLE brush,PVOID output_func,uchar &data[],int count,int X,int Y,int width,int height); -int GrayStringW(HANDLE hDC,HANDLE brush,PVOID output_func,PVOID data,int count,int X,int Y,int width,int height); -int HideCaret(HANDLE wnd); -int HiliteMenuItem(HANDLE wnd,HANDLE menu,uint uIDHiliteItem,uint hilite); -int InflateRect(RECT &lprc,int dx,int dy); -int InheritWindowMonitor(HANDLE hwnd,HANDLE inherit); -int InitializeTouchInjection(uint count,uint mode); -int InjectTouchInput(uint count,POINTER_TOUCH_INFO &contacts); -int InSendMessage(void); -uint InSendMessageEx(PVOID reserved); -int InsertMenuItemW(HANDLE hmenu,uint item,int by_position,const MENUITEMINFO &lpmi); -int InsertMenuW(HANDLE menu,uint position,uint flags,ulong uIDNewItem,const string new_item); -int InternalGetWindowText(HANDLE wnd,string str,int max_count); -int IntersectRect(RECT &dst,RECT &src1,RECT &src2); -int InvalidateRect(HANDLE wnd,RECT &rect,int erase); -int InvalidateRgn(HANDLE wnd,HANDLE rgn,int erase); -int InvertRect(HANDLE hDC,RECT &lprc); -int IsCharAlphaNumericW(short ch); -int IsCharAlphaW(short ch); -int IsCharLowerW(short ch); -int IsCharUpperW(short ch); -int IsChild(HANDLE wnd_parent,HANDLE wnd); -int IsClipboardFormatAvailable(uint format); -int IsDialogMessageW(HANDLE dlg,MSG &msg); -uint IsDlgButtonChecked(HANDLE dlg,int nIDButton); -int IsGUIThread(int convert); -int IsHungAppWindow(HANDLE hwnd); -int IsIconic(HANDLE wnd); -int IsImmersiveProcess(HANDLE process); -int IsMenu(HANDLE menu); -int IsMouseInPointerEnabled(void); -int IsProcessDPIAware(void); -int IsRectEmpty(RECT &lprc); -int IsTouchWindow(HANDLE hwnd,uint &flags); -int IsValidDpiAwarenessContext(HANDLE value); -int IsWindow(HANDLE wnd); -int IsWindowEnabled(HANDLE wnd); -int IsWindowUnicode(HANDLE wnd); -int IsWindowVisible(HANDLE wnd); -int IsWinEventHookInstalled(uint event); -int IsWow64Message(void); -int IsZoomed(HANDLE wnd); -void keybd_event(uchar vk,uchar scan,uint flags,ulong extra_info); -int KillTimer(HANDLE wnd,ulong uIDEvent); -HANDLE LoadAcceleratorsW(HANDLE instance,const string table_name); -HANDLE LoadBitmapW(HANDLE instance,const string bitmap_name); -HANDLE LoadCursorFromFileW(const string file_name); -HANDLE LoadCursorW(HANDLE instance,const string cursor_name); -HANDLE LoadIconW(HANDLE instance,const string icon_name); -HANDLE LoadImageW(HANDLE inst,const string name,uint type,int cx,int cy,uint load); -HANDLE LoadKeyboardLayoutW(const string pwszKLID,uint Flags); -HANDLE LoadMenuIndirectW(const PVOID menu_template); -HANDLE LoadMenuW(HANDLE instance,const string menu_name); -int LoadStringW(HANDLE instance,uint uID,string buffer,int buffer_max); -int LockSetForegroundWindow(uint lock_code); -int LockWindowUpdate(HANDLE wnd_lock); -int LockWorkStation(void); -int LogicalToPhysicalPoint(HANDLE wnd,POINT &point); -int LogicalToPhysicalPointForPerMonitorDPI(HANDLE wnd,POINT &point); -int LookupIconIdFromDirectory(uchar &presbits[],int icon); -int LookupIconIdFromDirectoryEx(uchar &presbits,int icon,int desired,int desired,uint Flags); -int MapDialogRect(HANDLE dlg,RECT &rect); -uint MapVirtualKeyExW(uint code,uint map_type,HANDLE dwhkl); -uint MapVirtualKeyW(uint code,uint map_type); -int MapWindowPoints(HANDLE wnd_from,HANDLE wnd_to,POINT &points[],uint points_count); -int MenuItemFromPoint(HANDLE wnd,HANDLE menu,POINT &screen); -int MessageBeep(uint type); -int MessageBoxExW(HANDLE wnd,const string text,const string caption,uint type,ushort language_id); -int MessageBoxIndirectW(MSGBOXPARAMSW &lpmbp); -int MessageBoxW(HANDLE wnd,const string text,const string caption,uint type); -int ModifyMenuW(HANDLE mnu,uint position,uint flags,ulong uIDNewItem,const string new_item); -HANDLE MonitorFromPoint(POINT &pt,uint flags); -HANDLE MonitorFromRect(const RECT &lprc,uint flags); -HANDLE MonitorFromWindow(HANDLE hwnd,uint flags); -void mouse_event(uint flags,uint dx,uint dy,uint data,ulong extra_info); -int MoveWindow(HANDLE wnd,int X,int Y,int width,int height,int repaint); -uint MsgWaitForMultipleObjects(uint count,const HANDLE &handles[],int wait_all,uint milliseconds,uint wake_mask); -uint MsgWaitForMultipleObjectsEx(uint count,const HANDLE &handles[],uint milliseconds,uint wake_mask,uint flags); -void NotifyWinEvent(uint event,HANDLE hwnd,int object,int child); -uint OemKeyScan(ushort oem_char); -int OemToCharBuffW(const char &src[],ushort &dst[],uint dst_length); -int OemToCharW(const char &src[],ushort &dst[]); -int OffsetRect(RECT &lprc,int dx,int dy); -int OpenClipboard(HANDLE wnd_new_owner); -HANDLE OpenDesktopW(const string desktop,uint flags,int inherit,uint desired_access); -int OpenIcon(HANDLE wnd); -HANDLE OpenInputDesktop(uint flags,int inherit,uint desired_access); -HANDLE OpenWindowStationW(const string win_sta,int inherit,uint desired_access); -PVOID PackTouchHitTestingProximityEvaluation(const TOUCH_HIT_TESTING_INPUT &hit_testing_input[],const TOUCH_HIT_TESTING_PROXIMITY_EVALUATION &proximity_eval[]); -int PaintDesktop(HANDLE hdc); -int PeekMessageW(MSG &msg,HANDLE wnd,uint msg_filter_min,uint msg_filter_max,uint remove_msg); -int PhysicalToLogicalPoint(HANDLE wnd,POINT &point); -int PhysicalToLogicalPointForPerMonitorDPI(HANDLE wnd,POINT &point); -int PostMessageW(HANDLE wnd,uint Msg,PVOID param,PVOID param); -void PostQuitMessage(int exit_code); -int PostThreadMessageW(uint thread,uint Msg,PVOID param,PVOID param); -int PrintWindow(HANDLE hwnd,HANDLE blt,uint flags); -uint PrivateExtractIconsW(const string file_name,int icon_index,int icon,int icon,HANDLE &phicon,uint &piconid,uint icons,uint flags); -int PtInRect(const RECT &lprc,long pt); -long QueryDisplayConfig(uint flags,uint &path_array_elements,DISPLAYCONFIG_PATH_INFO &array,uint &mode_info_array_elements,DISPLAYCONFIG_MODE_INFO &info_array[],DISPLAYCONFIG_TOPOLOGY_ID &topology_id); -HANDLE RealChildWindowFromPoint(HANDLE parent,long parent_client_coords); -uint RealGetWindowClassW(HANDLE hwnd,ushort &class_name[],uint class_name_max); -int RedrawWindow(HANDLE wnd,RECT &rect,HANDLE update,uint flags); -ushort RegisterClassExW(const WNDCLASSEXW &lpwcx); -ushort RegisterClassW(const WNDCLASSW &wnd_class); -uint RegisterClipboardFormatW(const string format); -PVOID RegisterDeviceNotificationW(HANDLE recipient,PVOID NotificationFilter,uint Flags); -int RegisterHotKey(HANDLE wnd,int id,uint modifiers,uint vk); -int RegisterPointerDeviceNotifications(HANDLE window,int range); -int RegisterPointerInputTarget(HANDLE hwnd,uint type); -int RegisterPointerInputTargetEx(HANDLE hwnd,uint type,int observe); -PVOID RegisterPowerSettingNotification(HANDLE recipient,const GUID &PowerSettingGuid,uint Flags); -int RegisterRawInputDevices(const RAWINPUTDEVICE &raw_input_devices[],uint num_devices,uint size); -int RegisterShellHookWindow(HANDLE hwnd); -PVOID RegisterSuspendResumeNotification(HANDLE recipient,uint Flags); -int RegisterTouchHitTestingWindow(HANDLE hwnd,uint value); -int RegisterTouchWindow(HANDLE hwnd,uint flags); -uint RegisterWindowMessageW(const string str); -int ReleaseCapture(void); -int ReleaseDC(HANDLE wnd,HANDLE hDC); -int RemoveClipboardFormatListener(HANDLE hwnd); -int RemoveMenu(HANDLE menu,uint position,uint flags); -HANDLE RemovePropW(HANDLE wnd,const string str); -int ReplyMessage(PVOID result); -int ScreenToClient(HANDLE wnd,POINT &point); -int ScrollDC(HANDLE hDC,int dx,int dy,RECT &scroll,RECT &clip,HANDLE update,RECT &update); -int ScrollWindow(HANDLE wnd,int XAmount,int YAmount,RECT &rect,RECT &clip_rect); -int ScrollWindowEx(HANDLE wnd,int dx,int dy,RECT &scroll,RECT &clip,HANDLE update,RECT &update,uint flags); -PVOID SendDlgItemMessageW(HANDLE dlg,int nIDDlgItem,uint Msg,PVOID param,PVOID param); -uint SendInput(uint inputs,INPUT &inputs[],int size); -int SendMessageCallbackW(HANDLE wnd,uint Msg,PVOID param,PVOID param,PVOID result_call_back,ulong data); -PVOID SendMessageTimeoutW(HANDLE wnd,uint Msg,PVOID param,PVOID param,uint flags,uint timeout,PVOID result); -PVOID SendMessageW(HANDLE wnd,uint Msg,PVOID param,PVOID param); -int SendNotifyMessageW(HANDLE wnd,uint Msg,PVOID param,PVOID param); -HANDLE SetActiveWindow(HANDLE wnd); -HANDLE SetCapture(HANDLE wnd); -int SetCaretBlinkTime(uint uMSeconds); -int SetCaretPos(int X,int Y); -ulong SetClassLongPtrW(HANDLE wnd,int index,long new_long); -uint SetClassLongW(HANDLE wnd,int index,int new_long); -ushort SetClassWord(HANDLE wnd,int index,ushort new_word); -HANDLE SetClipboardData(uint format,HANDLE mem); -HANDLE SetClipboardViewer(HANDLE wnd_new_viewer); -ulong SetCoalescableTimer(HANDLE wnd,ulong nIDEvent,uint elapse,PVOID timer_func,uint tolerance_delay); -HANDLE SetCursor(HANDLE cursor); -int SetCursorPos(int X,int Y); -void SetDebugErrorLevel(uint level); -int SetDialogControlDpiChangeBehavior(HANDLE wnd,DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS mask,DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS values); -int SetDialogDpiChangeBehavior(HANDLE dlg,DIALOG_DPI_CHANGE_BEHAVIORS mask,DIALOG_DPI_CHANGE_BEHAVIORS values); -int SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE orientation); -int SetDisplayConfig(uint path_array_elements,DISPLAYCONFIG_PATH_INFO &array,uint mode_info_array_elements,DISPLAYCONFIG_MODE_INFO &info_array[],uint flags); -int SetDlgItemInt(HANDLE dlg,int nIDDlgItem,uint value,int signed); -int SetDlgItemTextW(HANDLE dlg,int nIDDlgItem,const string str); -int SetDoubleClickTime(uint); -HANDLE SetFocus(HANDLE wnd); -int SetForegroundWindow(HANDLE wnd); -int SetGestureConfig(HANDLE hwnd,uint reserved,uint cIDs,GESTURECONFIG &gesture_config[],uint size); -int SetKeyboardState(uchar &key_state[]); -void SetLastErrorEx(uint err_code,uint type); -int SetLayeredWindowAttributes(HANDLE hwnd,uint key,uchar alpha,uint flags); -int SetMenu(HANDLE wnd,HANDLE menu); -int SetMenuContextHelpId(HANDLE,uint); -int SetMenuDefaultItem(HANDLE menu,uint item,uint by_pos); -int SetMenuInfo(HANDLE,const MENUINFO &); -int SetMenuItemBitmaps(HANDLE menu,uint position,uint flags,HANDLE bitmap_unchecked,HANDLE bitmap_checked); -int SetMenuItemInfoW(HANDLE hmenu,uint item,int by_positon,const MENUITEMINFOW &lpmii); -PVOID SetMessageExtraInfo(PVOID param); -int SetMessageQueue(int messages_max); -HANDLE SetParent(HANDLE wnd_child,HANDLE wnd_new_parent); -int SetPhysicalCursorPos(int X,int Y); -int SetProcessDefaultLayout(uint default_layout); -int SetProcessDPIAware(void); -int SetProcessDpiAwarenessContext(HANDLE value); -int SetProcessRestrictionExemption(int enable_exemption); -int SetProcessWindowStation(HANDLE win_sta); -int SetPropW(HANDLE wnd,const string str,HANDLE data); -int SetRect(RECT &lprc,int left,int top,int right,int bottom); -int SetRectEmpty(RECT &lprc); -int SetScrollInfo(HANDLE hwnd,int bar,const SCROLLINFO &lpsi,int redraw); -int SetScrollPos(HANDLE wnd,int bar,int pos,int redraw); -int SetScrollRange(HANDLE wnd,int bar,int min_pos,int max_pos,int redraw); -int SetSysColors(int elements_count,int &elements[],uint &rgb_values[]); -int SetSystemCursor(HANDLE hcur,uint id); -int SetThreadDesktop(HANDLE desktop); -HANDLE SetThreadDpiAwarenessContext(HANDLE context); -DPI_HOSTING_BEHAVIOR SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR value); -ulong SetTimer(HANDLE wnd,ulong nIDEvent,uint elapse,PVOID timer_func); -int SetUserObjectInformationW(HANDLE obj,int index,PVOID info,uint length); -int SetUserObjectSecurity(HANDLE obj,uint pSIRequested,SECURITY_DESCRIPTOR &pSID); -int SetWindowContextHelpId(HANDLE,uint); -int SetWindowDisplayAffinity(HANDLE wnd,uint affinity); -int SetWindowFeedbackSetting(HANDLE hwnd,FEEDBACK_TYPE feedback,uint flags,uint size,PVOID configuration); -long SetWindowLongPtrW(HANDLE wnd,int index,long new_long); -int SetWindowLongW(HANDLE wnd,int index,int new_long); -int SetWindowPlacement(HANDLE wnd,WINDOWPLACEMENT &lpwndpl); -int SetWindowPos(HANDLE wnd,HANDLE wnd_insert_after,int X,int Y,int cx,int cy,uint flags); -int SetWindowRgn(HANDLE wnd,HANDLE rgn,int redraw); -HANDLE SetWindowsHookExW(int hook,PVOID lpfn,HANDLE hmod,uint thread_id); -HANDLE SetWindowsHookW(int filter_type,PVOID filter_proc); -int SetWindowTextW(HANDLE wnd,const string str); -ushort SetWindowWord(HANDLE wnd,int index,ushort &new_word); -HANDLE SetWinEventHook(uint min,uint max,HANDLE win_event_proc,PVOID win_event_proc,uint process,uint thread,uint flags); -int ShowCaret(HANDLE wnd); -int ShowCursor(int show); -int ShowOwnedPopups(HANDLE wnd,int show); -int ShowScrollBar(HANDLE wnd,int bar,int show); -int ShowWindow(HANDLE wnd,int cmd_show); -int ShowWindowAsync(HANDLE wnd,int cmd_show); -int ShutdownBlockReasonCreate(HANDLE wnd,const string reason); -int ShutdownBlockReasonDestroy(HANDLE wnd); -int ShutdownBlockReasonQuery(HANDLE wnd,string buff,uint &buff[]); -int SkipPointerFrameMessages(uint id); -int SoundSentry(void); -int SubtractRect(RECT &dst,RECT &src1,RECT &src2); -int SwapMouseButton(int swap); -int SwitchDesktop(HANDLE desktop); -void SwitchToThisWindow(HANDLE hwnd,int unknown); -int SystemParametersInfoForDpi(uint action,uint param,PVOID param,uint win_ini,uint dpi); -int SystemParametersInfoW(uint action,uint param,PVOID param,uint win_ini); -int TabbedTextOutW(HANDLE hdc,int x,int y,const string str,int count,int tab_positions,const int &tab_stop_positions[],int tab_origin); -ushort TileWindows(HANDLE parent,uint how,const RECT &rect,uint kids,const HANDLE &kids[]); -int ToAscii(uint virt_key,uint scan_code,const uchar &key_state[],ushort &symbol,uint flags); -int ToAsciiEx(uint virt_key,uint scan_code,const uchar &key_state[],ushort &symbol,uint flags,HANDLE dwhkl); -int ToUnicode(uint virt_key,uint scan_code,const uchar &key_state[],ushort &buff[],int buff_size,uint flags); -int ToUnicodeEx(uint virt_key,uint scan_code,const uchar &key_state[],ushort &buff[],int buff_size,uint flags,HANDLE dwhkl); -int TrackMouseEvent(TRACKMOUSEEVENT &event_track); -int TrackPopupMenu(HANDLE menu,uint flags,int x,int y,int reserved,HANDLE wnd,RECT &rect); -int TrackPopupMenuEx(HANDLE menu,uint flags,int x,int y,HANDLE hwnd,TPMPARAMS &lptpm); -int TranslateAcceleratorW(HANDLE wnd,HANDLE acc_table,MSG &msg); -int TranslateMDISysAccel(HANDLE wnd_client,MSG &msg); -int TranslateMessage(MSG &msg); -int UnhookWindowsHook(int code,PVOID filter_proc); -int UnhookWindowsHookEx(HANDLE hhk); -int UnhookWinEvent(HANDLE win_event_hook); -int UnionRect(RECT &dst,RECT &src1,RECT &src2); -int UnloadKeyboardLayout(HANDLE hkl); -int UnregisterClassW(const PVOID class_name,HANDLE instance); -int UnregisterClassW(const string class_name,HANDLE instance); -int UnregisterDeviceNotification(PVOID Handle); -int UnregisterHotKey(HANDLE wnd,int id); -int UnregisterPointerInputTarget(HANDLE hwnd,uint type); -int UnregisterPointerInputTargetEx(HANDLE hwnd,uint type); -int UnregisterPowerSettingNotification(PVOID Handle); -int UnregisterSuspendResumeNotification(PVOID Handle); -int UnregisterTouchWindow(HANDLE hwnd); -int UpdateLayeredWindow(HANDLE wnd,HANDLE dst,POINT &dst,SIZE &psize,HANDLE src,POINT &src,uint key,BLENDFUNCTION &pblend,uint flags); -int UpdateLayeredWindowIndirect(HANDLE wnd,const UPDATELAYEREDWINDOWINFO &pULWInfo[]); -int UpdateWindow(HANDLE wnd); -int UserHandleGrantAccess(HANDLE user_handle,HANDLE job,int grant); -int ValidateRect(HANDLE wnd,RECT &rect); -int ValidateRgn(HANDLE wnd,HANDLE rgn); -short VkKeyScanExW(ushort ch,HANDLE dwhkl); -short VkKeyScanW(ushort ch); -uint WaitForInputIdle(HANDLE process,uint milliseconds); -int WaitMessage(void); -HANDLE WindowFromDC(HANDLE hDC); -HANDLE WindowFromPhysicalPoint(long point); -HANDLE WindowFromPoint(long point); -int WinHelpW(HANDLE wnd_main,const string help,uint command,ulong data); -int wvsprintfW(ushort &[],const string,PVOID &arglist[]); -#import -//+------------------------------------------------------------------+ diff --git a/Include/logger.mqh b/Include/logger.mqh deleted file mode 100644 index 1868d2a36c31886b971ff7bd8390f62b708dbcf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25540 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 diff --git a/Include/stderror.mqh b/Include/stderror.mqh deleted file mode 100644 index daa4877..0000000 --- a/Include/stderror.mqh +++ /dev/null @@ -1,99 +0,0 @@ -//+------------------------------------------------------------------+ -//| stderror.mqh | -//| Copyright © 2004-2007, MetaQuotes Software Corp. | -//| http://www.metaquotes.net/ | -//+------------------------------------------------------------------+ -//---- errors returned from trade server -#define ERR_NO_ERROR 0 -#define ERR_NO_RESULT 1 -#define ERR_COMMON_ERROR 2 -#define ERR_INVALID_TRADE_PARAMETERS 3 -#define ERR_SERVER_BUSY 4 -#define ERR_OLD_VERSION 5 -#define ERR_NO_CONNECTION 6 -#define ERR_NOT_ENOUGH_RIGHTS 7 -#define ERR_TOO_FREQUENT_REQUESTS 8 -#define ERR_MALFUNCTIONAL_TRADE 9 -#define ERR_ACCOUNT_DISABLED 64 -#define ERR_INVALID_ACCOUNT 65 -#define ERR_TRADE_TIMEOUT 128 -#define ERR_INVALID_PRICE 129 -#define ERR_INVALID_STOPS 130 -#define ERR_INVALID_TRADE_VOLUME 131 -#define ERR_MARKET_CLOSED 132 -#define ERR_TRADE_DISABLED 133 -#define ERR_NOT_ENOUGH_MONEY 134 -#define ERR_PRICE_CHANGED 135 -#define ERR_OFF_QUOTES 136 -#define ERR_BROKER_BUSY 137 -#define ERR_REQUOTE 138 -#define ERR_ORDER_LOCKED 139 -#define ERR_LONG_POSITIONS_ONLY_ALLOWED 140 -#define ERR_TOO_MANY_REQUESTS 141 -#define ERR_TRADE_MODIFY_DENIED 145 -#define ERR_TRADE_CONTEXT_BUSY 146 -#define ERR_TRADE_EXPIRATION_DENIED 147 -#define ERR_TRADE_TOO_MANY_ORDERS 148 -//---- mql4 run time errors -#define ERR_NO_MQLERROR 4000 -#define ERR_WRONG_FUNCTION_POINTER 4001 -#define ERR_ARRAY_INDEX_OUT_OF_RANGE 4002 -#define ERR_NO_MEMORY_FOR_CALL_STACK 4003 -#define ERR_RECURSIVE_STACK_OVERFLOW 4004 -#define ERR_NOT_ENOUGH_STACK_FOR_PARAM 4005 -#define ERR_NO_MEMORY_FOR_PARAM_STRING 4006 -#define ERR_NO_MEMORY_FOR_TEMP_STRING 4007 -#define ERR_NOT_INITIALIZED_STRING 4008 -#define ERR_NOT_INITIALIZED_ARRAYSTRING 4009 -#define ERR_NO_MEMORY_FOR_ARRAYSTRING 4010 -#define ERR_TOO_LONG_STRING 4011 -#define ERR_REMAINDER_FROM_ZERO_DIVIDE 4012 -#define ERR_ZERO_DIVIDE 4013 -#define ERR_UNKNOWN_COMMAND 4014 -#define ERR_WRONG_JUMP 4015 -#define ERR_NOT_INITIALIZED_ARRAY 4016 -#define ERR_DLL_CALLS_NOT_ALLOWED 4017 -#define ERR_CANNOT_LOAD_LIBRARY 4018 -#define ERR_CANNOT_CALL_FUNCTION 4019 -#define ERR_EXTERNAL_CALLS_NOT_ALLOWED 4020 -#define ERR_NO_MEMORY_FOR_RETURNED_STR 4021 -#define ERR_SYSTEM_BUSY 4022 -#define ERR_INVALID_FUNCTION_PARAMSCNT 4050 -#define ERR_INVALID_FUNCTION_PARAMVALUE 4051 -#define ERR_STRING_FUNCTION_INTERNAL 4052 -#define ERR_SOME_ARRAY_ERROR 4053 -#define ERR_INCORRECT_SERIESARRAY_USING 4054 -#define ERR_CUSTOM_INDICATOR_ERROR 4055 -#define ERR_INCOMPATIBLE_ARRAYS 4056 -#define ERR_GLOBAL_VARIABLES_PROCESSING 4057 -#define ERR_GLOBAL_VARIABLE_NOT_FOUND 4058 -#define ERR_FUNC_NOT_ALLOWED_IN_TESTING 4059 -#define ERR_FUNCTION_NOT_CONFIRMED 4060 -#define ERR_SEND_MAIL_ERROR 4061 -#define ERR_STRING_PARAMETER_EXPECTED 4062 -#define ERR_INTEGER_PARAMETER_EXPECTED 4063 -#define ERR_DOUBLE_PARAMETER_EXPECTED 4064 -#define ERR_ARRAY_AS_PARAMETER_EXPECTED 4065 -#define ERR_HISTORY_WILL_UPDATED 4066 -#define ERR_TRADE_ERROR 4067 -#define ERR_END_OF_FILE 4099 -#define ERR_SOME_FILE_ERROR 4100 -#define ERR_WRONG_FILE_NAME 4101 -#define ERR_TOO_MANY_OPENED_FILES 4102 -#define ERR_CANNOT_OPEN_FILE 4103 -#define ERR_INCOMPATIBLE_FILEACCESS 4104 -#define ERR_NO_ORDER_SELECTED 4105 -#define ERR_UNKNOWN_SYMBOL 4106 -#define ERR_INVALID_PRICE_PARAM 4107 -#define ERR_INVALID_TICKET 4108 -#define ERR_TRADE_NOT_ALLOWED 4109 -#define ERR_LONGS_NOT_ALLOWED 4110 -#define ERR_SHORTS_NOT_ALLOWED 4111 -#define ERR_OBJECT_ALREADY_EXISTS 4200 -#define ERR_UNKNOWN_OBJECT_PROPERTY 4201 -#define ERR_OBJECT_DOES_NOT_EXIST 4202 -#define ERR_UNKNOWN_OBJECT_TYPE 4203 -#define ERR_NO_OBJECT_NAME 4204 -#define ERR_OBJECT_COORDINATES_ERROR 4205 -#define ERR_NO_SPECIFIED_SUBWINDOW 4206 -#define ERR_SOME_OBJECT_ERROR 4207