using System.Numerics; namespace Just.Core.Collections; public class DataMap : Map, IDataMap, ICloneable where T : IComparisonOperators, IEqualityOperators { internal MapPoint MinCache = default; internal MapPoint MaxCache = default; internal DataMap(int width, int height, T[] values) : base(width, height, values) { } public DataMap(ReadOnlySpan values, int width, int height) : base(values, width, height) { } public DataMap(T[] values, int width, int height) : base(values, width, height) { } public DataMap(T[,] values) : base(values) { } [Pure] public MapPoint Min { get { if (MinCache.Map is null) FindMinMax(); return MinCache; } } [Pure] public MapPoint Max { get { if (MaxCache.Map is null) FindMinMax(); return MaxCache; } } private void FindMinMax() { var data = _values.AsSpan(); T min = data[0]; T max = data[0]; int minId = 0; int maxId = 0; for (int i = 0; i < data.Length; i++) { if (data[i] < min) { min = data[i]; minId = i; continue; } if (data[i] > max) { max = data[i]; maxId = i; } } MinCache = new(min, minId % Width, minId / Width, this); MaxCache = new(max, maxId % Width, maxId / Width, this); } [Pure] public DataMap Clone() { var clone = new DataMap(Width, Height, [.. _values]); clone.MinCache = new(clone._values[(MinCache.Y * Width) + MinCache.X], MinCache.X, MinCache.Y, clone); clone.MaxCache = new(clone._values[(MaxCache.Y * Width) + MaxCache.X], MaxCache.X, MaxCache.Y, clone); return clone; } object ICloneable.Clone() => Clone(); }