// construct from either value or log public CQuantity(CQuantityList thatQuantityList, string strThatLabel, double dblToken, bool bIsValue) { Init(thatQuantityList); _symbol = new CSymbol(strThatLabel); _number = new CNumber(dblToken, bIsValue); _isInteger = _number.IsInteger; }
public void RepairIndices() { int q; for (q = 0; q < this.Count; ++q) { CQuantity thisQuantity = this[q]; thisQuantity.ResetIndex(); thisQuantity.ResetInverse(); } for (q = 0; q < this.Count; ++q) { CQuantity thisQuantity = this[q]; if (thisQuantity.Index == -1) { thisQuantity.Index = q; double dblInverseLog = -thisQuantity.Log; CNumber inverseNumber = new CNumber(dblInverseLog, false); int intInverseIndex = this.FindEquivalent(inverseNumber); if (intInverseIndex > -1) { CQuantity inverseQty = this[intInverseIndex]; if (inverseQty.Index == -1) { inverseQty.Index = intInverseIndex; } thisQuantity.SetInverse(ref inverseQty); } } thisQuantity.ExpressionList.Sort(); } }
// this constructor initializes from a line of QuantityValues.txt public CQuantity(CQuantityList thatQuantityList, string strLine) { Init(thatQuantityList); string strThatLabel = ParseLine(ref strLine); string strToken = ParseLine(ref strLine); string strExactFlag = ParseLine(ref strLine); _symbol = new CSymbol(strThatLabel); if (strToken == "") { _number = new CNumber(); } else { _number = new CNumber(strToken, true); _uncertainty = new CNumber(_number.Uncertainty); _lowfence = new CNumber(_number.Value - _uncertainty.Value, true); _highfence = new CNumber(_number.Value + _uncertainty.Value, true); } _isExact = strExactFlag.ToUpper() == "X"; _isComputational = strExactFlag.ToUpper() == "C"; _isQED = strExactFlag.ToUpper() == "Q"; _isSuppressed = strExactFlag.ToUpper() == "S"; _isInteger = _number.IsInteger; }
// construct integer quantity from label and value public CQuantity(CQuantityList thatQuantityList, bool bIsInteger, string strThatLabel, double dblToken) { Init(thatQuantityList); _isExact = true; _isInteger = true; _symbol = new CSymbol(strThatLabel); _number = new CNumber(dblToken, true); }
public void ApplyUncertainty(double dblUncertainty) { _uncertainty = new CNumber(dblUncertainty); if (_uncertainty.Value > 0) { _lowfence = new CNumber(_number.Value - _uncertainty.Value, true); _highfence = new CNumber(_number.Value + _uncertainty.Value, true); } }
public CNumber MultiplyIntegers(CQuantity thatQuantity) { CNumber numberProduct = null; if (_isInteger && thatQuantity._isInteger) { double dblValue = this.Value * thatQuantity.Value; numberProduct = new CNumber(dblValue, true); } return(numberProduct); }
// Multiply integers. // Called by CFactoryList.Normalize(). public CNumber MultiplyIntegers(CFactor thatFactor) { CNumber numberProduct = null; if (this.Qty.IsInteger && thatFactor.Qty.IsInteger) { double dblValue = this.Qty.Value * thatFactor.Qty.Value; numberProduct = new CNumber(dblValue, true); } return(numberProduct); }
// Simplify integer to an integer power. // Resultant power is either 1 or 1/n. public void ApplyPowerToInteger() { if (Qty.IsInteger) { int intValue = (int)Qty.Number.Value; CRatio thisRatio = new CRatio(intValue); bool bSuccess = thisRatio.ApplyPower(ref _ratioPower); CNumber numberToPower = new CNumber(thisRatio); CQuantityList theQuantityList = this.Qty.QuantityList; // Because the calculated quantity value has changed, the factor qty must be replaced. this.Qty = theQuantityList.ReplaceIntegerQuantity(numberToPower); } }
// return index of equivalent if found, else -1 public int FindEquivalent(CNumber thatNumber) { int intIndex = -1; for (int i = 0; i < this.Count; ++i) { if (this[i].IsEquivalent(thatNumber)) { intIndex = i; break; } } return(intIndex); }
// Called in the process of normalizing expressions and factorlists public CQuantity ReplaceIntegerQuantity(CNumber thatNumber) { CQuantity thisQuantity = null; int intIndex = this.FindEquivalent(thatNumber); if (intIndex > -1) { thisQuantity = this[intIndex]; } else { thisQuantity = new CQuantity(this, true, thatNumber.Value.ToString(), thatNumber.Value); this.Add(thisQuantity); } return(thisQuantity); }
private void Init(CQuantityList thatQuantityList) { _intIndex = -1; _isExact = false; _isComputational = false; _isQED = false; _isSuppressed = false; _isInteger = false; _uncertainty = new CNumber(0); _lowfence = new CNumber(); _highfence = new CNumber(); _candidate = new CNumber(); _expressionList = new CExpressionList(); _candidateExpressionList = new CExpressionList(); _inverseQty = null; _quantityList = thatQuantityList; }
// Deep copy. Used in CQuantity::CalculateSubstitution and in deep copy constructors. public CQuantity(CQuantity thatQuantity) { Init(thatQuantity.QuantityList); _symbol = new CSymbol(thatQuantity._symbol); _number = new CNumber(thatQuantity._number); _uncertainty = new CNumber(thatQuantity._uncertainty); _lowfence = new CNumber(thatQuantity._lowfence); _highfence = new CNumber(thatQuantity._highfence); _intIndex = thatQuantity._intIndex; _inverseQty = thatQuantity.InverseQty; _expressionList = new CExpressionList(thatQuantity._expressionList); _isExact = thatQuantity._isExact; _isComputational = thatQuantity._isComputational; _isQED = thatQuantity._isQED; _isSuppressed = thatQuantity._isSuppressed; _isInteger = thatQuantity.IsInteger; }
// Calculate a new candidate value for this quantity as // an average of its expressions. Perform all calculations // using the log to limit propagation of truncation errors. public void CalcCandidate() { if (!_isExact && _expressionList.Count > 0) { _candidate.Log = _expressionList.AverageLog(); // keep the calculated value within the fences if (_uncertainty.Value != 0) { if (_candidate.Log < _lowfence.Log) { _candidate.Log = _lowfence.Log; } else if (_candidate.Log > _highfence.Log) { _candidate.Log = _highfence.Log; } } } else { _candidate = new CNumber(_number); } }
// return the evaluated log as a formatted string public string LogToString() { CNumber thisNumber = new CNumber(Log, false); return(thisNumber.LogToString()); }
// return the evaluated value as a formatted string public string ValueToString() { CNumber thisNumber = new CNumber(Value, true); return(thisNumber.ToString()); }
public void Normalize() { int intNumIndex, intDenomIndex = 0; _numerator.Normalize(); _denominator.Normalize(); if (_numerator.Count > 0 && _denominator.Count > 0) { for (intNumIndex = _numerator.Count - 1; intNumIndex > -1; --intNumIndex) { // if dupe is found in denominator then adjust both numerator and denominator CFactor numeratorFactor = _numerator[intNumIndex]; intDenomIndex = _denominator.Find(numeratorFactor.Label); if (intDenomIndex > -1) { CFactor denominatorFactor = _denominator[intDenomIndex]; numeratorFactor.DivideLike(denominatorFactor); _denominator.RemoveAt(intDenomIndex); _isLogValid = false; } // if inverse is found in denominator then adjust both numerator and denominator intDenomIndex = _denominator.Find(numeratorFactor.Qty.InverseLabel); if (intDenomIndex > -1) { CFactor denominatorFactor = _denominator[intDenomIndex]; CQuantity inverseQty = denominatorFactor.Qty.InverseQty; denominatorFactor.Qty = inverseQty; numeratorFactor.MultiplyLike(denominatorFactor); _denominator.RemoveAt(intDenomIndex); _isLogValid = false; } } } // if numerator factor has negative power swap it to denominator for (intNumIndex = _numerator.Count - 1; intNumIndex > -1; --intNumIndex) { CFactor numeratorFactor = _numerator[intNumIndex]; if (numeratorFactor.Power == 0) { _numerator.RemoveAt(intNumIndex); } else if (numeratorFactor.Power < 0) { _numerator.RemoveAt(intNumIndex); numeratorFactor.FlipPower(); _denominator.Add(numeratorFactor); _isLogValid = false; } } // if denominator factor has negative power swap it to numerator for (intDenomIndex = _denominator.Count - 1; intDenomIndex > -1; --intDenomIndex) { CFactor denominatorFactor = _denominator[intDenomIndex]; if (denominatorFactor.Power == 0) { _denominator.RemoveAt(intDenomIndex); } else if (denominatorFactor.Power < 0) { _denominator.RemoveAt(intDenomIndex); denominatorFactor.FlipPower(); _numerator.Add(denominatorFactor); _isLogValid = false; } } // net out integers between numerator and denominator int intNumeratorIndex = _numerator.FindInteger(); int intDenominatorIndex = _denominator.FindInteger(); if (intNumeratorIndex > -1 && intDenominatorIndex > -1) { CFactor numeratorFactor = _numerator[intNumeratorIndex]; CFactor denominatorFactor = _denominator[intDenominatorIndex]; if (numeratorFactor.RatioPower.Equals(1) && denominatorFactor.RatioPower.Equals(1)) { int intNumeratorValue = (int)numeratorFactor.Qty.Value; int intDenominatorValue = (int)denominatorFactor.Qty.Value; // Putting both integers into a CRatio has the effect of reducing them CRatio ratioThis = new CRatio(intNumeratorValue, intDenominatorValue); double dblNumerator = (double)ratioThis.Numerator; double dblDenominator = (double)ratioThis.Denominator; CNumber numberNumerator = new CNumber(dblNumerator); CNumber numberDenominator = new CNumber(dblDenominator); CQuantityList theQuantityList = numeratorFactor.Qty.QuantityList; numeratorFactor.Qty = theQuantityList.ReplaceIntegerQuantity(numberNumerator); denominatorFactor.Qty = theQuantityList.ReplaceIntegerQuantity(numberDenominator); } } _numerator.Normalize(); _denominator.Normalize(); SetSymbolCount(); }
// Substitute every term of each expression to form potential new expressions public void CalculateSubstitution(int intMaxFactors, bool bFirstPass) { int intLimit = _expressionList.Count; double dblLogThis = this.Log; CExpressionList thisExpressionList; // Integers are never substituted. if (!this._isInteger) { // On first pass initialize from the established expression list. // On subsequent passes build on previous candidate list. if (bFirstPass) { thisExpressionList = new CExpressionList(_expressionList); _candidateExpressionList = new CExpressionList(_expressionList); } else { thisExpressionList = new CExpressionList(_candidateExpressionList); } // Limit this to only the expressions that are already in the list. intLimit = thisExpressionList.Count; // for each expression in this quantity's expression list for (int i = 0; i < intLimit; ++i) { CExpression baseExpression = thisExpressionList[i]; CNumber baseNumber = new CNumber(baseExpression.Log, false); int intNumeratorLimit = baseExpression.Numerator.Count; int intDenominatorLimit = baseExpression.Denominator.Count; // for each factor in the numerator for (int intFactorIndex = 0; intFactorIndex < intNumeratorLimit; ++intFactorIndex) { CFactor baseFactor = baseExpression.Numerator[intFactorIndex]; CQuantity baseQuantity = new CQuantity(baseFactor.Qty); // Integers are never substituted. // Computational intermediates are never substituted. They are expanded on printout. if (!baseQuantity._isInteger /* && !baseQuantity._isComputational*/) { // for each expression associated with the numerator factor for (int k = 0; k < baseQuantity.ExpressionList.Count; ++k) { CExpression insertExpression = new CExpression(baseQuantity.ExpressionList[k]); if (!insertExpression.ContainsSymbol(this.Symbol)) { CExpression newExpression = new CExpression(baseExpression); newExpression.SubstituteIntoNumerator(intFactorIndex, insertExpression); CNumber newNumber = new CNumber(newExpression.Log, false); if (!baseNumber.IsEquivalent(newNumber)) { // !!! error double dblLogTest = newExpression.Log; // testing only } newExpression.Normalize(); if (newExpression.SymbolCount <= intMaxFactors) { _candidateExpressionList.Add(newExpression); } } } } } // for each factor in the denominator for (int intFactorIndex = 0; intFactorIndex < intDenominatorLimit; ++intFactorIndex) { CFactor baseFactor = baseExpression.Denominator[intFactorIndex]; CQuantity baseQuantity = new CQuantity(baseFactor.Qty); // Integers are never substituted. // Computational intermediates are never substituted. They are expanded on printout. if (!baseQuantity._isInteger /* && !baseQuantity._isComputational*/) { for (int k = 0; k < baseQuantity.ExpressionList.Count; ++k) { // for each expression associated with the denominator factor CExpression insertExpression = new CExpression(baseQuantity.ExpressionList[k]); if (!insertExpression.ContainsSymbol(this.Symbol)) { CExpression newExpression = new CExpression(baseExpression); newExpression.SubstituteIntoDenominator(intFactorIndex, insertExpression); CNumber newNumber = new CNumber(newExpression.Log, false); if (!baseNumber.IsEquivalent(newNumber)) { // !!! error double dblLogTest = newExpression.Log; // testing only } newExpression.Normalize(); if (newExpression.SymbolCount <= intMaxFactors) { _candidateExpressionList.Add(newExpression); } } } } } _candidateExpressionList.SuppressDupes(); _candidateExpressionList.SuppressTautology(this); } GC.Collect(); } }
// Sort quantities and then combine dupes by adding powers. public void Normalize() { Sort(); int i; // combine like factors for (i = this.Count - 1; i > 0; --i) { if (this[i].Label == this[i - 1].Label) { // n^x * n^y = n^xy this[i - 1].MultiplyLike(this[i]); this.RemoveAt(i); } } // Simplify integer to a power for (i = this.Count - 1; i > -1; --i) { CFactor thisFactor = this[i]; if (thisFactor.Qty.IsInteger && thisFactor.Power != 1) { thisFactor.ApplyPowerToInteger(); } } // combine integer factors for (i = this.Count - 1; i > 0; --i) { CFactor thisFactor = this[i]; CFactor nextFactor = this[i - 1]; if (thisFactor.IsInteger && nextFactor.IsInteger) { // !!! ToDo: deal with root != 1 CNumber numberProduct = nextFactor.MultiplyIntegers(thisFactor); CQuantityList theQuantityList = thisFactor.Qty.QuantityList; // Because the calculated quantity value has changed, the factor qty must be replaced. nextFactor.Qty = thisFactor.Qty.QuantityList.ReplaceIntegerQuantity(numberProduct); this.RemoveAt(i); } } // combine inverses for (i = this.Count - 1; i > 0; --i) { CFactor thisFactor = this[i]; if (thisFactor.Power != 0) { CQuantity thisQuantity = thisFactor.Qty; if (thisQuantity.InverseQty != null) { CQuantity inverseQty = thisQuantity.InverseQty; int intInverse = this.Find(inverseQty.Label); if (intInverse > -1) { // n^x * 1/n^y = n^x/n^y = n^(x-y) CFactor inverseFactor = this[intInverse]; thisFactor.Qty = inverseFactor.Qty; inverseFactor.DivideLike(thisFactor); this.RemoveAt(i); } } } } // drop factors that equal 1 for (i = this.Count - 1; i > -1; --i) { CFactor thisFactor = this[i]; // x^0 = 1 and log(1) = 0 // n*1 = n if (thisFactor.Power == 0 || thisFactor.Log == 0) { this.RemoveAt(i); } } }
// This comparison returns true if log is within standard difference // of otherNumber.log. public bool IsEquivalent(CNumber otherNumber) { return(_number.IsEquivalent(otherNumber)); }