-
Notifications
You must be signed in to change notification settings - Fork 0
/
Functions.cs
192 lines (154 loc) · 6.2 KB
/
Functions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
using ExcelDna.Integration;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Campagna.Functions
{
public static class Input
{
[ExcelFunction(Description = "Generates a triangular distribution with given minimum, most likely and max", IsVolatile = true, IsMacroType =true)]
public static object CampagnaInputTriangular(double min, double ml, double max)
{
double dblLowerRange = ml - min;
double dblHigherRange = max - ml;
double dblTotalRange = max - min;
double U;
double k;
if ((min > ml) | (max < ml))
return ExcelError.ExcelErrorNum;
if ((min == ml) & (ml == max))
return ml;
object caller = XlCall.Excel(XlCall.xlfCaller) as ExcelReference;
U = (double)GetRandomNumber(caller, Globals._currentIteration);
if (U <= (dblLowerRange / dblTotalRange))
k = min + Math.Sqrt(U * dblLowerRange * dblTotalRange);
else
k = max - Math.Sqrt((1 - U) * dblHigherRange * dblTotalRange);
return k;
}
[ExcelFunction(Description = "Generates a Bernoulli distribution with a given probability ", IsVolatile = true, IsMacroType =true)]
public static object CampagnaInputBernoulli(double probability)
{
double U;
if ((probability < 0) || (probability > 1))
return ExcelError.ExcelErrorNum;
else
{
U = Globals._rand.NextDouble();
if (U > probability)
return 0;
else
return 1;
}
}
public static object GetRandomNumber(object range, int k)
{
if (Globals._randomSeed == 0 || Globals._randomNumbers.Count==0)
{
return Globals._rand.NextDouble();
}
else
{
string address = (string)XlCall.Excel(XlCall.xlfReftext, range, true);
List<Slice> sliceList = Globals._randomNumbers.GetSliceList(address);
return sliceList[k - 1].Data;
}
}
}
public static class Output
{
[ComVisible(true)]
[ExcelFunction(Description = "Returns the percentile of the given distribution", IsMacroType = true)]
public static object CampagnaOutputPercentile([ExcelArgument(AllowReference = true)] object range, double percentile)
{
if (Globals._isSimulating == true)
return ExcelError.ExcelErrorGettingData;
if (Globals._sliceData.Count == 0)
return ExcelError.ExcelErrorValue;
try
{
string address = (string)XlCall.Excel(XlCall.xlfReftext, range, true);
List<Slice> sliceList = Globals._sliceData.GetSliceList(address);
sliceList.Sort();
int N = sliceList.Count;
double n = (N - 1) * percentile + 1;
if (n == 1d) return sliceList[0].Data;
else if (n == N) return sliceList[N - 1].Data;
else
{
int k = (int)n;
double d = n - k;
return sliceList[k - 1].Data + d * (sliceList[k].Data - sliceList[k - 1].Data);
}
}
catch (ArgumentNullException)
{
return ExcelError.ExcelErrorValue;
}
}
[ComVisible(true)]
[ExcelFunction(Description = "Returns the kth data slice of the distribution in order that they were sampled.", IsMacroType = true)]
public static object CampagnaOutputSingleSlice([ExcelArgument(AllowReference = true)] object range, int k)
{
if (Globals._isSimulating == true)
return ExcelError.ExcelErrorGettingData;
if (Globals._sliceData.Count == 0)
return ExcelError.ExcelErrorValue;
try
{
string address = (string)XlCall.Excel(XlCall.xlfReftext, range, true);
List<Slice> sliceList = Globals._sliceData.GetSliceList(address);
return sliceList[k - 1].Data;
}
catch (ArgumentNullException)
{
return ExcelError.ExcelErrorValue;
}
}
[ComVisible(true)]
[ExcelFunction(Description = "Calculates the arithmetic mean of the given distribution", IsMacroType = true)]
public static object CampagnaOutputMean([ExcelArgument(AllowReference = true)] object range)
{
if (Globals._isSimulating == true)
return ExcelError.ExcelErrorGettingData;
if (Globals._sliceData.Count == 0)
return ExcelError.ExcelErrorValue;
double total = 0;
try
{
string address = (string)XlCall.Excel(XlCall.xlfReftext, range, true);
List<Slice> sliceList = Globals._sliceData.GetSliceList(address);
foreach (Slice sliceDatum in sliceList)
{
total += sliceDatum.Data;
}
return total / sliceList.Count;
}
catch (ArgumentNullException)
{
return ExcelError.ExcelErrorValue;
}
}
[ComVisible(true)]
[ExcelFunction(Description = "Outputs various properties of the last analysis that has been run", IsVolatile = true)]
public static object CampagnaOutputProperties(int property)
{
switch (property)
{
case 1:
if (Globals._numberIterations != 0)
{
return Globals._numberIterations;
}
return ExcelError.ExcelErrorValue;
case 2:
if (Globals._start != DateTime.MinValue)
{
return Globals._start;
}
return Globals._start;
}
return ExcelError.ExcelErrorValue;
}
}
}