/// <inheritdoc/>
        public override MathExpression ApplyTo(BinaryExpression expr, IOptimizationContext <ICommutativitySettings> ctx, out bool transformResult)
        {
            transformResult = true;
            var list = expr.Arguments.Select(e => ApplyTo(e, ctx)).ToList();

            if (!ctx.Settings.IgnoreCommutativityFor.Contains(expr.Type))
            {
                switch (expr.Type)
                {
                case ExpressionType.Add:
                case ExpressionType.Multiply:
                case ExpressionType.And:
                case ExpressionType.Or:

                    bool IsCombinableExpression(MathExpression e)
                    => e is BinaryExpression ex && ex.Type == expr.Type;

                    if (list.Any(IsCombinableExpression))
                    {
                        foreach (var ex in list.ToArray().Where(IsCombinableExpression).Cast <BinaryExpression>())
                        {
                            list.Remove(ex);
                            list.AddRange(ex.Arguments);
                        }
                    }
                    break;
                }
            }
            return(new BinaryExpression(expr.Type, list).WithToken(expr.Token));
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public override MathExpression ApplyTo(FunctionExpression expr, IOptimizationContext <IFunctionInlineSettings> ctx, out bool transformResult)
        {
            if (expr.IsUserDefined)
            {
                var definedFunctions = GetDefinedFunctions(ctx);

                if (definedFunctions.TryGetValue(expr.Name, out var tup) && expr.Arguments.Count == tup.func.ParameterList.Count)
                {
                    var variableSubs = GetVariableSubstitutions(ctx);
                    if (variableSubs.Count == 0)
                    { // only when we're not currently substituting
                        foreach (var(replace, with) in tup.func.ParameterList.Zip(expr.Arguments, Helpers.Tuple))
                        {
                            variableSubs.Add(replace, with);
                        }

                        var value = ApplyTo(tup.func.Definition, ctx);

                        variableSubs.Clear();

                        transformResult = false;     // because we have applied all transformations by definition with the following call
                        // this could very easily create dangerously deep callstacks
                        return(ApplyTo(value, ctx)); // handle nested calls
                    }
                }
            }

            return(base.ApplyTo(expr, ctx, out transformResult));
        }
Ejemplo n.º 3
0
        /// <inheritdoc/>
        public override MathExpression ApplyTo(VariableExpression expr, IOptimizationContext <IFunctionInlineSettings> ctx, out bool transformResult)
        {
            var variableSubs = GetVariableSubstitutions(ctx);

            transformResult = true;
            if (variableSubs.TryGetValue(expr, out var replaceWith))
            {
                return(replaceWith);
            }

            return(base.ApplyTo(expr, ctx, out transformResult));
        }
Ejemplo n.º 4
0
 /// <inheritdoc/>
 public override MathExpression ApplyTo(BinaryExpression expr, IOptimizationContext <IDomainRestrictionSettings> ctx, out bool transformResult)
 {
     switch (expr.Type)
     {
     case BinaryExpression.ExpressionType.Power:
         if (expr.Left is LiteralExpression l && l.Value == DecimalMath.E)
         {
             transformResult = false;     // because we will have already applied to our target
             //  transform into call to `exp` function, then apply to that
             return(ApplyTo(new FunctionExpression(BuiltinFunctionExp.ConstName, new[] { ApplyTo(expr.Right, ctx) }.ToList(), false).WithToken(expr.Token), ctx));
         }
         break;
     }
     return(base.ApplyTo(expr, ctx, out transformResult));
 }
        public IOptimizationContext AddOrGetContext(string name)
        {
            if (null == name)
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (this.Contexts.TryGetValue(name, out IOptimizationContext context))
            {
                return(context);
            }

            IOptimizationContext optimizationContext = ActivatorUtilities.CreateInstance <TContext>(this.ServiceProvider);

            this.Contexts.Add(name, optimizationContext);
            return(optimizationContext);
        }
Ejemplo n.º 6
0
 /// <inheritdoc/>
 public override MathExpression ApplyTo(FunctionExpression f, IOptimizationContext <IDomainRestrictionSettings> ctx, out bool transformResult)
 {
     if (!f.IsUserDefined && f.Name == BuiltinFunctionExp.ConstName)
     { // exp(x)
         if (f.Arguments.Count == 1)
         {
             var arg = f.Arguments.First();
             if (arg is FunctionExpression fn && !fn.IsUserDefined && fn.Name == BuiltinFunctionLn.ConstName)
             { // exp(ln(x))
                 if (fn.Arguments.Count == 1 && ctx.Settings.AllowDomainChangingOptimizations)
                 {
                     var ln = fn.Arguments.First();
                     var dr = GetDomainRestrictions(ctx);
                     dr.Add(new BinaryExpression(ln, new LiteralExpression(0), BinaryExpression.ExpressionType.LessEq));
                     transformResult = false;  //because we will have already applied to it
                     return(ApplyTo(ln, ctx)); // apply to the argument, transform to that
                 }
             }
         }
     }
     return(base.ApplyTo(f, ctx, out transformResult));
 }
Ejemplo n.º 7
0
        /// <inheritdoc/>
        public override MathExpression ApplyTo(CustomDefinitionExpression expr, IOptimizationContext <IFunctionInlineSettings> ctx, out bool transformResult)
        {
            if (ctx.Settings.ShouldInline && expr.DefinitionSize <= ctx.Settings.DoNotInlineAfterSize)
            {
                var definedFunctions = GetDefinedFunctions(ctx);

                definedFunctions.Add(expr.FunctionName, (expr, false));

                var value = ApplyTo(expr.Value, ctx);
                transformResult = false; // because the resulting value has already been fully transformed
                if (definedFunctions[expr.FunctionName].hasNotInlinedUses)
                {
                    return(new CustomDefinitionExpression(expr.FunctionName, expr.ParameterList, expr.Definition, value).WithToken(expr.Token));
                }
                else
                {
                    return(value);
                }
            }

            return(base.ApplyTo(expr, ctx, out transformResult));
        }
        /// <inheritdoc/>
        public override MathExpression ApplyTo(FunctionExpression expr, IOptimizationContext <object?> ctx, out bool transformResult)
        {
            if (!expr.IsUserDefined && (expr.Name == BuiltinFunctionExp.ConstName || expr.Name == BuiltinFunctionLn.ConstName))
            { // exp(x)
                if (expr.Arguments.Count == 1)
                {
                    var arg = ApplyTo(expr.Arguments.First(), ctx);
                    if (arg is LiteralExpression lit)
                    {
                        transformResult = true;
                        if (expr.Name == BuiltinFunctionExp.ConstName)
                        {
                            return(new LiteralExpression(DecimalMath.Exp(lit.Value)).WithToken(expr.Token));
                        }
                        if (expr.Name == BuiltinFunctionLn.ConstName)
                        {
                            return(new LiteralExpression(DecimalMath.Ln(lit.Value)).WithToken(expr.Token));
                        }
                    }
                }
            }

            return(base.ApplyTo(expr, ctx, out transformResult));
        }
Ejemplo n.º 9
0
        public async Task <OptimizationResult> OptimizeAsync(IOptimizationContext context, AssetFileExtension assetFileExtension)
        {
            if (null == assetFileExtension)
            {
                assetFileExtension = string.Empty;
            }

            if (!context.Assets.Any())
            {
                return(OptimizationResult.Empty);
            }

            var orderedAssets = this.Orderer.Order(context.Assets.Where(a => 0 == string.Compare(Path.GetExtension(a.Location.ToString()), assetFileExtension, StringComparison.OrdinalIgnoreCase)));

            foreach (var asset in orderedAssets)
            {
                bool isAssetLoaded = false;

                foreach (var loader in this.Loaders)
                {
                    if (loader.CanLoad(asset))
                    {
                        this.Logger.LogTrace($"Loading asset '{asset.Location}' using '{nameof(loader)}'.");
                        using (var stream = await loader.OpenReadStreamAsync(asset))
                        {
                            await asset.SetContentAsync(stream);

                            isAssetLoaded = true;
                        }
                        break;
                    }
                }

                if (!isAssetLoaded)
                {
                    throw new InvalidOperationException($"Couldn't find an asset loader to load the asset from '{asset.Location}'.");
                }
            }

            IEnumerable <Asset> assets = orderedAssets;

            foreach (var transformPair in this.TransformChains.Where(x => 0 == string.Compare(x.Key, assetFileExtension, StringComparison.OrdinalIgnoreCase)))
            {
                foreach (ITransform transform in transformPair.Value)
                {
                    if (null == this.Events?.TransformRunning || this.Events.TransformRunning.Invoke(assetFileExtension, this.Options, transform))
                    {
                        var inputAssets = assets.ToArray();
                        assets = await transform.TransformAsync(assetFileExtension, inputAssets);

                        await transform.CleanUpAsync(inputAssets);
                    }
                }
                break;
            }

            var optimizationResult = new OptimizationResult();
            await optimizationResult.InitializeAsync(assets);

            return(optimizationResult);
        }
        public DefaultOptimizationScope(IServiceProvider serviceProvider)
        {
            this.ServiceProvider = serviceProvider;

            this.DefaultContext = this.AddOrGetContext(Options.DefaultName);
        }
Ejemplo n.º 11
0
 /// <inheritdoc/>
 public override MathExpression ApplyTo(BinaryExpression expr, IOptimizationContext <object?> ctx, out bool transformResult)
 {
     transformResult = true;
     var list = expr.Arguments.Select(e => ApplyTo(e, ctx)).ToList();
Ejemplo n.º 12
0
 private Dictionary <VariableExpression, MathExpression> GetVariableSubstitutions(IOptimizationContext <IFunctionInlineSettings> ctx)
 => ctx.Data <Dictionary <VariableExpression, MathExpression> >().GetOrCreateIn(this);
Ejemplo n.º 13
0
 // name -> function info
 private Dictionary <string, (CustomDefinitionExpression func, bool hasNotInlinedUses)> GetDefinedFunctions(IOptimizationContext <IFunctionInlineSettings> ctx)
 => ctx.Data <Dictionary <string, (CustomDefinitionExpression func, bool hasNotInlinedUses)> >().GetOrCreateIn(ctx.Settings);