public override int Compare(CNumber other) { if (other.MyType != MyType) { throw new NotImplementedException(); } CNumber_Integer o = (CNumber_Integer)other; int t_len = size; int o_len = o.size; if (o_len > t_len) { return(-1); } if (o_len < t_len) { return(1); } --t_len; while (t_len > 0 && o._Values[t_len] == _Values[t_len]) { --t_len; } return(Math.Sign(_Values[t_len] - o._Values[t_len])); }
//------------------------------------------------------------ // add a number // the native way to take care of the overflow // is checking after the summation if the sum is less than // one of the summands, this would mean overflow // but this would need some more conditional branches // so I choose a way with conversions from uint to ulong // to let the .Net calc the overflow protected virtual void Addition(CNumber_Integer other) { ulong rem = 0; // the remainder (either 0 or 1) (ulong for the overflow) int o_len = other._Values.Count; // the other length int t_len = _Values.Count; // our own length int len = (t_len < o_len) ? t_len : o_len; // calc the minimum length int i = 0; // start with the lowest digit for (; i < len; i++) // first add all common digits { rem += (ulong)other._Values[i]; // val = rem + val + other.val rem += (ulong)_Values[i]; _Values[i] = (uint)rem; rem >>= 32; // rem = overflow } for (; i < o_len; i++) // now copy the remaining from the other { rem += (ulong)other._Values[i]; // don't forget the remainder _Values.Add((uint)rem); rem >>= 32; } for (; (rem > 0) && (i < t_len); i++) // now increase our own remaining digits { // as long as the remainder is non-zero rem += (ulong)_Values[i]; _Values[i] = (uint)rem; rem >>= 32; } if (rem > 0) { _Values.Add((uint)rem); // still something left, just add it } }
public override MMC.Numbers.CNumber sqr() { int cnt = _Values.Count; // calc the different interims (could be done in parallel) CNumber_Integer[] Results = new CNumber_Integer[cnt]; for (int i = 0; i < cnt; ++i) { CNumber_Integer tmp = new CNumber_Integer(this); tmp.Multiply(_Values[i]); tmp._Values.InsertRange(0, new byte[i]); Results[i] = tmp; } // now add them all up CNumber_Integer res = new CNumber_Integer(Results[0]); for (int i = 1; i < cnt; i++) { res.Addition(Results[i]); } res.Trim(); return(res); }
//------------------------------------------------------------ // convert into a string public override string ToString(uint Base) { // first the sign string str = (_Sign) ? "-" : ""; // numbers of digits separated by '.' int step = 4; // now the base-indication switch (Base) { case 2: str += "0b"; break; case 8: str += "0o"; break; case 10: step = 3; break; case 16: str += "0x"; break; default: str += '[' + Base.ToString() + ']'; break; } // if the base is a power of 2 // let's calc the binary logarithm bool poweroftwo = ((Base & (Base - 1)) == 0); if (poweroftwo) { uint b = Base; Base = 0; while (b > 1) { b >>= 1; Base++; } ; } // generate reversed string of digits CNumber_Integer tmp = (CNumber_Integer)Clone(); string num = String.Empty; int cnt = 0; do { if (cnt == step) { cnt = 0; num += '.'; } uint rem = (poweroftwo) ? tmp.ShiftRight((int)Base) : tmp.Divide(Base); num += (char)((rem > 9) ? (rem - 10 + 'A') : (rem + '0')); cnt++; } while (!tmp.IsZero); for (int i = num.Length - 1; i >= 0; i--) { str += num[i]; } return(str); }
//------------------------------------------------------------ // logical functions public override CNumber not() { CNumber_Integer res = new CNumber_Integer(this); res.Not(); res.Trim(); return(res); }
//------------------------------------------------------------ // return a negative version of this one public override MMC.Numbers.CNumber neg() { CNumber_Integer res = new CNumber_Integer(this); if (!IsZero) { res._Sign = !_Sign; } return(res); }
//------------------------------------------------------------ public CNumber_Integer(CNumber_Integer other) { if (other == null) { setZero(); } else { CopyFrom(other); } }
public override MMC.Numbers.CNumber rem(MMC.Numbers.CNumber other) { if (other.MyType != MyType) { throw new NotImplementedException(); } CNumber_Integer Res = new CNumber_Integer(this); return(Res.Divide((CNumber_Integer)other)); }
//------------------------------------------------------------ // helper to create a new number public MMC.Numbers.CNumber NewNumber(double Value) { MMC.Numbers.CNumber res = null; switch (_NumberType) { case MMC.Numbers.CNumber.CNumberType.cnt_Double: res = new MMC.Numbers.CNumber_Double(Value); break; case MMC.Numbers.CNumber.CNumberType.cnt_Integer: res = new MMC.Numbers.CNumber_Integer(Value); break; default: break; } return(res); }
public override MMC.Numbers.CNumber sub(MMC.Numbers.CNumber other) { if (other.MyType != MyType) { throw new NotImplementedException(); } CNumber_Integer res = new CNumber_Integer(this); if (_Sign != ((CNumber_Integer)other)._Sign) { res.Addition((CNumber_Integer)other); } else { res.Subtraction((CNumber_Integer)other); } return(res); }
//------------------------------------------------------------ // subtract a number of shorter or equal length protected virtual void Subtraction(CNumber_Integer other) { bool rem = false; // the overflow state int o_len = other._Values.Count; // the other length int t_len = _Values.Count; // our own length int len = (t_len < o_len) ? t_len : o_len; // calc the minimum length int i = 0; // start with the lowest digit for (; i < len; i++) { byte v = other._Values[i]; if (rem) { ++v; } rem = (v > _Values[i]); _Values[i] -= v; } for (; i < o_len; i++) // now copy the remaining from the other { byte v = other._Values[i]; if (rem) { ++v; } _Values.Add((byte)(-v)); // = 0-v; rem = true; // allways an overflow } for (; rem && (i < t_len); ++i) // now decrease our own remaining digits { rem = (_Values[i] == 0); --_Values[i]; } if (rem) // if we have an overflow we have to { // negate the result _Values[0] = (byte)(-_Values[0]); for (int k = 1; k < _Values.Count; k++) { _Values[k] ^= 0xFF; } _Sign = !_Sign; } Trim(); // could have created some leading zeros }
//------------------------------------------------------------ // divide by another number and return the remainder protected virtual CNumber_Integer Divide(CNumber_Integer other) { CNumber_Integer Save = new CNumber_Integer(this); // save the old value setZero(); // set the initial result to 0 int o_len = other._Values.Count; int t_len = _Values.Count; int pos = t_len - o_len; if (pos < 0) { return(Save); // fewer digits means the result is zero and the remainder are just we } CNumber_Integer Rem = new CNumber_Integer(); // set the remainder to 0 int len = o_len - 1; while (pos >= 0) { Rem.InsertDigit(Save._Values[pos]); // take the next digit byte q = Rem._Values[len]; q /= other._Values[len]; // and make an estimate for the quotient CNumber_Integer tmp = new CNumber_Integer(other); // and calculate the product for this estimated value tmp._Sign = false; tmp.Multiply(q); Rem.Subtraction(tmp); // see how good we estimated if (Rem._Sign) // if we are too low just correct by one { --q; Rem.add(other); } InsertDigit(q); // and write down the quotients digit --pos; // walk one further in our (this) digits } _Sign = (_Sign != other._Sign); Trim(); return(Rem); }
public override CNumber xor(CNumber other) { if (other.MyType != MyType) { throw new NotImplementedException(); } CNumber_Integer res = new CNumber_Integer(this); CNumber_Integer o = (CNumber_Integer)other; int o_len = o._Values.Count; // the other length int t_len = _Values.Count; // our own length int len = (t_len < o_len) ? t_len : o_len; // calc the minimum length int i = 0; // start with the lowest digit for (; i < len; i++) // first handle the common digits { res._Values[i] ^= o._Values[i]; } res.Trim(); return(res); }
// written multiplication public override MMC.Numbers.CNumber mul(MMC.Numbers.CNumber other) { if (other.MyType != MyType) { throw new NotImplementedException(); } CNumber_Integer o = (CNumber_Integer)other; int cnt = o._Values.Count; // calc the different interims (could be done in parallel) CNumber_Integer[] Results = new CNumber_Integer[cnt]; for (int i = 0; i < cnt; i++) { CNumber_Integer tmp = new CNumber_Integer(this); tmp.Multiply(o._Values[i]); tmp._Values.InsertRange(0, new byte[i]); Results[i] = tmp; } // now add them all up CNumber_Integer res = new CNumber_Integer(Results[0]); for (int i = 1; i < cnt; i++) { res.Addition(Results[i]); } //CNumber_Integer mul = (CNumber_Integer)other; //for (int i = mul._Values.Count - 1; i >= 0; i--) //{ // CNumber_Integer tmp = (CNumber_Integer) Clone(); // tmp.Multiply(mul._Values[i]); // res.Insert(0); // res.Addition(tmp); //} res._Sign = (_Sign != o._Sign); res.Trim(); return(res); }
//------------------------------------------------------------ // create a string to a base of a power of 2 protected string toString_2ish_base(uint Base) { uint bits = log_bin(Base); // generate reversed string of digits CNumber_Integer tmp = (CNumber_Integer)Clone(); string num = String.Empty; int cnt = 0; do { if (cnt == 4) { cnt = 0; num += '.'; } uint rem = tmp.ShiftRight(bits); num += (char)((rem > 9) ? (rem - 10 + 'A') : (rem + '0')); ++cnt; } while (!tmp.IsZero); return(num); }
//------------------------------------------------------------ // create a string to a base that is not a power of 2 protected string toString_odd_base(byte Base) { // numbers of digits separated by '.' int step = (Base == 10) ? 3 : 4; // generate reversed string of digits CNumber_Integer tmp = (CNumber_Integer)Clone(); string num = String.Empty; int cnt = 0; do { if (cnt == step) { cnt = 0; num += '.'; } uint rem = tmp.Divide(Base); num += (char)((rem > 9) ? (rem - 10 + 'A') : (rem + '0')); cnt++; } while (!tmp.IsZero); return(num); }
public override bool Equals(MMC.Numbers.CNumber other) { if (other.MyType != MyType) { return(false); } CNumber_Integer o = (CNumber_Integer)other; if (size != o.size) { return(false); } for (int i = 0; i < size; i++) { if (_Values[i] != o._Values[i]) { return(false); } } return(true); }
//------------------------------------------------------------ // add a number // the native way to take care of the overflow // is checking after the summation if the sum is less than // one of the summands, this would mean overflow // but this would need some more conditional branches // so I choose a way with conversions from byte to uint // to let the .Net calc the overflow public void Addition(CNumber_Integer other) { resizeDigits((uint)other.size); // make sure we are big enough for both uint rem = 0; // the remainder int o_len = other.size; // the other length int t_len = size; // our own length int len = (t_len < o_len) ? t_len : o_len; // calc the minimum length int i = 0; // start with the lowest digit for (; i < len; ++i) // first add all common digits { rem += other._Values[i]; // val = rem + val + other.val rem += _Values[i]; _Values[i] = (byte)rem; rem >>= bitsDigit; // rem = overflow } for (; i < o_len; ++i) // now copy the remaining from the other { rem += other._Values[i]; // don't forget the remainder _Values[i] = (byte)rem; rem >>= bitsDigit; } for (; (rem > 0) && (i < t_len); ++i) // now increase our own remaining digits { // as long as the remainder is non-zero rem += _Values[i]; _Values[i] = (byte)rem; rem >>= bitsDigit; } if (rem > 0) { AddDigit((byte)rem); // still something left, just add it } }
//------------------------------------------------------------ // to copy protected virtual void CopyFrom(CNumber_Integer other) { _Values = new List <byte>(other._Values); _Sign = other._Sign; }