OSDN Git Service

MathExクラスの追加,誤差関数の実装(#23869)
[karinto/karinto.git] / Karinto / MathEx.cs
diff --git a/Karinto/MathEx.cs b/Karinto/MathEx.cs
new file mode 100755 (executable)
index 0000000..0453747
--- /dev/null
@@ -0,0 +1,231 @@
+/*\r
+ *     Karinto Library Project\r
+ *\r
+ *     This software is distributed under a zlib-style license.\r
+ *     See license.txt for more information.\r
+ */\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace Karinto\r
+{\r
+    public static class MathEx\r
+    {\r
+        #region fields\r
+        private static readonly Polynomial[] erfcTable = \r
+        {\r
+            new Polynomial( //[0]: 1 <= x < 2\r
+                4.7019003296642450457550391704e-1,\r
+                -5.4129916560282193120142282350e-4,\r
+                3.2466045488989207057247716494e-2,\r
+                -1.5551574967900995569013129661e-3,\r
+                1.2991371652846980287617056420e-3,\r
+                -1.2476738559919909068871115854e-4,\r
+                4.2164948133638407169423314936e-5,\r
+                -5.5944555649744218134732620248e-6,\r
+                1.2391258283306184550290288637e-6,\r
+                -1.8629332352031266041799875695e-7,\r
+                3.3508489330180889238527074083e-8,\r
+                -5.1453759994172323811411458769e-9,\r
+                8.2778054007509566713316121080e-10,\r
+                -1.2419584612081402943997565209e-10,\r
+                1.8628225410158766603724913483e-11,\r
+                -2.6916642541339090011279256698e-12,\r
+                3.8321798025710167662264220379e-13,\r
+                -5.2985573947392393836199793226e-14,\r
+                7.2214593891835651145391699616e-15,\r
+                -1.0552316968012789176241975783e-15,\r
+                1.3848365749828243613160210837e-16\r
+                ),\r
+            new Polynomial( //[1]: 2 <= x < 4\r
+                0.28246919208993532,//2.8246919208993525100243945507e-1,\r
+                1.0295429295263581287408466969e-4,\r
+                2.6352174925955979906965931429e-2,\r
+                -2.0840262584872572824603082922e-3,\r
+                1.6107317263933041407504226538e-3,\r
+                -2.6413257091217055241174636048e-4,\r
+                9.3720096524725604112989062675e-5,\r
+                -2.0394452777501772979594808178e-5,\r
+                5.4818843984699154429750547408e-6,\r
+                -1.2769242863171188612896799307e-6,\r
+                3.0855108190100308040276886416e-7,\r
+                -7.1110449954162265412516889674e-8,\r
+                1.6277854940656666077194365644e-8,\r
+                -3.6388350444865150940102551512e-9,\r
+                8.0125451384130244729739875906e-10,\r
+                -1.7333139256038089278659882792e-10,\r
+                3.6913251414732819339098560977e-11,\r
+                -7.7391112861863152629855204763e-12,\r
+                1.5985771117554783386097643078e-12,\r
+                -3.2558812235239520370430316160e-13,\r
+                6.5474397002885039401566856717e-14,\r
+                -1.2908539064863451579569117003e-14,\r
+                2.4663418649675516649805424542e-15,\r
+                -5.0102905606542145531985288605e-16,\r
+                1.1637629874200535139854357149e-16,\r
+                -1.7702372520803693617903759643e-17\r
+                ),\r
+            new Polynomial( //[2]: 4 <= x < 8\r
+                2.6609916698112647641230096605e-1,\r
+                1.0052997692961233689565319255e-1,\r
+                0.063819586227166714,//6.3819586227166696717161903119e-2,\r
+                1.6510111747337704484097091109e-2,\r
+                6.7745775475928297665975539362e-3,\r
+                1.2613799574673550665257600345e-3,\r
+                4.6314050254419785813179921962e-4,\r
+                5.4816124629655721757719475954e-5,\r
+                2.5069740734847835425277961803e-5,\r
+                7.6494811710229433994592919775e-7,\r
+                1.3069891449561428965827894398e-6,\r
+                -1.1211722505095090109921762128e-7,\r
+                7.7627072370605473720667209070e-8,\r
+                -1.5067764445724103557487307330e-8,\r
+                5.3921138750029687859330065848e-9,\r
+                -1.3591247804716958040748207366e-9,\r
+                4.0341965879492537779635899830e-10,\r
+                -1.0884398300756496354533131958e-10,\r
+                3.0363217123340332343882922235e-11,\r
+                -8.2439513886349055414081918841e-12,\r
+                2.2756305305902268859393373330e-12,\r
+                -6.1246789459726400033402401708e-13,\r
+                1.4333003386843162197015125496e-13,\r
+                -3.7815369812690037058307445308e-14,\r
+                1.7401564599128446023009328203e-14,\r
+                -4.5875278594765951588791904401e-15\r
+                ),\r
+            new Polynomial( //[3]: 8 <= x < 16\r
+                4.6854221014893762619745618301e-2,\r
+                -1.5511450952249084104775598329e-2,\r
+                5.1178905303441648577722059649e-3,\r
+                -1.6829798529769531049332840624e-3,\r
+                5.5160777130644620308102757353e-4,\r
+                -1.8020184996880086091090661904e-4,\r
+                5.8678514133519807272309470851e-5,\r
+                -1.9045977453678276537004114523e-5,\r
+                6.1623270905278656151589976968e-6,\r
+                -1.9875419915464967477768116933e-6,\r
+                6.3904356643246431611609250453e-7,\r
+                -2.0483278667408340516487849749e-7,\r
+                6.5453904816333940501972558207e-8,\r
+                -2.0852118199579889358624923805e-8,\r
+                6.6229050456699429842283832512e-9,\r
+                -2.0972627311983894339808366077e-9,\r
+                6.6237821648144864340143708663e-10,\r
+                -2.0853485442305791192334927397e-10,\r
+                6.5162153190849185531320932146e-11,\r
+                -2.0380108335416826794297357698e-11,\r
+                6.6463403803777970165860627602e-12,\r
+                -2.0777605497301746376639943675e-12,\r
+                4.6614566309518191650253075708e-13,\r
+                -1.4074713019480904125485292343e-13,\r
+                1.0831110710204089408511450325e-13,\r
+                -3.3906934201035073659517665140e-14\r
+                ),\r
+            new Polynomial( //[4]: 16 <= x < 28\r
+                2.8262089312268317148835811995e-2,\r
+                -5.4152623609484073274229170763e-3,\r
+                1.6241399412435775154107409724e-3,\r
+                -5.0744105591774430405597196162e-3,\r
+                -1.7616157737971578130497741968e-2,\r
+                2.3083427166129394399962687197e-2,\r
+                1.1164742403248709989628167597e-1,\r
+                -3.5273994341997794105095275190e-2,\r
+                -3.0869428535741202544195312887e-1,\r
+                -1.3020536214165453885942308553e-2,\r
+                4.3332671745834241123676787595e-1,\r
+                9.4385604975718760529994282754e-2,\r
+                -3.0238469418692319645741714650e-1,\r
+                -9.5995136295717931771565803096e-2,\r
+                8.3313274670729987166299100438e-2,\r
+                3.1593997744278794785645602547e-2\r
+                )\r
+        };\r
+        #endregion\r
+\r
+        #region public methods\r
+        public static double Erf(double x)\r
+        {\r
+            double a = Math.Abs(x);\r
+            if (a >= 1.0)\r
+            {\r
+                return 1.0 - Erfc(x);\r
+            }\r
+            double y;\r
+            double aa = a * a;\r
+            if (a < 0.0625)\r
+            {\r
+                double c1 = a * aa;\r
+                double c2 = c1 * aa;\r
+                double c3 = c2 * aa;\r
+                double c4 = c3 * aa;\r
+\r
+                double s1 = c1 * -315.0;// (3*5*7*9 / -3 / 1!);\r
+                double s2 = s1 * 0 + c2 * 189.0 / 2.0;// (3*5*7*9 / +5 / 2!)\r
+                double s3 = s2 * 0 + c3 * -45.0 / 2.0;// (3*5*7*9 / -7 / 3!)\r
+                double s4 = s3 * 0 + c4 * 35.0 / 8.0;// (3*5*7*9 / 9 / 4!)\r
+                y = a + (s1 + s2 + s3 + s4) / 945.0; //(3*5*7*9);\r
+            }\r
+            else\r
+            {\r
+                double c = a;\r
+                double s = 0;\r
+                double b = 1.0;\r
+                for (double i = -1.0; i > -20.0; i-=1.0)\r
+                {\r
+                    c *= aa / i;\r
+                    b += 2.0;\r
+                    s += c / b;\r
+                }\r
+                y = a + s;\r
+            }\r
+            y *= 1.1283791670955126;     // 2 / pi^0.5\r
+            return Math.Sign(x) > 0 ? y : -y;\r
+        }\r
+\r
+        public static double Erfc(double x)\r
+        {\r
+            double a = Math.Abs(x);\r
+            if (a < 1.0)\r
+            {\r
+                return 1.0 - Erf(x);\r
+            }\r
+            if (a > 27.226017111108501)\r
+            {\r
+                return x > 0 ? 0 : 2.0;\r
+            }\r
+            double y = 0.0;\r
+\r
+            if (a < 2.0)\r
+            {\r
+                y = Math.Exp(-1.1688327773406599 * a * a);\r
+                y *= erfcTable[0].GetValueAt(a + a - 3.0);\r
+            }\r
+            else if (a < 4.0)\r
+            {\r
+                decimal b = -1.05068636145441m * (decimal)a * (decimal)a;\r
+                y = Math.Exp((double)b);\r
+                y *= erfcTable[1].GetValueAt(a - 3.0);\r
+            }\r
+            else if (a < 8.0)\r
+            {\r
+                decimal b = -1.0292687483818601m * (decimal)a * (decimal)a;\r
+                y = Math.Exp((double)b);\r
+                y *= erfcTable[2].GetValueAt(a * 0.5 - 3);\r
+            }\r
+            else if (a < 16.0)\r
+            {\r
+                y = Math.Exp(-a * a);\r
+                y *= erfcTable[3].GetValueAt(a * 0.25 - 3);\r
+            }\r
+            else\r
+            {\r
+                y = Math.Exp(-a * a);\r
+                y *= erfcTable[4].GetValueAt(a * 0.125 - 3);\r
+            }\r
+            return x > 0 ? y : 2.0 - y;\r
+        }\r
+        #endregion\r
+    }\r
+}\r