Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Multiply.cs
1using System;
2using System.Collections.Generic;
3using System.Numerics;
4using System.Reflection;
5using System.Threading.Tasks;
12
14{
19 {
29 : base(Left, Right, Start, Length, Expression)
30 {
31 }
32
39 {
40 IElement Left = this.left.Evaluate(Variables);
41 IElement Right = this.right.Evaluate(Variables);
42
43 return EvaluateMultiplication(Left, Right, this);
44 }
45
51 public override async Task<IElement> EvaluateAsync(Variables Variables)
52 {
53 if (!this.isAsync)
54 return this.Evaluate(Variables);
55
56 IElement Left = await this.left.EvaluateAsync(Variables);
57 IElement Right = await this.right.EvaluateAsync(Variables);
58
59 return EvaluateMultiplication(Left, Right, this);
60 }
61
70 {
71 IElement Result;
72
73 if (Left is IRingElement LE && Right is IRingElement RE)
74 {
75 Result = LE.MultiplyRight(RE);
76 if (!(Result is null))
77 return Result;
78
79 Result = RE.MultiplyLeft(LE);
80 if (!(Result is null))
81 return Result;
82 }
83
84 if (Left.IsScalar)
85 {
86 if (Right.IsScalar)
87 {
88 ISet LeftSet = Left.AssociatedSet;
89 ISet RightSet = Right.AssociatedSet;
90
91 if (!LeftSet.Equals(RightSet))
92 {
93 if (Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet))
94 {
95 LE = Left as IRingElement;
96 RE = Right as IRingElement;
97 if (!(LE is null) && !(RE is null))
98 {
99 Result = LE.MultiplyRight(RE);
100 if (!(Result is null))
101 return Result;
102
103 Result = RE.MultiplyLeft(LE);
104 if (!(Result is null))
105 return Result;
106 }
107 }
108 }
109
110 Result = EvaluateNamedOperator("op_Multiply", Left, Right, Node);
111 if (!(Result is null))
112 return Result;
113
114 object LeftObj = Left.AssociatedObjectValue;
115
116 if (LeftObj is double D)
117 {
118 if (Right is GroupElement E)
119 return EvaluateScalarMultiplication(D, E, Node);
120 else
121 return EvaluateScalarMultiplication(D, Right, Node);
122 }
123 else if (LeftObj is BigInteger I)
124 {
125 if (Right is GroupElement E)
126 return EvaluateScalarMultiplication(I, E, Node);
127 else
128 return EvaluateScalarMultiplication(I, Right, Node);
129 }
130
131 object RightObj = Right.AssociatedObjectValue;
132
133 if (RightObj is double D2)
134 {
135 if (Left is GroupElement E2)
136 return EvaluateScalarMultiplication(D2, E2, Node);
137 else
138 return EvaluateScalarMultiplication(D2, Left, Node);
139 }
140 else if (RightObj is BigInteger I2)
141 {
142 if (Left is GroupElement E2)
143 return EvaluateScalarMultiplication(I2, E2, Node);
144 else
145 return EvaluateScalarMultiplication(I2, Left, Node);
146 }
147
148 throw new ScriptRuntimeException("Operands cannot be multiplied.", Node);
149 }
150 else
151 {
152 LinkedList<IElement> Elements = new LinkedList<IElement>();
153
154 foreach (IElement RightChild in Right.ChildElements)
155 Elements.AddLast(EvaluateMultiplication(Left, RightChild, Node));
156
157 return Right.Encapsulate(Elements, Node);
158 }
159 }
160 else
161 {
162 if (Right.IsScalar)
163 {
164 LinkedList<IElement> Elements = new LinkedList<IElement>();
165
166 foreach (IElement LeftChild in Left.ChildElements)
167 Elements.AddLast(EvaluateMultiplication(LeftChild, Right, Node));
168
169 return Left.Encapsulate(Elements, Node);
170 }
171 else
172 {
173 ICollection<IElement> LeftChildren = Left.ChildElements;
174 ICollection<IElement> RightChildren = Right.ChildElements;
175
176 if (LeftChildren.Count == RightChildren.Count)
177 {
178 LinkedList<IElement> Elements = new LinkedList<IElement>();
179 IEnumerator<IElement> eLeft = LeftChildren.GetEnumerator();
180 IEnumerator<IElement> eRight = RightChildren.GetEnumerator();
181
182 try
183 {
184 while (eLeft.MoveNext() && eRight.MoveNext())
185 Elements.AddLast(EvaluateMultiplication(eLeft.Current, eRight.Current, Node));
186 }
187 finally
188 {
189 eLeft.Dispose();
190 eRight.Dispose();
191 }
192
193 return Left.Encapsulate(Elements, Node);
194 }
195 else
196 {
197 LinkedList<IElement> LeftResult = new LinkedList<IElement>();
198
199 foreach (IElement LeftChild in LeftChildren)
200 {
201 LinkedList<IElement> RightResult = new LinkedList<IElement>();
202
203 foreach (IElement RightChild in RightChildren)
204 RightResult.AddLast(EvaluateMultiplication(LeftChild, RightChild, Node));
205
206 LeftResult.AddLast(Right.Encapsulate(RightResult, Node));
207 }
208
209 return Left.Encapsulate(LeftResult, Node);
210 }
211 }
212 }
213 }
214
223 {
224 bool Sign = N < 0;
225 if (Sign)
226 N = -N;
227
228 ISemiGroupElement Result = Element.AssociatedGroup.AdditiveIdentity;
230
231 while (N != 0)
232 {
233 if ((N & 1) != 0)
234 Result = Result.AddRight(Power);
235
236 N >>= 1;
237 Power = Power.AddRight(Power);
238 }
239
240 if (Sign)
241 return Negate(Result, Node);
242 else
243 return Result;
244 }
245
254 {
255 if (N != Math.Floor(N))
256 throw new ScriptRuntimeException("Only scalar multiplication of integers allowed.", Node);
257
258 if (N <= long.MaxValue && N >= long.MinValue)
259 return EvaluateScalarMultiplication((long)N, Element, Node);
260
261 bool Sign = N < 0;
262 if (Sign)
263 N = -N;
264
265 ISemiGroupElement Result = Element.AssociatedGroup.AdditiveIdentity;
267
268 while (N >= 1)
269 {
270 if (Math.IEEERemainder(N, 2) != 0)
271 {
272 Result = Result.AddRight(Power);
273 N -= 1;
274 }
275
276 N /= 2;
277 Power = Power.AddRight(Power);
278 }
279
280 if (Sign)
281 return Negate(Result, Node);
282 else
283 return Result;
284 }
285
294 {
295 bool Sign = N.Sign < 0;
296 if (Sign)
297 N = -N;
298
299 ISemiGroupElement Result = Element.AssociatedGroup.AdditiveIdentity;
301
302 while (!N.IsZero)
303 {
304 N = BigInteger.DivRem(N, two, out BigInteger Rem);
305 if (!Rem.IsZero)
306 Result = Result.AddRight(Power);
307
308 Power = Power.AddRight(Power);
309 }
310
311 if (Sign)
312 return Negate(Result, Node);
313 else
314 return Result;
315 }
316
325 {
326 bool Sign = N < 0;
327 if (Sign)
328 N = -N;
329
330 IElement Result = null;
332
333 while (N != 0)
334 {
335 if ((N & 1) != 0)
336 Result = Result is null ? Power : Add.EvaluateAddition(Result, Power, Node);
337
338 N >>= 1;
340 }
341
342 if (Result is null)
343 return GetZero(Element, Node);
344 else if (Sign)
345 return Negate(Result, Node);
346 else
347 return Result;
348 }
349
350 private static IElement Negate(IElement Element, ScriptNode Node)
351 {
353 return E.Negate();
354
355 object Value = Element.AssociatedObjectValue;
356 if (Value is null)
357 return Element;
358
359 Type T = Value.GetType();
360 MethodInfo MI = T.GetRuntimeMethod("Negate", Types.NoTypes);
361 if (!(MI is null))
362 return Expression.Encapsulate(MI.Invoke(Value, Types.NoParameters));
363
364 throw new ScriptRuntimeException("Not an abelian group element.", Node);
365 }
366
367 private static IElement GetZero(IElement Element, ScriptNode Node)
368 {
369 if (Element is IGroupElement E)
370 return E.AssociatedGroup.AdditiveIdentity;
371
372 object Value = Element.AssociatedObjectValue;
373 if (Value is null)
374 return Element;
375
376 Type T = Value.GetType();
377 PropertyInfo PI = T.GetRuntimeProperty("Zero");
378 if (!(PI is null))
379 return Expression.Encapsulate(PI.GetValue(Value));
380
381 FieldInfo FI = T.GetRuntimeField("Zero");
382 if (!(FI is null))
383 return Expression.Encapsulate(FI.GetValue(Value));
384
385 throw new ScriptRuntimeException("Zero not defined.", Node);
386 }
387
396 {
397 if (N != Math.Floor(N))
398 throw new ScriptRuntimeException("Only scalar multiplication of integers allowed.", Node);
399
400 if (N <= long.MaxValue && N >= long.MinValue)
401 return EvaluateScalarMultiplication((long)N, Element, Node);
402
403 bool Sign = N < 0;
404 if (Sign)
405 N = -N;
406
407 IElement Result = null;
409
410 while (N >= 1)
411 {
412 if (Math.IEEERemainder(N, 2) != 0)
413 {
414 Result = Result is null ? Power : Add.EvaluateAddition(Result, Power, Node);
415 N -= 1;
416 }
417
418 N /= 2;
420 }
421
422 if (Result is null)
423 return GetZero(Element, Node);
424 else if (Sign)
425 return Negate(Result, Node);
426 else
427 return Result;
428 }
429
438 {
439 bool Sign = N.Sign < 0;
440 if (Sign)
441 N = -N;
442
443 IElement Result = null;
445
446 while (!N.IsZero)
447 {
448 N = BigInteger.DivRem(N, two, out BigInteger Rem);
449 if (!Rem.IsZero)
450 Result = Result is null ? Power : Add.EvaluateAddition(Result, Power, Node);
451
453 }
454
455 if (Result is null)
456 return GetZero(Element, Node);
457 else if (Sign)
458 return Negate(Result, Node);
459 else
460 return Result;
461 }
462
463
464 private static readonly BigInteger two = new BigInteger(2);
465
466
473 public ScriptNode Differentiate(string VariableName, Variables Variables)
474 {
475 if (this.left is IDifferentiable Left &&
476 this.right is IDifferentiable Right)
477 {
478 int Start = this.Start;
479 int Len = this.Length;
481
482 return new Add(
483 new Multiply(
484 Left.Differentiate(VariableName, Variables),
485 this.right,
486 Start, Len, Expression),
487 new Multiply(
488 this.left,
489 Right.Differentiate(VariableName, Variables),
490 Start, Len, Expression),
491 Start, Len, Expression);
492 }
493 else
494 throw new ScriptRuntimeException("Factors not differentiable.", this);
495 }
496
497 }
498}
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:14
static Type[] NoTypes
Contains an empty array of types.
Definition: Types.cs:543
static object[] NoParameters
Contains an empty array of parameter values.
Definition: Types.cs:548
Base class for all types of elements.
Definition: Element.cs:13
abstract object AssociatedObjectValue
Associated object value.
Definition: Element.cs:46
Base class for all types of group elements.
Definition: GroupElement.cs:10
Class managing a script expression.
Definition: Expression.cs:39
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:4955
static bool UpgradeField(ref IElement E1, ref ISet Set1, ref IElement E2, ref ISet Set2)
Upgrades elements if necessary, to a common field extension, trying to make them compatible.
Definition: Expression.cs:5070
Base class for all binary operators.
ScriptNode right
Right operand.
ScriptNode left
Left operand.
static IElement EvaluateNamedOperator(string Name, IElement Left, IElement Right, ScriptNode Node)
Evaluates a named operator available in code-behind.
bool isAsync
If subtree is asynchroneous.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
Expression Expression
Expression of which the node is a part.
Definition: ScriptNode.cs:177
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
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 IElement EvaluateAddition(IElement Left, IElement Right, ScriptNode Node)
Adds two operands.
Definition: Add.cs:67
static IElement EvaluateMultiplication(IElement Left, IElement Right, ScriptNode Node)
Multiplies two operands.
Definition: Multiply.cs:69
static IElement EvaluateScalarMultiplication(BigInteger N, IGroupElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:293
static IElement EvaluateScalarMultiplication(double N, IElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:395
ScriptNode Differentiate(string VariableName, Variables Variables)
Differentiates a script node, if possible.
Definition: Multiply.cs:473
static IElement EvaluateScalarMultiplication(double N, IGroupElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:253
Multiply(ScriptNode Left, ScriptNode Right, int Start, int Length, Expression Expression)
Multiplication operator.
Definition: Multiply.cs:28
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: Multiply.cs:51
static IElement EvaluateScalarMultiplication(long N, IElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:324
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: Multiply.cs:38
static IElement EvaluateScalarMultiplication(long N, IGroupElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:222
static IElement EvaluateScalarMultiplication(BigInteger N, IElement Element, ScriptNode Node)
Performs a scalar multiplication.
Definition: Multiply.cs:437
Negate(ScriptNode Operand, int Start, int Length, Expression Expression)
Negation operator.
Definition: Negate.cs:21
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of abelian group elements.
Basic interface for all types of elements.
Definition: IElement.cs:20
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:33
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:49
IElement Encapsulate(ICollection< 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:41
Basic interface for all types of group elements.
Definition: IGroupElement.cs:9
Basic interface for all types of ring elements.
Definition: IRingElement.cs:10
Basic interface for all types of semigroup elements.
ISemiGroupElement AddRight(ISemiGroupElement Element)
Tries to add an element to the current element, from the right.
Basic interface for all types of sets.
Definition: ISet.cs:10
Base interface for lambda expressions.