예제 #1
0
        public Msubsup(IBuildable[] contents)
        { // handle star superscript
            List <IBuildable> localCopy = new List <IBuildable>(contents);

            if (localCopy.Count == 3)
            {
                Mo mo = localCopy[2] as Mo;
                if (mo != null && mo.IsTimesOrStar)
                {
                    Mi subscript = localCopy[1] as Mi;
                    if (subscript != null)
                    {
                        subscript.Content += Semantics.StarPrefix;
                        localCopy.RemoveAt(2);
                    }
                    else
                    {
                        // maybe the subscript is an mrow
                        Mrow row = localCopy[1] as Mrow;
                        if (row != null && row.LastElement != null && row.LastElement is WithTextContent)
                        {
                            WithTextContent lastElem = (WithTextContent)row.LastElement;
                            lastElem.Content += Semantics.StarPrefix;
                            localCopy.RemoveAt(2);
                        }
                    }
                }
            }
            base.contents = localCopy.ToArray();
        }
예제 #2
0
 public override void Visit(StringBuilder sb, BuildContext bc)
 {
     if (bc.Options.SubscriptMode)
     {
         // separate by double underscore to differentiate from Msub and prevent clashes
         first.Visit(sb, bc);
         sb.Append("__");
         second.Visit(sb, bc);
         bc.Tokens.Add(this);
     }
     else if (second is Mo mo && mo.IsTimesOrStar && first is Mi mi)
     {
         // this isn't really a superscript - it's part of the variable
         Mi newMi = new Mi(mi.Content + Semantics.StarPrefix);
         newMi.Visit(sb, bc);
         bc.Tokens.Add(this);
     }
 /// <summary>
 /// This function replaces all known inverse trig functions (in the msup blocks)
 /// by inverse names, so that sin^-1 becomes arcsin.
 /// </summary>
 /// <param name="contents">Buidlable contents</param>
 private static void ReplaceInverseTrigFunctions(IBuildable[] contents)
 {
     for (int i = 0; i < contents.Length; i++)
     {
         IBuildable c            = contents[i];
         string     trigFunction = string.Empty;
         if (c is Msup)
         {
             bool funcIsTrig = false, radixIsNeg1 = false;
             Pair <IBuildable, IBuildable> terms = (c as Msup).Values;
             if (terms.First is Mrow)
             {
                 Mrow row1 = terms.First as Mrow;
                 if (row1.Contents.Length > 0 && row1.Contents[0] is Mi)
                 {
                     if (Semantics.inverseTrigs.ContainsKey((row1.Contents[0] as Mi).Content))
                     {
                         trigFunction = (row1.Contents[0] as Mi).Content;
                         funcIsTrig   = true;
                     }
                 }
             }
             if (terms.Second is Mrow)
             {
                 Mrow          row2 = terms.Second as Mrow;
                 StringBuilder sb   = new StringBuilder();
                 BuildContext  bc   = new BuildContext();
                 row2.Visit(sb, bc);
                 if (sb.ToString() == "-1")
                 {
                     radixIsNeg1 = true;
                 }
             }
             // if this is an inverse function, replace an <msup> with an inverse <mi>
             if (funcIsTrig && radixIsNeg1)
             {
                 Mi mi = new Mi(Semantics.inverseTrigs[trigFunction]);
                 contents[i] = mi;
             }
         }
     }
 }
예제 #4
0
        public override void Visit(StringBuilder sb, BuildContext bc)
        {
            if (bc.Options.SubscriptMode)
            {
                // separate by double underscore to differentiate from Msub and prevent clashes
                first.Visit(sb, bc);
                sb.Append("__");
                second.Visit(sb, bc);
            }
            else if (second is Mo && (second as Mo).IsTimesOrStar && first is Mi)
            {
                // this isn't really a superscript - it's part of the variable
                Mi mi    = (Mi)first;
                Mi newMi = new Mi(mi.Content + Semantics.starPrefix);
                newMi.Visit(sb, bc);
            }
            else
            {
                if ((first is Mrow) && ((first as Mrow).ContainsSingleMtable))
                {
                    if ((second is Mrow) && ((second as Mrow).ContainsSingleMi) && ((second as Mrow).LastElement as Mi).Content == "T")
                    {
                        first.Visit(sb, bc);
                        sb.Append(".Transpose()");
                    }
                    else if ((second is Mrow) && ((second as Mrow).ContainsSingleMn) && ((second as Mrow).LastElement as Mn).IsIntegerGreaterThan1)
                    {
                        first.Visit(sb, bc);
                        sb.Append(".Power(");
                        second.Visit(sb, bc);
                        sb.Append(")");
                    }
                    else if ((second is Mrow) && ((second as Mrow).ContainsSingleMn) && ((second as Mrow).LastElement as Mn).Content == "-1")
                    {
                        first.Visit(sb, bc);
                        sb.Append(".Inverse()");
                    }
                    bc.Tokens.Add(this);
                    return;
                }

                if (bc.LastTokenRequiresTimes)
                {
                    sb.Append("*");
                }

                // determine whether power must be inlined
                bool firstIsMrowMi         = (first is Mrow) && ((first as Mrow).ContainsSingleMi);
                bool secondIsIntegralPower = (second is Mrow) && ((second as Mrow).ContainsSingleMn) &&
                                             ((second as Mrow).LastElement as Mn).IsIntegerGreaterThan1;
                bool mustInlinePower = false;
                int  power           = 0;
                if (secondIsIntegralPower)
                {
                    power           = ((second as Mrow).LastElement as Mn).IntegerValue;
                    mustInlinePower = power <= bc.Options.MaxInlinePower;
                }
                if (mustInlinePower)
                {
                    for (int i = 0; i < power; ++i)
                    {
                        if (i != 0 && (first is Mrow) && ((first as Mrow).ContainsSingleMn))
                        {
                            sb.Append("*");  //for the case mn^2 not appended * automatically
                        }
                        first.Visit(sb, bc); // * sign appended automatically
                    }
                }
                else
                {
                    sb.Append("Math.Pow(");
                    first.Visit(sb, bc);
                    sb.Append(", ");
                    second.Visit(sb, bc);
                    sb.Append(")");
                }
            }

            bc.Tokens.Add(this);
        }
        public virtual void Visit(StringBuilder sb, BuildContext context)
        {
            bool containsFunct = false;
            int  numFuncts     = 0;

            if (sb == null || context == null || contents == null || contents.Length == 0)
            {
                return;
            }

            // copy contents into list
            List <IBuildable> ctxCopy = new List <IBuildable>(contents);

            // check if the Sigma operator acts as a sum
            if (context.Options.TreatSigmaAsSum)
            {
                // look for the plain sigma operator
                int index;
                while ((index = ctxCopy.FindIndex(a => (a is Mo && (a as Mo).IsSigma))) != -1)
                {
                    // so long as it is not the last element
                    if (index != ctxCopy.Count - 1)
                    {
                        BuildablePlainSum bps = new BuildablePlainSum(ctxCopy[index + 1]);
                        ctxCopy.RemoveAt(index + 1);
                        ctxCopy[index] = bps;

                        context.AddSum(bps);
                    }
                }
            }

            // check if delta <mo> appears before an <mi>
            if (context.Options.DeltaPartOfIdent)
            {
                int index;
                while ((index = ctxCopy.FindIndex(a => (a is Mo && (a as Mo).IsDelta))) != -1)
                {
                    // check that it's not the last element
                    if (index != ctxCopy.Count - 1)
                    {
                        // check that the next element is <mi>
                        Mi mi = ctxCopy[index + 1] as Mi;
                        if (mi != null)
                        {
                            // change Mi's content to incorporate the delta
                            Mi newMi = new Mi("∆" + mi.Content);
                            ctxCopy[index + 1] = newMi;
                            // remove the delta
                            ctxCopy.RemoveAt(index);
                            Trace.WriteLine(newMi.Content);
                        }
                    }
                }
            }
            else
            {
                // change delta from mo to mi
                int index;
                while ((index = ctxCopy.FindIndex(a => (a is Mo && (a as Mo).IsDelta))) != -1)
                {
                    ctxCopy[index] = new Mi("∆");
                }
            }

            // Scan for functions.
            // If one is found, increment the number. Because nested
            // functions which do not contain parentheses (e.g. sin sin x)
            // are contained in the same row element (in non-Word generated markup),
            // this allows us to determine how many close parens we need.
            foreach (IBuildable v in ctxCopy)
            {
                if (v is Mi && Semantics.knownFuncts.Contains((v as Mi).Content))
                {
                    containsFunct = true;
                    numFuncts++;
                }
            }

            if (containsFunct)
            {
                // Only process if this is not the spurious function.
                if (ctxCopy.Count != 1 || (!Semantics.knownFuncts.Contains((ctxCopy[0] as Mi).Content)))
                {
                    foreach (IBuildable v in ctxCopy)
                    {
                        v.Visit(sb, context);
                    }

                    for (; numFuncts > 0; numFuncts--)
                    {
                        sb.Append(")");
                    }
                }
            }
            // No function was found, so process in the normal fashion.
            else
            {
                foreach (var v in ctxCopy)
                {
                    v.Visit(sb, context);
                }
            }
        }