-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathNormalDistribution.cs
125 lines (113 loc) · 3.92 KB
/
NormalDistribution.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
// Copyright (c) 2020-2023 Vladimir Popov [email protected] https://github.com/ZorPastaman/Random-Generators
using System;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using UnityEngine;
namespace Zor.RandomGenerators.ContinuousDistributions
{
/// <summary>
/// Collection of methods that generate a random value using Normal distribution algorithms.
/// </summary>
/// <remarks>
/// Marsaglia polar method is used here.
/// </remarks>
public static class NormalDistribution
{
public const float DefaultMean = 0f;
public const float DefaultDeviation = 1f;
/// <summary>
/// Generates a random value using <see cref="UnityGeneratorStruct.DefaultInclusive"/> as an iid source.
/// </summary>
/// <returns>
/// Two generated values.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public static (float, float) Generate()
{
return Generate(UnityGeneratorStruct.DefaultInclusive);
}
/// <summary>
/// Generates a random value using <see cref="UnityGeneratorStruct.DefaultInclusive"/> as an iid source.
/// </summary>
/// <returns>
/// Two generated values.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public static (float, float) Generate(float mean, float deviation)
{
return Generate(UnityGeneratorStruct.DefaultInclusive, mean, deviation);
}
/// <summary>
/// Generates a random value using <paramref name="iidFunc"/> as an iid source.
/// </summary>
/// <param name="iidFunc">
/// Function that returns an independent and identically distributed random value in range [0, 1].
/// </param>
/// <returns>
/// Two generated values.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public static (float, float) Generate([NotNull] Func<float> iidFunc)
{
return Generate(new FuncGeneratorStruct(iidFunc));
}
/// <summary>
/// Generates a random value using <paramref name="iidFunc"/> as an iid source.
/// </summary>
/// <param name="iidFunc">
/// Function that returns an independent and identically distributed random value in range [0, 1].
/// </param>
/// <param name="mean"></param>
/// <param name="deviation"></param>
/// <returns>
/// Two generated values.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public static (float, float) Generate([NotNull] Func<float> iidFunc, float mean, float deviation)
{
return Generate(new FuncGeneratorStruct(iidFunc), mean, deviation);
}
/// <summary>
/// Generates a random value using <paramref name="iidGenerator"/> as an iid source.
/// </summary>
/// <param name="iidGenerator">
/// Random generator that returns an independent and identically distributed random value in range [0, 1].
/// </param>
/// <returns>
/// Two generated values.
/// </returns>
[Pure]
public static (float, float) Generate<T>([NotNull] T iidGenerator) where T : IContinuousGenerator
{
float u, v, s;
do
{
u = iidGenerator.Generate() * 2f - 1f;
v = iidGenerator.Generate() * 2f - 1f;
s = u * u + v * v;
} while (s >= 1f | s < NumberConstants.NormalEpsilon);
s = Mathf.Sqrt(-2f * Mathf.Log(s) / s);
float z0 = u * s;
float z1 = v * s;
return (z0, z1);
}
/// <summary>
/// Generates a random value using <paramref name="iidGenerator"/> as an iid source.
/// </summary>
/// <param name="iidGenerator">
/// Random generator that returns an independent and identically distributed random value in range [0, 1].
/// </param>
/// <param name="mean"></param>
/// <param name="deviation"></param>
/// <returns>
/// Two generated values.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public static (float, float) Generate<T>([NotNull] T iidGenerator, float mean, float deviation)
where T : IContinuousGenerator
{
(float z0, float z1) = Generate(iidGenerator);
return (z0 * deviation + mean, z1 * deviation + mean);
}
}
}