1 #Region "Microsoft.VisualBasic::4e3de488c27d37d9d84f4fc815ad6396, 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, (+2 OverloadsToString, TryParse
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         ''' 
146         <MethodImpl(MethodImplOptions.AggressiveInlining)>
147         Public Overrides Function ToString() As String
148             Return ToString("G2")
149         End Function
150
151         Public Overloads Function ToString(format As StringAs String
152             Return $"[min={Min.ToString(format)}, max={Max.ToString(format)}]"
153         End Function
154
155         ''' <summary>
156         ''' Check if the specified value is inside this range
157         ''' </summary>
158         ''' 
159         ''' <param name="x">Value to check</param>
160         ''' 
161         ''' <returns><b>True</b> if the specified value is inside this range or
162         ''' <b>false</b> otherwise.</returns>
163         ''' 
164         Public Function IsInside(x As DoubleAs Boolean Implements IRanges(Of Double).IsInside
165             Return ((x >= Min) AndAlso (x <= Max))
166         End Function
167
168         ''' <summary>
169         ''' Check if the specified <paramref name="range"/> is inside this range.
170         ''' (如果函数参数<paramref name="range"/>在当前的这个range之中,则返回真)
171         ''' </summary>
172         ''' <param name="range">Range to check</param>
173         ''' <returns>
174         ''' + <b>True</b> if the specified input <paramref name="range"/> parameter is inside this range or
175         ''' + <b>false</b> otherwise.</returns>
176         Public Function IsInside(range As DoubleRange) As Boolean
177             Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max)))
178         End Function
179
180         ''' <summary>
181         ''' Check if the specified range overlaps with this range
182         ''' </summary>
183         ''' 
184         ''' <param name="range">Range to check for overlapping</param>
185         ''' 
186         ''' <returns><b>True</b> if the specified range overlaps with this range or
187         ''' <b>false</b> otherwise.</returns>
188         ''' 
189         Public Function IsOverlapping(range As DoubleRange) As Boolean
190             Return ((IsInside(range.Min)) OrElse (IsInside(range.Max)))
191         End Function
192
193         Public Function IsInside(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsInside
194             Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max)))
195         End Function
196
197         Public Function IsOverlapping(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsOverlapping
198             Return ((IsInside(range.Min)) OrElse (IsInside(range.Max)))
199         End Function
200
201         <MethodImpl(MethodImplOptions.AggressiveInlining)>
202         Public Shared Widening Operator CType(exp As StringAs DoubleRange
203             Dim r As New DoubleRange
204             Call exp.Parser(r.Min, r.Max)
205             Return r
206         End Operator
207
208         <MethodImpl(MethodImplOptions.AggressiveInlining)>
209         Public Shared Widening Operator CType(data#()) As DoubleRange
210             With data
211                 Return New DoubleRange(min:= .Min, max:= .Max)
212             End With
213         End Operator
214
215         Public Shared Widening Operator CType(tuple As (min#, max#)) As DoubleRange
216             Return New DoubleRange(tuple.min, tuple.max)
217         End Operator
218
219         Public Shared Widening Operator CType(tuple As (min!, max!)) As DoubleRange
220             Return New DoubleRange(tuple.min, tuple.max)
221         End Operator
222
223         Public Shared Widening Operator CType(tuple As (min&, max&)) As DoubleRange
224             Return New DoubleRange(tuple.min, tuple.max)
225         End Operator
226
227         Public Shared Widening Operator CType(data As VectorShadows(Of Single)) As DoubleRange
228             Return data _
229                 .Select(Function(s) CDbl(s)) _
230                 .ToArray
231         End Operator
232
233         ''' <summary>
234         ''' Scale numeric range
235         ''' </summary>
236         ''' <param name="range"></param>
237         ''' <param name="factor#"></param>
238         ''' <returns></returns>
239         ''' 
240         <MethodImpl(MethodImplOptions.AggressiveInlining)>
241         Public Shared Operator *(range As DoubleRange, factor#) As DoubleRange
242             With range
243                 Dim delta = (.Length * factor - .Length) / 2
244                 Dim ar As Double() = {
245                     .Min - delta,
246                     .Max + delta
247                 }
248
249                 Return New DoubleRange(ar)
250             End With
251         End Operator
252
253         ''' <summary>
254         ''' 这个函数需要通过一个返回结果的元素个数参数来计算出step步长
255         ''' </summary>
256         ''' <param name="n%">所返回来的数组的元素的个数</param>
257         ''' <returns></returns>
258         Public Function Enumerate(n%) As Double()
259             If Length = 0 Then
260                 Return {}
261             Else
262                 Dim delta# = Length / n
263                 Dim out As New List(Of Double)
264
265                 For x As Double = Min To Max Step delta
266                     out += x
267                 Next
268
269                 Return out
270             End If
271         End Function
272
273         ''' <summary>
274         ''' Transform a numeric value in this <see cref="DoubleRange"/> into 
275         ''' target numeric range: ``<paramref name="valueRange"/>``.
276         ''' (将当前的范围内的一个实数映射到另外的一个范围内的实数区间之中)
277         ''' </summary>
278         ''' <param name="x#">A numeric value in this <see cref="DoubleRange"/></param>
279         ''' <param name="valueRange"></param>
280         ''' <returns></returns>
281         Public Function ScaleMapping(x#, valueRange As DoubleRange) As Double
282             Dim percent# = (x - Min) / Length
283             Dim value# = percent * valueRange.Length + valueRange.Min
284             Return value
285         End Function
286
287         Public Overridable Iterator Function GetEnumerator() As IEnumerator(Of DoubleImplements IEnumerable(Of Double).GetEnumerator
288             For Each x In Me.Enumerate(100)
289                 Yield x
290             Next
291         End Function
292
293         Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
294             Yield GetEnumerator()
295         End Function
296
297         Public Shared Operator =(range As DoubleRange, value#) As Boolean
298             If range Is Nothing AndAlso value = 0 Then
299                 ' 假若将doublerange看作为double类型的数值的话,则数值类型的Nothing值为0,
300                 ' 所以在这里将Nothing等价于右边的value 0
301                 Return True
302             Else
303                 Return range.Length = 0 AndAlso range.Min = value
304             End If
305         End Operator
306
307         Public Shared Operator <>(range As DoubleRange, value#) As Boolean
308             Return Not range = value
309         End Operator
310
311         Public Shared Function TryParse(expression As StringAs DoubleRange
312             If expression.StringEmpty Then
313                 Return Nothing
314             End If
315
316             Try
317                 Return expression
318             Catch ex As Exception
319                 Return Nothing
320             End Try
321         End Function
322     End Class
323 End Namespace