diff --git a/BigFloat.cs b/BigFloat.cs new file mode 100644 index 0000000..4a4b64c --- /dev/null +++ b/BigFloat.cs @@ -0,0 +1,747 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Numerics; + +namespace LibZNI +{ + [Serializable] + public class BigFloat : IComparable, IComparable, IEquatable + { + private BigInteger numerator; + private BigInteger denominator; + + public static readonly BigFloat One = new BigFloat(1); + public static readonly BigFloat Zero = new BigFloat(0); + public static readonly BigFloat MinusOne = new BigFloat(-1); + public static readonly BigFloat OneHalf = new BigFloat(1, 2); + + public int Sign + { + get + { + switch (numerator.Sign + denominator.Sign) + { + case 2: + case -2: + return 1; + case 0: + return -1; + default: + return 0; + } + } + } + + + //constructors + public BigFloat() + { + numerator = BigInteger.Zero; + denominator = BigInteger.One; + } + public BigFloat(string value) + { + BigFloat bf = Parse(value); + this.numerator = bf.numerator; + this.denominator = bf.denominator; + } + public BigFloat(BigInteger numerator, BigInteger denominator) + { + this.numerator = numerator; + if (denominator == 0) + throw new ArgumentException("denominator equals 0"); + this.denominator = BigInteger.Abs(denominator); + } + public BigFloat(BigInteger value) + { + this.numerator = value; + this.denominator = BigInteger.One; + } + public BigFloat(BigFloat value) + { + if (BigFloat.Equals(value, null)) + { + this.numerator = BigInteger.Zero; + this.denominator = BigInteger.One; + } + else + { + + this.numerator = value.numerator; + this.denominator = value.denominator; + } + } + public BigFloat(ulong value) + { + numerator = new BigInteger(value); + denominator = BigInteger.One; + } + public BigFloat(long value) + { + numerator = new BigInteger(value); + denominator = BigInteger.One; + } + public BigFloat(uint value) + { + numerator = new BigInteger(value); + denominator = BigInteger.One; + } + public BigFloat(int value) + { + numerator = new BigInteger(value); + denominator = BigInteger.One; + } + public BigFloat(float value) : this(value.ToString("N99")) + { + } + public BigFloat(double value) : this(value.ToString("N99")) + { + } + public BigFloat(decimal value) : this(value.ToString("N99")) + { + } + + //non-static methods + public BigFloat Add(BigFloat other) + { + if (BigFloat.Equals(other, null)) + throw new ArgumentNullException("other"); + + this.numerator = this.numerator * other.denominator + other.numerator * this.denominator; + this.denominator *= other.denominator; + return this; + } + public BigFloat Subtract(BigFloat other) + { + if (BigFloat.Equals(other, null)) + throw new ArgumentNullException("other"); + + this.numerator = this.numerator * other.denominator - other.numerator * this.denominator; + this.denominator *= other.denominator; + return this; + } + public BigFloat Multiply(BigFloat other) + { + if (BigFloat.Equals(other, null)) + throw new ArgumentNullException("other"); + + this.numerator *= other.numerator; + this.denominator *= other.denominator; + return this; + } + public BigFloat Divide(BigFloat other) + { + if (BigInteger.Equals(other, null)) + throw new ArgumentNullException("other"); + if (other.numerator == 0) + throw new System.DivideByZeroException("other"); + + this.numerator *= other.denominator; + this.denominator *= other.numerator; + return this; + } + public BigFloat Remainder(BigFloat other) + { + if (BigInteger.Equals(other, null)) + throw new ArgumentNullException("other"); + + //b = a mod n + //remainder = a - floor(a/n) * n + + BigFloat result = this - Floor(this / other) * other; + + this.numerator = result.numerator; + this.denominator = result.denominator; + + + return this; + } + public BigFloat DivideRemainder(BigFloat other, out BigFloat remainder) + { + this.Divide(other); + + remainder = BigFloat.Remainder(this, other); + + return this; + } + public BigFloat Pow(int exponent) + { + if (numerator.IsZero) + { + // Nothing to do + } + else if (exponent < 0) + { + BigInteger savedNumerator = numerator; + numerator = BigInteger.Pow(denominator, -exponent); + denominator = BigInteger.Pow(savedNumerator, -exponent); + } + else + { + numerator = BigInteger.Pow(numerator, exponent); + denominator = BigInteger.Pow(denominator, exponent); + } + + return this; + } + public BigFloat Abs() + { + numerator = BigInteger.Abs(numerator); + return this; + } + public BigFloat Negate() + { + numerator = BigInteger.Negate(numerator); + return this; + } + public BigFloat Inverse() + { + BigInteger temp = numerator; + numerator = denominator; + denominator = temp; + return this; + } + public BigFloat Increment() + { + numerator += denominator; + return this; + } + public BigFloat Decrement() + { + numerator -= denominator; + return this; + } + public BigFloat Ceil() + { + if (numerator < 0) + numerator -= BigInteger.Remainder(numerator, denominator); + else + numerator += denominator - BigInteger.Remainder(numerator, denominator); + + Factor(); + return this; + } + public BigFloat Floor() + { + if (numerator < 0) + numerator += denominator - BigInteger.Remainder(numerator, denominator); + else + numerator -= BigInteger.Remainder(numerator, denominator); + + Factor(); + return this; + } + public BigFloat Round() + { + //get remainder. Over divisor see if it is > new BigFloat(0.5) + BigFloat value = BigFloat.Decimals(this); + + if (value.CompareTo(OneHalf) >= 0) + this.Ceil(); + else + this.Floor(); + + return this; + } + public BigFloat Truncate() + { + numerator -= BigInteger.Remainder(numerator, denominator); + Factor(); + return this; + } + public BigFloat Decimals() + { + BigInteger result = BigInteger.Remainder(numerator, denominator); + + return new BigFloat(result, denominator); + } + public BigFloat ShiftDecimalLeft(int shift) + { + if (shift < 0) + return ShiftDecimalRight(-shift); + + numerator *= BigInteger.Pow(10, shift); + return this; + } + public BigFloat ShiftDecimalRight(int shift) + { + if (shift < 0) + return ShiftDecimalLeft(-shift); + denominator *= BigInteger.Pow(10, shift); + return this; + } + public double Sqrt() + { + return Math.Pow(10, BigInteger.Log10(numerator) / 2) / Math.Pow(10, BigInteger.Log10(denominator) / 2); + } + public double Log10() + { + return BigInteger.Log10(numerator) - BigInteger.Log10(denominator); + } + public double Log(double baseValue) + { + return BigInteger.Log(numerator, baseValue) - BigInteger.Log(numerator, baseValue); + } + public override string ToString() + { + //default precision = 100 + return ToString(100); + } + + public int GetActualDecimalCount() + { + Factor(); + BigInteger remain; + BigInteger res = BigInteger.DivRem(numerator, denominator, out remain); + if (remain == 0) return 0; + + BigInteger decimals = (numerator * BigInteger.Pow(10, 100)) / denominator; + if (decimals == 0) return 0; + + StringBuilder sb = new StringBuilder(); + while (decimals > 0) + { + sb.Append(decimals % 10); + decimals /= 10; + } + return sb.Length; + } + public string ToString(int precision, bool trailingZeros = false) + { + Factor(); + + BigInteger remainder; + BigInteger result = BigInteger.DivRem(numerator, denominator, out remainder); + + if (remainder == 0 && trailingZeros) + return result + ".0"; + else if (remainder == 0) + return result.ToString(); + + + BigInteger decimals = (numerator * BigInteger.Pow(10, precision)) / denominator; + + if (decimals == 0 && trailingZeros) + return result + ".0"; + else if (decimals == 0) + return result.ToString(); + + StringBuilder sb = new StringBuilder(); + + while (precision-- > 0 && decimals > 0) + { + sb.Append(decimals % 10); + decimals /= 10; + } + + if (trailingZeros) + return result + "." + new string(sb.ToString().Reverse().ToArray()); + else + return result + "." + new string(sb.ToString().Reverse().ToArray()).TrimEnd(new char[] { '0' }); + + + } + public string ToMixString() + { + Factor(); + + BigInteger remainder; + BigInteger result = BigInteger.DivRem(numerator, denominator, out remainder); + + if (remainder == 0) + return result.ToString(); + else + return result + ", " + remainder + "/" + denominator; + } + + public string ToRationalString() + { + Factor(); + + return numerator + " / " + denominator; + } + public int CompareTo(BigFloat other) + { + if (BigFloat.Equals(other, null)) + throw new ArgumentNullException("other"); + + //Make copies + BigInteger one = this.numerator; + BigInteger two = other.numerator; + + //cross multiply + one *= other.denominator; + two *= this.denominator; + + //test + return BigInteger.Compare(one, two); + } + public int CompareTo(object other) + { + if (other == null) + throw new ArgumentNullException("other"); + + if (!(other is BigFloat)) + throw new System.ArgumentException("other is not a BigFloat"); + + return CompareTo((BigFloat)other); + } + public override bool Equals(object other) + { + if (other == null || GetType() != other.GetType()) + { + return false; + } + + return this.numerator == ((BigFloat)other).numerator && this.denominator == ((BigFloat)other).denominator; + } + public bool Equals(BigFloat other) + { + return (other.numerator == this.numerator && other.denominator == this.denominator); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + //static methods + public static bool Equals(object left, object right) + { + if (left == null && right == null) return true; + else if (left == null || right == null) return false; + else if (left.GetType() != right.GetType()) return false; + else + return (((BigInteger)left).Equals((BigInteger)right)); + } + public static string ToString(BigFloat value) + { + return value.ToString(); + } + + public static BigFloat Inverse(BigFloat value) + { + return (new BigFloat(value)).Inverse(); + } + public static BigFloat Decrement(BigFloat value) + { + return (new BigFloat(value)).Decrement(); + } + public static BigFloat Negate(BigFloat value) + { + return (new BigFloat(value)).Negate(); + } + public static BigFloat Increment(BigFloat value) + { + return (new BigFloat(value)).Increment(); + } + public static BigFloat Abs(BigFloat value) + { + return (new BigFloat(value)).Abs(); + } + public static BigFloat Add(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Add(right); + } + public static BigFloat Subtract(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Subtract(right); + } + public static BigFloat Multiply(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Multiply(right); + } + public static BigFloat Divide(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Divide(right); + } + public static BigFloat Pow(BigFloat value, int exponent) + { + return (new BigFloat(value)).Pow(exponent); + } + public static BigFloat Remainder(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Remainder(right); + } + public static BigFloat DivideRemainder(BigFloat left, BigFloat right, out BigFloat remainder) + { + return (new BigFloat(left)).DivideRemainder(right, out remainder); + } + public static BigFloat Decimals(BigFloat value) + { + return value.Decimals(); + } + public static BigFloat Truncate(BigFloat value) + { + return (new BigFloat(value)).Truncate(); + } + public static BigFloat Ceil(BigFloat value) + { + return (new BigFloat(value)).Ceil(); + } + public static BigFloat Floor(BigFloat value) + { + return (new BigFloat(value)).Floor(); + } + public static BigFloat Round(BigFloat value) + { + return (new BigFloat(value)).Round(); + } + public static BigFloat Parse(string value) + { + if (value == null) + throw new ArgumentNullException("value"); + + value.Trim(); + value = value.Replace(",", ""); + int pos = value.IndexOf('.'); + value = value.Replace(".", ""); + + if (pos < 0) + { + //no decimal point + BigInteger numerator = BigInteger.Parse(value); + return (new BigFloat(numerator)).Factor(); + } + else + { + //decimal point (length - pos - 1) + BigInteger numerator = BigInteger.Parse(value); + BigInteger denominator = BigInteger.Pow(10, value.Length - pos); + + return (new BigFloat(numerator, denominator)).Factor(); + } + } + public static BigFloat ShiftDecimalLeft(BigFloat value, int shift) + { + return (new BigFloat(value)).ShiftDecimalLeft(shift); + } + public static BigFloat ShiftDecimalRight(BigFloat value, int shift) + { + return (new BigFloat(value)).ShiftDecimalRight(shift); + } + public static bool TryParse(string value, out BigFloat result) + { + try + { + result = BigFloat.Parse(value); + return true; + } + catch (ArgumentNullException) + { + result = null; + return false; + } + catch (FormatException) + { + result = null; + return false; + } + } + public static int Compare(BigFloat left, BigFloat right) + { + if (BigFloat.Equals(left, null)) + throw new ArgumentNullException("left"); + if (BigFloat.Equals(right, null)) + throw new ArgumentNullException("right"); + + return (new BigFloat(left)).CompareTo(right); + } + public static double Log10(BigFloat value) + { + return (new BigFloat(value)).Log10(); + } + public static double Log(BigFloat value, double baseValue) + { + return (new BigFloat(value)).Log(baseValue); + } + public static double Sqrt(BigFloat value) + { + return (new BigFloat(value)).Sqrt(); + } + + public static BigFloat operator -(BigFloat value) + { + return (new BigFloat(value)).Negate(); + } + public static BigFloat operator -(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Subtract(right); + } + public static BigFloat operator --(BigFloat value) + { + return value.Decrement(); + } + public static BigFloat operator +(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Add(right); + } + public static BigFloat operator +(BigFloat value) + { + return (new BigFloat(value)).Abs(); + } + public static BigFloat operator ++(BigFloat value) + { + return value.Increment(); + } + public static BigFloat operator %(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Remainder(right); + } + public static BigFloat operator *(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Multiply(right); + } + public static BigFloat operator /(BigFloat left, BigFloat right) + { + return (new BigFloat(left)).Divide(right); + } + public static BigFloat operator >>(BigFloat value, int shift) + { + return (new BigFloat(value)).ShiftDecimalRight(shift); + } + public static BigFloat operator <<(BigFloat value, int shift) + { + return (new BigFloat(value)).ShiftDecimalLeft(shift); + } + public static BigFloat operator ^(BigFloat left, int right) + { + return (new BigFloat(left)).Pow(right); + } + public static BigFloat operator ~(BigFloat value) + { + return (new BigFloat(value)).Inverse(); + } + + public static bool operator !=(BigFloat left, BigFloat right) + { + return Compare(left, right) != 0; + } + public static bool operator ==(BigFloat left, BigFloat right) + { + return Compare(left, right) == 0; + } + public static bool operator <(BigFloat left, BigFloat right) + { + return Compare(left, right) < 0; + } + public static bool operator <=(BigFloat left, BigFloat right) + { + return Compare(left, right) <= 0; + } + public static bool operator >(BigFloat left, BigFloat right) + { + return Compare(left, right) > 0; + } + public static bool operator >=(BigFloat left, BigFloat right) + { + return Compare(left, right) >= 0; + } + + public static bool operator true(BigFloat value) + { + return value != 0; + } + public static bool operator false(BigFloat value) + { + return value == 0; + } + + public static explicit operator decimal(BigFloat value) + { + if (decimal.MinValue > value) throw new System.OverflowException("value is less than System.decimal.MinValue."); + if (decimal.MaxValue < value) throw new System.OverflowException("value is greater than System.decimal.MaxValue."); + + return (decimal)value.numerator / (decimal)value.denominator; + } + public static explicit operator double(BigFloat value) + { + if (double.MinValue > value) throw new System.OverflowException("value is less than System.double.MinValue."); + if (double.MaxValue < value) throw new System.OverflowException("value is greater than System.double.MaxValue."); + + return (double)value.numerator / (double)value.denominator; + } + public static explicit operator float(BigFloat value) + { + if (float.MinValue > value) throw new System.OverflowException("value is less than System.float.MinValue."); + if (float.MaxValue < value) throw new System.OverflowException("value is greater than System.float.MaxValue."); + + return (float)value.numerator / (float)value.denominator; + } + + //byte, sbyte, + public static implicit operator BigFloat(byte value) + { + return new BigFloat((uint)value); + } + public static implicit operator BigFloat(sbyte value) + { + return new BigFloat((int)value); + } + public static implicit operator BigFloat(short value) + { + return new BigFloat((int)value); + } + public static implicit operator BigFloat(ushort value) + { + return new BigFloat((uint)value); + } + public static implicit operator BigFloat(int value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(long value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(uint value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(ulong value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(decimal value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(double value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(float value) + { + return new BigFloat(value); + } + public static implicit operator BigFloat(BigInteger value) + { + return new BigFloat(value); + } + public static explicit operator BigFloat(string value) + { + return new BigFloat(value); + } + + private BigFloat Factor() + { + //factoring can be very slow. So use only when neccessary (ToString, and comparisons) + + if (denominator == 1) + return this; + + //factor numerator and denominator + BigInteger factor = BigInteger.GreatestCommonDivisor(numerator, denominator); + + numerator /= factor; + denominator /= factor; + + return this; + } + + } + +} diff --git a/LibZNI.csproj b/LibZNI.csproj index b99759e..61fd50e 100644 --- a/LibZNI.csproj +++ b/LibZNI.csproj @@ -2,7 +2,7 @@ Library - net5.0 + net6.0 true false false @@ -10,7 +10,8 @@ - + + diff --git a/Tools.cs b/Tools.cs index 27b0533..8f1bea8 100644 --- a/Tools.cs +++ b/Tools.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; +using Newtonsoft.Json; [assembly: LibZNI.AutoUpdater("/job/LibZNI", "library.tar")] namespace LibZNI @@ -29,6 +30,7 @@ namespace LibZNI return "unknown"; } + public static string Hash2String(byte[] Hash) { StringBuilder sb = new StringBuilder(); @@ -65,16 +67,18 @@ namespace LibZNI public static string ZHX(string ToHash) { - ZHash.Instance.NewKey(); - ZHash.Instance.Key = ToHash; - return ZHash.Instance.Key; + ZHash tmp = new ZHash(); + tmp.NewKey(); + tmp.CalculateKey(ToHash); + return tmp._key; } public static string ZSR(string ToSerialize) { - ZHash.Instance.NewSerial(); - ZHash.Instance.Key = ToSerialize; - return ZHash.Instance.Key; + ZHash tmp = new ZHash(); + tmp.NewSerial(); + tmp.CalculateKey(ToSerialize); + return tmp._key; } public static string Base64Encode(string plainText) @@ -104,47 +108,55 @@ namespace LibZNI } } - - - public sealed class ZHash + [Serializable()] + public class ZHash { - private static readonly object _lock = new object(); - private static ZHash _inst = new ZHash(); - static ZHash() { } - - public static ZHash Instance - { - get - { - lock (_lock) - { - if (_inst == null) _inst = new ZHash(); - return _inst; - } - } - } - - + [JsonRequired(), JsonProperty(PropertyName = "value")] public string _key; - public string Key - { - set - { - lock (_lock) - { + [JsonIgnore()] + public string _template; - if (value != "") - CalculateKey(value); - else NewKey(); - } - } - get - { - return _key; - } + public void Reset() + { + _key = _template; + } + + public override string ToString() + { + return _key; } + public void NewKey() + { + + _key = "".PadLeft(10, '0'); + _key += "-"; + _key += "".PadRight(4, '0'); + _key += "-"; + _key += "".PadRight(6, '0'); + _key += "-"; + _key += "".PadRight(8, '0'); + + } + + public void NewSerial() + { + _key = "".PadLeft(10, '0'); + _key += "-"; + _key += "".PadRight(6, '0'); + _key += "-"; + _key += "".PadRight(4, '0'); + _key += "-"; + _key += "".PadRight(4, '0'); + _key += "-"; + _key += "".PadRight(2, '0'); + _key += "-"; + _key += "".PadRight(4, '0'); + _key += "-"; + _key += "".PadRight(8, '0'); + + } public void CalculateKey(string K) { string valid = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ=.+/\\][{}';:?><,_-)(*&^%$#@!`~|"; @@ -160,7 +172,7 @@ namespace LibZNI if (V != '-') { MD5 MDHash = MD5.Create(); - for (int ii = 0; ii < K.Length; ii++) + for (int ii = 0; ii < ((K.Length > _key.Length) ? _key.Length : K.Length); ii++) { byte[] md5Data = MDHash.ComputeHash(Encoding.UTF8.GetBytes((K + i.ToString() + valid[i].ToString() + valid[ii].ToString()).ToCharArray())); // Replace digit with MD5'd char from String K encoded alongside (i) @@ -179,49 +191,61 @@ namespace LibZNI _key = tmp.ToString(); } - public void NewKey() + public static byte[] HashToBytes(string Key) { - lock (_lock) + return Enumerable.Range(0, Key.Length).Where(x=>x % 2 == 0).Select(x=>Convert.ToByte(Key.Substring(x,2),16)).ToArray(); + } + public static ZHash Bytes2Hash(byte[] key) + { + ZHash itm = new ZHash(); + foreach(byte b in key) { - - _key = "".PadLeft(10, '0'); - _key += "-"; - _key += "".PadRight(4, '0'); - _key += "-"; - _key += "".PadRight(6, '0'); - _key += "-"; - _key += "".PadRight(8, '0'); + itm._key += b.ToString("X2"); } + itm._template = itm._key; + return itm; } - public void NewSerial() + public static string Bytes2HashStr(byte[] key) { - lock (_lock) - { - _key = "".PadLeft(10, '0'); - _key += "-"; - _key += "".PadRight(6, '0'); - _key += "-"; - _key += "".PadRight(4, '0'); - _key += "-"; - _key += "".PadRight(4, '0'); - _key += "-"; - _key += "".PadRight(2, '0'); - _key += "-"; - _key += "".PadRight(4, '0'); - _key += "-"; - _key += "".PadRight(8, '0'); - } - } - - public void SetKey(string Key) - { - _key = Key; + return Bytes2Hash(key)._key; } } + public static class ZNILSLTools { + public static bool Compare(this List itx, List itx2) + { + if (itx.Count != itx2.Count) return false; + for(int i = 0; i < itx.Count; i++) + { + if(itx[i] != itx2[i]) return false; + } + + return true; + } + + public static List llParseString2List(this string item, string[] opts, string[] keepopts) + { + return ParseString2List(item, opts, keepopts); + } + internal static string[] Augment(this string[] itm, string x) + { + List working = new List(itm); + List buffer = new List(); + for(int i = 0; i < working.Count; i++) + { + if (String.IsNullOrEmpty(working[i])) break; + buffer.Add(working[i]); + + if (i == working.Count - 1) break; + else + buffer.Add(x); + + } + return buffer.ToArray(); + } public static List ParseString2List(this string item, string[] opts, string[] keepopts) { List entries = new List(); @@ -256,11 +280,10 @@ namespace LibZNI string y = buffer[i]; if (y.Contains(z)) { - string[] newbuff = y.Split(z); + string[] newbuff = y.Split(z).Augment(z); foreach(string V in newbuff) { tmpBuffer.Add(V); - tmpBuffer.Add(z); } }else {