1 #Region "Microsoft.VisualBasic::ad2b4d859b45690e5b25f3e4e30da2c6, Microsoft.VisualBasic.Core\ComponentModel\Ranges\RangeModel\DoubleRange.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class DoubleRange
35     
36     '         Properties: Length, Max, Min
37     
38     '         Constructor: (+6 OverloadsSub New
39     '         FunctionEnumerate, GetEnumerator, IEnumerable_GetEnumerator, (+3 OverloadsIsInside, (+2 OverloadsIsOverlapping
40     '                   ScaleMapping, ToString
41     '         Operators: *, <>, =
42     
43     
44     ' /********************************************************************************/
45
46 #End Region
47
48 ' AForge Library
49 '
50 ' Copyright © Andrew Kirillov, 2006
51 ' andrew.kirillov@gmail.com
52 '
53
54 Imports System.Runtime.CompilerServices
55 Imports System.Xml.Serialization
56 Imports Microsoft.VisualBasic.Language
57 Imports Microsoft.VisualBasic.Language.Vectorization
58
59 Namespace ComponentModel.Ranges.Model
60
61     ''' <summary>
62     ''' Represents a double range with minimum and maximum values
63     ''' </summary>
64     Public Class DoubleRange : Implements IRanges(Of Double)
65         Implements IEnumerable(Of Double)
66
67         ''' <summary>
68         ''' Minimum value
69         ''' </summary>
70         ''' 
71         <XmlAttribute("min")>
72         Public Property Min As Double Implements IRanges(Of Double).Min
73
74         ''' <summary>
75         ''' Maximum value
76         ''' </summary>
77         '''   
78         <XmlAttribute("max")>
79         Public Property Max As Double Implements IRanges(Of Double).Max
80
81         ''' <summary>
82         ''' Length of the range (deffirence between maximum and minimum values)
83         ''' </summary>
84         ''' 
85         Public ReadOnly Property Length() As Double
86             <MethodImpl(MethodImplOptions.AggressiveInlining)>
87             Get
88                 Return Max - Min
89             End Get
90         End Property
91
92         ''' <summary>
93         ''' Initializes a new instance of the <see cref="DoubleRange"/> class
94         ''' </summary>
95         ''' 
96         ''' <param name="min">Minimum value of the range</param>
97         ''' <param name="max">Maximum value of the range</param>
98         Public Sub New(min#, max#)
99             Me.Min = min
100             Me.Max = max
101         End Sub
102
103         ''' <summary>
104         ''' 从一个任意的实数数组之中构建出一个实数区间范围
105         ''' </summary>
106         ''' <param name="data"></param>
107         Sub New(data As Double())
108             Call Me.New(data.Min, data.Max)
109         End Sub
110
111         ''' <summary>
112         ''' 从一个任意的实数向量之中构建出一个实数区间范围
113         ''' </summary>
114         ''' <param name="vector"></param>
115         Sub New(vector As IEnumerable(Of Double))
116             Call Me.New(data:=vector.ToArray)
117         End Sub
118
119         Sub New(range As IntRange)
120             Call Me.New(range.Min, range.Max)
121         End Sub
122
123         ''' <summary>
124         ''' Value copy
125         ''' </summary>
126         ''' <param name="range"></param>
127         Sub New(range As DoubleRange)
128             Call Me.New(range.Min, range.Max)
129         End Sub
130
131         ''' <summary>
132         ''' For xml serialization.
133         ''' </summary>
134         Sub New()
135         End Sub
136
137         ''' <summary>
138         ''' 
139         ''' </summary>
140         ''' <returns></returns>
141         ''' <remarks>
142         ''' 因为进行json序列化的话,因为这个实现了<see cref="IEnumerable(Of T)"/>接口,但是并没有实现Add方法,
143         ''' 所以会出错,这里取消使用json来生成<see cref="ToString"/>函数的结果
144         ''' </remarks>
145         Public Overrides Function ToString() As String
146             Return $"[min={Min}, max={Max}]"
147         End Function
148
149         ''' <summary>
150         ''' Check if the specified value is inside this range
151         ''' </summary>
152         ''' 
153         ''' <param name="x">Value to check</param>
154         ''' 
155         ''' <returns><b>True</b> if the specified value is inside this range or
156         ''' <b>false</b> otherwise.</returns>
157         ''' 
158         Public Function IsInside(x As DoubleAs Boolean Implements IRanges(Of Double).IsInside
159             Return ((x >= Min) AndAlso (x <= Max))
160         End Function
161
162         ''' <summary>
163         ''' Check if the specified <paramref name="range"/> is inside this range.
164         ''' (如果函数参数<paramref name="range"/>在当前的这个range之中,则返回真)
165         ''' </summary>
166         ''' <param name="range">Range to check</param>
167         ''' <returns>
168         ''' + <b>True</b> if the specified input <paramref name="range"/> parameter is inside this range or
169         ''' + <b>false</b> otherwise.</returns>
170         Public Function IsInside(range As DoubleRange) As Boolean
171             Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max)))
172         End Function
173
174         ''' <summary>
175         ''' Check if the specified range overlaps with this range
176         ''' </summary>
177         ''' 
178         ''' <param name="range">Range to check for overlapping</param>
179         ''' 
180         ''' <returns><b>True</b> if the specified range overlaps with this range or
181         ''' <b>false</b> otherwise.</returns>
182         ''' 
183         Public Function IsOverlapping(range As DoubleRange) As Boolean
184             Return ((IsInside(range.Min)) OrElse (IsInside(range.Max)))
185         End Function
186
187         Public Function IsInside(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsInside
188             Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max)))
189         End Function
190
191         Public Function IsOverlapping(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsOverlapping
192             Return ((IsInside(range.Min)) OrElse (IsInside(range.Max)))
193         End Function
194
195         <MethodImpl(MethodImplOptions.AggressiveInlining)>
196         Public Shared Widening Operator CType(exp As StringAs DoubleRange
197             Dim r As New DoubleRange
198             Call exp.Parser(r.Min, r.Max)
199             Return r
200         End Operator
201
202         <MethodImpl(MethodImplOptions.AggressiveInlining)>
203         Public Shared Widening Operator CType(data#()) As DoubleRange
204             With data
205                 Return New DoubleRange(min:= .Min, max:= .Max)
206             End With
207         End Operator
208
209         Public Shared Widening Operator CType(tuple As (min#, max#)) As DoubleRange
210             Return New DoubleRange(tuple.min, tuple.max)
211         End Operator
212
213         Public Shared Widening Operator CType(tuple As (min!, max!)) As DoubleRange
214             Return New DoubleRange(tuple.min, tuple.max)
215         End Operator
216
217         Public Shared Widening Operator CType(tuple As (min&, max&)) As DoubleRange
218             Return New DoubleRange(tuple.min, tuple.max)
219         End Operator
220
221         Public Shared Widening Operator CType(data As VectorShadows(Of Single)) As DoubleRange
222             Return data _
223                 .Select(Function(s) CDbl(s)) _
224                 .ToArray
225         End Operator
226
227         ''' <summary>
228         ''' Scale numeric range
229         ''' </summary>
230         ''' <param name="range"></param>
231         ''' <param name="factor#"></param>
232         ''' <returns></returns>
233         ''' 
234         <MethodImpl(MethodImplOptions.AggressiveInlining)>
235         Public Shared Operator *(range As DoubleRange, factor#) As DoubleRange
236             With range
237                 Dim delta = (.Length * factor - .Length) / 2
238                 Dim ar As Double() = {
239                     .Min - delta,
240                     .Max + delta
241                 }
242
243                 Return New DoubleRange(ar)
244             End With
245         End Operator
246
247         ''' <summary>
248         ''' 这个函数需要通过一个返回结果的元素个数参数来计算出step步长
249         ''' </summary>
250         ''' <param name="n%">所返回来的数组的元素的个数</param>
251         ''' <returns></returns>
252         Public Function Enumerate(n%) As Double()
253             If Length = 0 Then
254                 Return {}
255             Else
256                 Dim delta# = Length / n
257                 Dim out As New List(Of Double)
258
259                 For x As Double = Min To Max Step delta
260                     out += x
261                 Next
262
263                 Return out
264             End If
265         End Function
266
267         ''' <summary>
268         ''' Transform a numeric value in this <see cref="DoubleRange"/> into 
269         ''' target numeric range: ``<paramref name="valueRange"/>``.
270         ''' (将当前的范围内的一个实数映射到另外的一个范围内的实数区间之中)
271         ''' </summary>
272         ''' <param name="x#">A numeric value in this <see cref="DoubleRange"/></param>
273         ''' <param name="valueRange"></param>
274         ''' <returns></returns>
275         Public Function ScaleMapping(x#, valueRange As DoubleRange) As Double
276             Dim percent# = (x - Min) / Length
277             Dim value# = percent * valueRange.Length + valueRange.Min
278             Return value
279         End Function
280
281         Public Overridable Iterator Function GetEnumerator() As IEnumerator(Of DoubleImplements IEnumerable(Of Double).GetEnumerator
282             For Each x In Me.Enumerate(100)
283                 Yield x
284             Next
285         End Function
286
287         Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
288             Yield GetEnumerator()
289         End Function
290
291         Public Shared Operator =(range As DoubleRange, value#) As Boolean
292             If range Is Nothing AndAlso value = 0 Then
293                 ' 假若将doublerange看作为double类型的数值的话,则数值类型的Nothing值为0,
294                 ' 所以在这里将Nothing等价于右边的value 0
295                 Return True
296             Else
297                 Return range.Length = 0 AndAlso range.Min = value
298             End If
299         End Operator
300
301         Public Shared Operator <>(range As DoubleRange, value#) As Boolean
302             Return Not range = value
303         End Operator
304     End Class
305 End Namespace