Ejemplo n.º 1
0
func textToCasReal(instring string, recs string) (exp Express, err error) {
	//TextToCas will turn a string (eg "2*x+3") to an Express class
	//var origin = instring
	//fmt.Println(instring, "oi")
	newstringindent := recs + "    "
	origin := instring
	//fix stupid signs

	instring = strings.Replace(instring, "-", "+-", -1)
	instring = strings.Replace(instring, "++", "+", -1)
	instring = strings.Replace(instring, "--", "+", -1)
	instring = strings.Replace(instring, "(+-", "(-", -1)
	newinstring := ""
	for index, charbyte := range instring {
		char := string(charbyte)
		if char == "_" && index != 0 &&
			strmans.StringInSlice(string(instring[index-1]), []string{"*", "/", "+", "-", "("}) == false &&
			(((index >= 2 && string(instring[index-2]) == "-") || (index+1 < len(instring) && string(instring[index+1]) == "{")) == false) {

			newinstring += "*"

		}
		newinstring += char
	}
	instring = newinstring
	if len(strmans.StrToBracketpairs(instring)) > 0 &&
		strmans.StrToBracketpairs(instring)[0][0] == 0 &&
		strmans.StrToBracketpairs(instring)[0][1] == len(instring)-1 {
		instring = instring[1 : len(instring)-1]
	}
	if string(instring[0]) == "+" || string(instring[0]) == "*" {
		instring = instring[1:]
	}
	//fix negative numbers
	if instring == "-1" { //Avoid "-1" becomes product(-1,1)
		return Number("-1"), nil
	}
	if string(instring[0]) == "-" && len(strmans.FindCharOutsideBracket("+", instring)) == 0 {
		dbg.Debug(10, recs+origin+" Becomes minusnumber")
		retval, err := textToCasReal(instring[1:], newstringindent)
		if err == nil {
			return Product(Number("-1"), retval), nil
		} else {
			panic("bad input to TextToCas " + origin)
		}

	}
	/*if string(instring[0]) == "-" &&
		len(strmans.StrToBracketpairs(instring)) == 0 {
		dbg.Debug(10, recs+origin+" Becomes minusnumber")
		retval, err := textToCasReal(instring[1:], newstringindent)
		if err == nil {
			return Product(Number("-1"), retval), nil
		} else {
			panic("bad input to TextToCas " + origin)
		}
	}*/
	//remove unnecessary bracket it's sorrounding the whole instring
	bracketPairs := strmans.StrToBracketpairs(instring)
	if len(bracketPairs) > 0 && bracketPairs[0][0] == 0 && bracketPairs[0][1] == len(instring)-1 {
		instring = instring[1 : len(instring)-1]
	}
	bracketPairs = strmans.StrToBracketpairs(instring)
	if instring == "-1" { //Avoid "-1" becomes product(-1,1)
		return Number("-1"), nil
	}
	//parse addition
	plusses := strmans.FindCharOutsideBracket("+", instring)
	if len(plusses) > 0 {
		dbg.Debug(10, recs+origin+" becomes ADDITION"+
			fmt.Sprintf("%v", strmans.SplitStringByIndexes(instring, plusses)))
		var retaddends []Express
		for _, addendstring := range strmans.SplitStringByIndexes(instring, plusses) {
			returnaddend, err := textToCasReal(addendstring, newstringindent)
			if err != nil {
				panic("bad input to TextToCas " + origin)
			}
			retaddends = append(retaddends, returnaddend)
		}
		return Addition(retaddends...), nil
	}
	//if it's not addition, check for product
	productsigns := strmans.FindCharOutsideBracket("*", instring)
	if len(productsigns) > 0 {
		dbg.Debug(10, recs+origin+" becomes PRODUCT"+
			fmt.Sprintf("%v", strmans.SplitStringByIndexes(instring, productsigns)))
		var retfactors []Express
		for _, factorstring := range strmans.SplitStringByIndexes(instring, productsigns) {
			returnfactor, err := textToCasReal(factorstring, newstringindent)
			if err != nil {
				panic("bad input to TextToCas " + origin)
			}
			retfactors = append(retfactors, returnfactor)
		}
		return Product(retfactors...), nil
	}
	//if it's not a product, check for fraction
	fractionsigns := strmans.FindCharOutsideBracket("/", instring)
	if len(fractionsigns) > 0 {
		if len(fractionsigns) > 1 {
			dbg.Debug(0, "BAD FRACTION, DON'T DO STUFF LIKE 2/3/2 (BRACKETS PLEASE)")
		}

		dbg.Debug(10, recs+origin+" becomes FRACTION"+
			fmt.Sprintf("%v", strmans.SplitStringByIndexes(instring, fractionsigns)))
		retnum, err1 := textToCasReal(strmans.SplitStringByIndexes(instring, fractionsigns)[0], newstringindent)
		retdenom, err2 := textToCasReal(strmans.SplitStringByIndexes(instring, fractionsigns)[1], newstringindent)
		if err1 != nil || err2 != nil {
			panic("bad input to TextToCas " + origin)
		}
		return Fraction(retnum, retdenom), nil

	}
	//if it's not a fraction, then it might be a power
	powersigns := strmans.FindCharOutsideBracket("^", instring)
	if len(powersigns) > 0 {
		if len(powersigns) > 1 {
			dbg.Debug(0, "BAD POWER, PLEASE USE BRACKETS")
		}
		dbg.Debug(10, recs+origin+" becomes POWER"+
			fmt.Sprintf("%v", (strmans.SplitStringByIndexes(instring, powersigns))))
		rootandexpstrings := strmans.SplitStringByIndexes(instring, powersigns)
		retroot, err1 := textToCasReal(rootandexpstrings[0], newstringindent)
		retexp, err2 := textToCasReal(rootandexpstrings[1], newstringindent)
		if err1 != nil || err2 != nil {
			panic("Bad input to TextToCas " + origin)
		}
		retval := Power(retroot, retexp)
		retval.Forcepowerprint = true
		return retval, nil
	}
	//no usual things to look after; check for functions
	for index, charbytes := range instring {
		char := string(charbytes)
		if char == "(" && string(instring[index-1]) != "(" && string(instring[index-1]) != ")" {
			startbracket := index
			//find function string
			bracketoffset := 1
			var funcend int
			for indexk := len(instring) - 1; indexk > -1; indexk-- {
				if string(instring[indexk]) == "(" {
					bracketoffset++
				} else if string(instring[indexk]) == ")" {
					bracketoffset--
					if bracketoffset == 0 {
						funcend = indexk
						break
					}
				}
			}
			funcstring := instring[0:startbracket]
			insidebrackets := instring[startbracket+1 : funcend]
			//findcommas
			escapeoffset := 0
			var commaindexes []int
			for index, charbytes := range insidebrackets {
				char := string(charbytes)
				if escapeoffset > 0 {
					if char == "}" {
						escapeoffset--
					}
				}
				if char == "{" {
					escapeoffset++
				}
				if char == "," {
					commaindexes = append(commaindexes, index)
				}
			}
			if len(commaindexes) == 0 {
				switch funcstring {
				case "sin":
					{
						dbg.Debug(10, recs+origin+" becomes sine: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Sine(argexp), nil
					}
				case "cos":
					{
						dbg.Debug(10, recs+origin+" becomes cosine: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Cosine(argexp), nil
					}
				case "tan":
					{
						dbg.Debug(10, recs+origin+" becomes tangent: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Tangent(argexp), nil
					}
				case "arcsin":
					{
						dbg.Debug(10, recs+origin+" becomes arcsine: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Arcsine(argexp), nil
					}
				case "arccos":
					{
						dbg.Debug(10, recs+origin+" becomes arccosine: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Arccosine(argexp), nil
					}
				case "arctan":
					{
						dbg.Debug(10, recs+origin+" becomes arctangent: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Arctangent(argexp), nil
					}
				case "ln":
					{
						dbg.Debug(10, recs+origin+" becomes natlogarithm: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Natlog(argexp), nil
					}
				case "log":
					{
						dbg.Debug(10, recs+origin+" becomes comlogarithm: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Comlog(argexp), nil
					}
				case "sqrt":
					{
						dbg.Debug(10, recs+origin+" becomes squareroot: "+insidebrackets)
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Squareroot(argexp), nil
					}
				default:
					{
						dbg.Debug(10, recs+origin+" becomes unknownfunction: "+
							funcstring+"("+insidebrackets+")")
						argexp, err := textToCasReal(insidebrackets, newstringindent)
						if err != nil {
							panic("bad input to TextToCas " + origin)
						}
						return Unknownfunction(funcstring, []Express{argexp}), nil
					}
				}
			} else {
				argstrings := strmans.SplitStringByIndexes(insidebrackets, commaindexes)
				dbg.Debug(10, recs+origin+"becomes unknownfunction: "+
					funcstring+"("+insidebrackets+")")
				var retargs []Express
				for _, argstr := range argstrings {
					retarg, err := textToCasReal(argstr, newstringindent)
					if err != nil {
						panic("Bad input to TextToCas " + origin)
					}
					retargs = append(retargs, retarg)
				}
				return Unknownfunction(funcstring, retargs), nil

			}
		}
	}
	stillsignsininstring := false
	bracketoffset := 0
	for _, charbyte := range instring {
		char := string(charbyte)
		if char == "{" {
			bracketoffset++
		} else if char == "}" {
			bracketoffset--
		}
		if bracketoffset == 0 &&
			(char == "+" || char == "*" || char == "/" || char == "^") {

			stillsignsininstring = true
			break
		}

	}
	if stillsignsininstring {
		brackets := strmans.StrToBracketpairs(instring)
		if string(instring[0]) == "-" &&
			len(brackets) > 0 && brackets[0][0] == 1 && brackets[0][1] == len(instring)-1 {
			dbg.Debug(10, recs+origin+"becomes negative "+instring[1:len(instring)-1])
			partret, err := textToCasReal(instring[1:len(instring)-1], newstringindent)
			if err != nil {
				panic("Bad input to TextToCas: " + origin)
			}
			return Product(Number("-1"), partret), nil
		}
		panic("BAD EXPRESSION")
	}
	if string(instring[0]) == "-" {
		dbg.Debug(10, recs+origin+" becomes negative "+instring[1:])
		dbg.Debug(10, recs+"    "+"-1")
		partret, err := textToCasReal(instring[1:], newstringindent)
		if err != nil {
			panic("Bad input to TextToCas: " + origin)
		}
		return Product(Number("-1"), partret), nil
	} else {
		//NUMBER INSTANCE
		dbg.Debug(10, recs+origin)
		return Number(instring), nil

	}

}
Ejemplo n.º 2
0
// Simplifies an input expression (instance) with respect to the focus
//
// Uses the Substitutiondict
func (instance Express) AlgebraicSimp(focus Express, approx bool) Express {
	dbg.Debug(10, "starting simplify:"+instance.Tostring()+" "+instance.Etype)
	instancecopy := instance.Makesubs()
	newinstance := instancecopy
	var last Express
	dbg.Debug(10, "starting simplify:"+newinstance.Tostring()+" "+instance.Etype)

	for {
		last = newinstance
		var simptry Express
		var err error
		newinstance = Treesimplify(newinstance)
		newinstance = newinstance.Evalsimplify(approx)
		dbg.Debug(10, "starting simplify:"+newinstance.Tostring()+" "+instance.Etype)

		// Simplify all parts
		switch newinstance.Etype {
		case "Number":
			return newinstance
		case "Sine":
			newinstance = Sine(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Cosine":
			newinstance = Cosine(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Tangent":
			newinstance = Tangent(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Arcsine":
			newinstance = Arcsine(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Arccosine":
			newinstance = Arccosine(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Arctangent":
			newinstance = Arctangent(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Natlog":
			newinstance = Natlog(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Comlog":
			newinstance = Comlog(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Squareroot":
			newinstance = Squareroot(newinstance.Arg.AlgebraicSimp(focus, approx))
		case "Addition":
			var newnewinstanceadds []Express
			for _, addend := range *newinstance.Addends {
				newnewinstanceadds = append(newnewinstanceadds,
					addend.AlgebraicSimp(focus, approx))
			}
			newinstance = Addition(newnewinstanceadds...)
		case "Product":
			var newnewinstancefacs []Express
			for _, fac := range *newinstance.Factors {
				newnewinstancefacs = append(newnewinstancefacs,
					fac.AlgebraicSimp(focus, approx))
			}
			newinstance = Product(newnewinstancefacs...)
		case "Unknownfunction":
			var newnewargs []Express
			for _, arg := range *newinstance.Argarr {
				newnewargs = append(newnewargs, arg.AlgebraicSimp(focus, approx))
			}
			newinstance = Unknownfunction(newinstance.Funcstr, newnewargs)
		case "Fraction":
			newinstance = Fraction(
				newinstance.Numerator.AlgebraicSimp(focus, approx),
				newinstance.Denominator.AlgebraicSimp(focus, approx))

		case "Power":
			newinstance = Power(
				newinstance.Root.AlgebraicSimp(focus, approx),
				newinstance.Exponent.AlgebraicSimp(focus, approx))
		}
		newinstance = Treesimplify(newinstance)
		newinstance = newinstance.Evalsimplify(approx)
		switch newinstance.Etype {
		case "Number":
			return newinstance
		case "Addition":
			simptry, err = newinstance.Antidistributive(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Antidistributive"+
					" function")
				newinstance = simptry
				continue
			}
			//simptry, err = newinstance.Associativeadd()
			//if err == nil {
			//	newinstance = simptry
			//	continue
			//}
		case "Product":
			simptry, err = newinstance.Ntimes0()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Ntimes0"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.AssociativeProd()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"AssocitaiveProd"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Sameroot(focus, false)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Sameroot"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Sameexponent(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Sameexponent"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Distributive(focus, false)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Distributive"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Fractionasfactor()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Fractionasfactor"+
					" function")
				newinstance = simptry
				continue
			}
		case "Fraction":

			simptry, err = newinstance.Samerootofexponentfactors(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Samerootofexponentfactor"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Ndiv1()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Ndiv1"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Antisameexponentfrac(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Antisameexponentfrac"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Shortfract()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Shortfract"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Cancelfactors()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Cancelfactors"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Samerootofexponent(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Samerootofexponent"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Movefactordownifalone()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Movefactordownifalone"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Fractionindenom()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Fractionindenom"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Fractioninnum()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Fractioninnum"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Shortenevaluables()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Shortenevaluables"+
					" function")
				newinstance = simptry
				continue
			}
		case "Power":
			simptry, err = newinstance.Ntothe0()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Ntothe0"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Ntothe1()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Ntothe1"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Sameexponentfrac(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Sameexponentfrac"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Antisameroot(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Antisameroot"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Antisameexponent(focus)
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Antisameexponent"+
					" function")
				newinstance = simptry
				continue
			}
			simptry, err = newinstance.Powerasroot()
			if err == nil {
				dbg.Debug(10, "Simplifying from "+newinstance.Tostring()+
					" to "+simptry.Tostring()+" with the "+"Powerasroot"+
					" function")
				newinstance = simptry
				continue
			}
		}
		if Expeq(last, newinstance) {
			break
		}
	}
	return newinstance

}