Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FunctionMultiVariate.cs
1using System;
4using System.Threading.Tasks;
10
11namespace Waher.Script.Model
12{
16 public abstract class FunctionMultiVariate : Function
17 {
21 protected static readonly ArgumentType[] argumentTypes0 = Array.Empty<ArgumentType>();
22
26 protected static readonly ArgumentType[] argumentTypes1Normal = new ArgumentType[] { ArgumentType.Normal };
27
31 protected static readonly ArgumentType[] argumentTypes1Vector = new ArgumentType[] { ArgumentType.Vector };
32
36 protected static readonly ArgumentType[] argumentTypes1Matrix = new ArgumentType[] { ArgumentType.Matrix };
37
41 protected static readonly ArgumentType[] argumentTypes1Set = new ArgumentType[] { ArgumentType.Set };
42
46 protected static readonly ArgumentType[] argumentTypes2Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal };
47
51 protected static readonly ArgumentType[] argumentTypes3Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
52
56 protected static readonly ArgumentType[] argumentTypes4Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
57
61 protected static readonly ArgumentType[] argumentTypes5Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
62
66 protected static readonly ArgumentType[] argumentTypes6Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
67
71 protected static readonly ArgumentType[] argumentTypes7Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
72
76 protected static readonly ArgumentType[] argumentTypes8Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
77
81 protected static readonly ArgumentType[] argumentTypes9Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
82
86 protected static readonly ArgumentType[] argumentTypes1Scalar = new ArgumentType[] { ArgumentType.Scalar };
87
91 protected static readonly ArgumentType[] argumentTypes2Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar };
92
96 protected static readonly ArgumentType[] argumentTypes3Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
97
101 protected static readonly ArgumentType[] argumentTypes4Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
102
106 protected static readonly ArgumentType[] argumentTypes5Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
107
111 protected static readonly ArgumentType[] argumentTypes6Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
112
116 protected static readonly ArgumentType[] argumentTypes7Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
117
121 protected static readonly ArgumentType[] argumentTypes8Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
122
126 protected static readonly ArgumentType[] argumentTypes9Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
127
128
129 private readonly ScriptNode[] arguments;
130 private readonly ArgumentType[] argumentTypes;
131 private readonly bool allNormal;
132 private readonly int nrArguments;
133 private bool isAsync;
134
144 : base(Start, Length, Expression)
145 {
146 if (Arguments.Length != ArgumentTypes.Length)
147 throw new ArgumentException("Size of ArgumentTypes must match the size of Arguments.", nameof(ArgumentTypes));
148
149 this.arguments = Arguments;
150 this.arguments?.SetParent(this);
151
152 this.argumentTypes = ArgumentTypes;
153 this.nrArguments = this.arguments.Length;
154
155 this.allNormal = true;
156 foreach (ArgumentType Type in this.argumentTypes)
157 {
158 if (Type != ArgumentType.Normal)
159 {
160 this.allNormal = false;
161 break;
162 }
163 }
164
165 this.CalcIsAsync();
166 }
167
168 private void CalcIsAsync()
169 {
170 this.isAsync = false;
171
172 for (int i = 0; i < this.nrArguments; i++)
173 {
174 if (this.arguments[i]?.IsAsynchronous ?? false)
175 {
176 this.isAsync = true;
177 break;
178 }
179 }
180 }
181
185 public ScriptNode[] Arguments => this.arguments;
186
190 public ArgumentType[] ArgumentTypes => this.argumentTypes;
191
196 public override bool IsAsynchronous => this.isAsync;
197
204 {
205 IElement[] Arg = new IElement[this.nrArguments];
206 ScriptNode Node;
207 int i;
208
209 for (i = 0; i < this.nrArguments; i++)
210 {
211 Node = this.arguments[i];
212 if (Node is null)
213 Arg[i] = ObjectValue.Null;
214 else
215 Arg[i] = Node.Evaluate(Variables);
216 }
217
218 if (this.allNormal)
219 return this.Evaluate(Arg, Variables);
220 else
221 return this.EvaluateCanonicalExtension(Arg, Variables);
222 }
223
229 public override async Task<IElement> EvaluateAsync(Variables Variables)
230 {
231 if (!this.IsAsynchronous)
232 return this.Evaluate(Variables);
233
234 IElement[] Arg = new IElement[this.nrArguments];
235 ScriptNode Node;
236 int i;
237
238 for (i = 0; i < this.nrArguments; i++)
239 {
240 Node = this.arguments[i];
241 if (Node is null)
242 Arg[i] = ObjectValue.Null;
243 else
244 Arg[i] = await Node.EvaluateAsync(Variables);
245 }
246
247 if (this.allNormal)
248 return await this.EvaluateAsync(Arg, Variables);
249 else
250 return await this.EvaluateCanonicalExtensionAsync(Arg, Variables);
251 }
252
253 private IElement EvaluateCanonicalExtension(IElement[] Arguments, Variables Variables)
254 {
255 int i, j;
256
257 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
258
259 try
260 {
261 if (!(Encapsulation is null))
262 {
264 IElement[] Arguments2 = new IElement[this.nrArguments];
265
266 for (j = 0; j < Dimension; j++)
267 {
268 for (i = 0; i < this.nrArguments; i++)
269 {
270 if (e[i] is null || !e[i].MoveNext())
271 Arguments2[i] = Arguments[i];
272 else
273 Arguments2[i] = e[i].Current;
274 }
275
276 Result.Add(this.EvaluateCanonicalExtension(Arguments2, Variables));
277 }
278
279 return Encapsulation(Result, this);
280 }
281 else
282 return this.Evaluate(Arguments, Variables);
283 }
284 finally
285 {
286 for (i = 0, j = e?.Length ?? 0; i < j; i++)
287 e[i]?.Dispose();
288 }
289 }
290
291 private void Prepare(IElement[] Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e)
292 {
293 ICollection<IElement> ChildElements;
294 IElement Argument;
295 IMatrix M;
296 ISet S;
298 int i, j;
299
300 e = new IEnumerator<IElement>[this.nrArguments];
301 Encapsulation = null;
302 Dimension = -1;
303
304 for (i = 0; i < this.nrArguments; i++)
305 {
306 Argument = Arguments[i];
307
308 switch (this.argumentTypes[i])
309 {
310 case ArgumentType.Normal:
311 e[i] = null;
312 break;
313
314 case ArgumentType.Scalar:
315 if (Argument.IsScalar)
316 e[i] = null;
317 else
318 {
319 ChildElements = Argument.ChildElements;
320
321 if (Dimension < 0)
322 Dimension = ChildElements.Count;
323 else if (ChildElements.Count != Dimension)
325
326 e[i] = ChildElements.GetEnumerator();
327 if (Encapsulation is null)
328 Encapsulation = Argument.Encapsulate;
329 }
330 break;
331
332 case ArgumentType.Vector:
333 if (Argument is IVector)
334 e[i] = null;
335 else if (!((M = Argument as IMatrix) is null))
336 {
337 if (Dimension < 0)
338 Dimension = M.Rows;
339 else if (M.Rows != Dimension)
341
343
344 for (j = 0; j < Dimension; j++)
345 Vectors.Add(M.GetRow(j));
346
347 e[i] = Vectors.GetEnumerator();
348 if (Encapsulation is null)
349 Encapsulation = Operators.LambdaDefinition.EncapsulateToVector;
350 }
351 else if (!((S = Argument as ISet) is null))
352 {
353 int? Size = S.Size;
354 if (!Size.HasValue)
356
357 if (Dimension < 0)
358 Dimension = Size.Value;
359 else if (Size.Value != Dimension)
361
362 e[i] = S.ChildElements.GetEnumerator();
363 if (Encapsulation is null)
364 Encapsulation = Argument.Encapsulate;
365 }
366 else if (Argument.AssociatedObjectValue is IEnumerable Enumerable &&
367 !(Argument.AssociatedObjectValue is string) &&
368 !(Argument.AssociatedObjectValue is IDictionary<string, IElement>) &&
369 !(Argument.AssociatedObjectValue is IDictionary<string, object>))
370 {
371 Arguments[i] = Operators.Vectors.VectorDefinition.Encapsulate(Enumerable, false, this);
372 e[i] = null;
373 }
374 else
375 {
376 Arguments[i] = Operators.Vectors.VectorDefinition.Encapsulate(new IElement[] { Argument }, false, this);
377 e[i] = null;
378 }
379 break;
380
381 case ArgumentType.Set:
382 if (Argument is ISet)
383 e[i] = null;
384 else if (!((V = Argument as IVectorSpaceElement) is null))
385 {
386 Arguments[i] = Operators.Sets.SetDefinition.Encapsulate(V.ChildElements);
387 e[i] = null;
388 }
389 else if (!((M = Argument as IMatrix) is null))
390 {
391 if (Dimension < 0)
392 Dimension = M.Rows;
393 else if (M.Rows != Dimension)
395
397
398 for (j = 0; j < Dimension; j++)
399 Vectors.Add(M.GetRow(j));
400
401 Arguments[i] = Argument = Operators.Sets.SetDefinition.Encapsulate(Vectors);
402 ChildElements = Argument.ChildElements;
403
404 e[i] = ChildElements.GetEnumerator();
405 if (Encapsulation is null)
406 Encapsulation = Operators.LambdaDefinition.EncapsulateToVector;
407 }
408 else if (Argument.AssociatedObjectValue is IEnumerable Enumerable &&
409 !(Argument.AssociatedObjectValue is string) &&
410 !(Argument.AssociatedObjectValue is IDictionary<string, IElement>) &&
411 !(Argument.AssociatedObjectValue is IDictionary<string, object>))
412 {
413 Arguments[i] = Operators.Sets.SetDefinition.Encapsulate(Enumerable);
414 e[i] = null;
415 }
416 else
417 {
418 Arguments[i] = Operators.Sets.SetDefinition.Encapsulate(new IElement[] { Argument });
419 e[i] = null;
420 }
421 break;
422
423 case ArgumentType.Matrix:
424 if (Argument is IMatrix)
425 e[i] = null;
426 else if (!((V = Argument as IVectorSpaceElement) is null))
427 {
428 Arguments[i] = Operators.Matrices.MatrixDefinition.Encapsulate(V.ChildElements, 1, V.Dimension, this);
429 e[i] = null;
430 }
431 else if (!((S = Argument as ISet) is null))
432 {
433 int? Size = S.Size;
434 if (!Size.HasValue)
436
437 if (Dimension < 0)
438 Dimension = Size.Value;
439 else if (Size.Value != Dimension)
441
442 e[i] = S.ChildElements.GetEnumerator();
443 if (Encapsulation is null)
444 Encapsulation = Argument.Encapsulate;
445 }
446 else
447 {
448 Arguments[i] = Operators.Matrices.MatrixDefinition.Encapsulate(new IElement[] { Argument }, 1, 1, this);
449 e[i] = null;
450 }
451 break;
452
453 default:
454 throw new ScriptRuntimeException("Unhandled argument type.", this);
455 }
456 }
457 }
458
459 private async Task<IElement> EvaluateCanonicalExtensionAsync(IElement[] Arguments, Variables Variables)
460 {
461 int i, j;
462
463 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
464
465 try
466 {
467 if (!(Encapsulation is null))
468 {
470 IElement[] Arguments2 = new IElement[this.nrArguments];
471
472 for (j = 0; j < Dimension; j++)
473 {
474 for (i = 0; i < this.nrArguments; i++)
475 {
476 if (e[i] is null || !e[i].MoveNext())
477 Arguments2[i] = Arguments[i];
478 else
479 Arguments2[i] = e[i].Current;
480 }
481
482 Result.Add(await this.EvaluateCanonicalExtensionAsync(Arguments2, Variables));
483 }
484
485 return Encapsulation(Result, this);
486 }
487 else
488 return await this.EvaluateAsync(Arguments, Variables);
489 }
490 finally
491 {
492 for (i = 0, j = e?.Length ?? 0; i < j; i++)
493 e[i]?.Dispose();
494 }
495 }
496
504
511 public virtual Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
512 {
513 return Task.FromResult(this.Evaluate(Arguments, Variables));
514 }
515
523 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
524 {
525 int i;
526
527 if (Order == SearchMethod.DepthFirst)
528 {
529 if (!this.arguments.ForAllChildNodes(Callback, State, Order))
530 return false;
531 }
532
533 ScriptNode Node;
534 bool RecalcIsAsync = false;
535
536 for (i = 0; i < this.nrArguments; i++)
537 {
538 Node = this.arguments[i];
539 if (!(Node is null))
540 {
541 bool b = !Callback(Node, out ScriptNode NewNode, State);
542 if (!(NewNode is null))
543 {
544 this.arguments[i] = NewNode;
545 NewNode.SetParent(this);
546 Node = NewNode;
547
548 RecalcIsAsync = true;
549 }
550
551 if (b || (Order == SearchMethod.TreeOrder && !Node.ForAllChildNodes(Callback, State, Order)))
552 {
553 if (RecalcIsAsync)
554 this.CalcIsAsync();
555
556 return false;
557 }
558 }
559 }
560
561 if (RecalcIsAsync)
562 this.CalcIsAsync();
563
564 if (Order == SearchMethod.BreadthFirst)
565 {
566 if (!this.arguments.ForAllChildNodes(Callback, State, Order))
567 return false;
568 }
569
570 return true;
571 }
572
574 public override bool Equals(object obj)
575 {
576 return obj is FunctionMultiVariate O &&
577 AreEqual(this.arguments, O.arguments) &&
578 AreEqual(this.argumentTypes, O.argumentTypes) &&
579 base.Equals(obj);
580 }
581
583 public override int GetHashCode()
584 {
585 int Result = base.GetHashCode();
586 Result ^= Result << 5 ^ GetHashCode(this.arguments);
587 Result ^= Result << 5 ^ GetHashCode(this.argumentTypes);
588 return Result;
589 }
590
591 }
592}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
IEnumerator< T > GetEnumerator()
Returns an enumerator for the collection.
Definition: ChunkedList.cs:418
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
Class managing a script expression.
Definition: Expression.cs:41
Base class for all funcions.
Definition: Function.cs:7
Base class for multivariate funcions.
static readonly ArgumentType[] argumentTypes3Normal
Three normal parameters.
static readonly ArgumentType[] argumentTypes5Scalar
Five scalar parameters.
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
static readonly ArgumentType[] argumentTypes4Normal
Four normal parameters.
static readonly ArgumentType[] argumentTypes1Matrix
One matrix parameter.
static readonly ArgumentType[] argumentTypes8Normal
Eight normal parameters.
static readonly ArgumentType[] argumentTypes2Normal
Two normal parameters.
ScriptNode[] Arguments
Function arguments.
FunctionMultiVariate(ScriptNode[] Arguments, ArgumentType[] ArgumentTypes, int Start, int Length, Expression Expression)
Base class for funcions of one variable.
static readonly ArgumentType[] argumentTypes2Scalar
Two scalar parameters.
static readonly ArgumentType[] argumentTypes0
Zero parameters.
static readonly ArgumentType[] argumentTypes7Normal
Seven normal parameters.
abstract IElement Evaluate(IElement[] Arguments, Variables Variables)
Evaluates the function.
static readonly ArgumentType[] argumentTypes1Normal
One scalar parameter.
static readonly ArgumentType[] argumentTypes9Normal
Nine normal parameters.
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
static readonly ArgumentType[] argumentTypes1Vector
One vector parameter.
static readonly ArgumentType[] argumentTypes3Scalar
Three scalar parameters.
static readonly ArgumentType[] argumentTypes7Scalar
Seven scalar parameters.
static readonly ArgumentType[] argumentTypes9Scalar
Nine scalar parameters.
static readonly ArgumentType[] argumentTypes8Scalar
Eight scalar parameters.
static readonly ArgumentType[] argumentTypes6Normal
Six normal parameters.
ArgumentType[] ArgumentTypes
Function argument types.
static readonly ArgumentType[] argumentTypes5Normal
Five normal parameters.
virtual Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
Evaluates the function.
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
static readonly ArgumentType[] argumentTypes1Scalar
One scalar parameter.
static readonly ArgumentType[] argumentTypes1Set
One set parameter.
static readonly ArgumentType[] argumentTypes6Scalar
Six scalar parameters.
static readonly ArgumentType[] argumentTypes4Scalar
Four scalar parameters.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all child nodes.
Definition: ScriptNode.cs:243
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
Definition: ScriptNode.cs:275
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
Definition: ScriptNode.cs:132
abstract IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Definition: ScriptNode.cs:158
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:88
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:50
IElement Encapsulate(ChunkedList< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
bool IsScalar
If the element represents a scalar value.
Definition: IElement.cs:42
Basic interface for matrices.
Definition: IMatrix.cs:7
IVector GetRow(int Row)
Gets a row vector from the matrix.
Basic interface for vectors.
Definition: IVector.cs:9
int Dimension
Dimension of vector.
Definition: IVector.cs:14
Basic interface for all types of module elements.
Basic interface for all types of sets.
Definition: ISet.cs:10
int? Size
Size of set, if finite and known, otherwise null is returned.
Definition: ISet.cs:22
delegate IElement Encapsulation(ICollection< IElement > Elements, ScriptNode Node)
Delegate for encapsulation methods.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
ArgumentType
Type of parameter used in a function definition or a lambda definition.
Definition: IFunction.cs:9
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38