public unsafe HybridMap2(IFontProvider fontProvider, IPixelFormatProvider pixelFormatProvider, string fullMapPath, string refMapPath, string refFontPath, int coreCount, int partitionsPerDim, int?partitionDepth) { if (coreCount < 1) { coreCount = System.Environment.ProcessorCount - coreCount; } this.FontProvider = fontProvider; this.PixelFormatProvider = pixelFormatProvider; this.FontProvider.Init(this.PixelFormatProvider.DiscreteNormalizedValues.Length); Log.WriteLine(" DiscreteNormalizedValues:"); for (int i = 0; i < PixelFormatProvider.DiscreteNormalizedValues.Length; ++i) { if (i > 14) { Log.WriteLine(" ..."); break; } Log.WriteLine(" {0}: {1,10:0.00}", i, PixelFormatProvider.DiscreteNormalizedValues[i]); } Log.WriteLine("Number of source chars (1d): " + this.FontProvider.CharCount.ToString("N0")); Log.WriteLine("Chosen values per tile: " + pixelFormatProvider.DiscreteNormalizedValues.Length); Log.WriteLine("Dimensions: " + PixelFormatProvider.DimensionCount); Log.WriteLine("Resulting map will have this many entries: " + pixelFormatProvider.MapEntryCount.ToString("N0")); long mapdimpix = (long)Math.Sqrt(pixelFormatProvider.MapEntryCount); Log.WriteLine("Resulting map will be about: [" + mapdimpix.ToString("N0") + ", " + mapdimpix.ToString("N0") + "]"); // fill in char source info (actual tile values) Log.EnterTask("Analyze incoming font"); this.CharInfo = new CharInfo[FontProvider.CharCount];// new List<CharInfo>(); for (int ichar = 0; ichar < FontProvider.CharCount; ++ichar) { var ci = new CharInfo(PixelFormatProvider.DimensionCount) { srcIndex = ichar, #if DEBUG //fontImageCellPos = FontProvider.GetCharPosInChars(ichar), //fontImagePixelPos = FontProvider.GetCharOriginInPixels(ichar), #endif }; pixelFormatProvider.PopulateCharColorData(ci, fontProvider); this.CharInfo[ichar] = ci; } Log.WriteLine("Number of source chars: " + this.CharInfo.Length); PartitionManager pm = new PartitionManager(partitionsPerDim, partitionDepth.GetValueOrDefault(PixelFormatProvider.DimensionCount + 1), PixelFormatProvider.DiscreteNormalizedValues); // create list of all mapkeys Log.EnterTask("Generating {0:N0} map key indices", pixelFormatProvider.MapEntryCount); this.Keys = Utils.Permutate(PixelFormatProvider.DimensionCount, pixelFormatProvider.DiscreteNormalizedValues); // returns sorted. // populate the denormalized values for (int i = 0; i < this.Keys.Length; ++i) { this.Keys[i].DenormalizedValues = this.PixelFormatProvider.Denormalize(this.Keys[i].NormalizedValues); } Log.EndTask(); Log.WriteLine("Key count: " + this.Keys.Length); foreach (var ci in this.CharInfo) { pm.AddItem(ci); } Log.EndTask(); Log.EnterTask("Calculate all mappings"); // - generate a list of mappings and their distances ulong theoreticalMappings = (ulong)this.CharInfo.Length * (ulong)pixelFormatProvider.MapEntryCount; Log.WriteLine(" Theoretical mapping count: " + theoreticalMappings.ToString("N0")); List <Task> comparisonBatches = new List <Task>(); var Map = new Mapping[Keys.Length];// indices need to be synchronized with Keys. for (int icore = 0; icore < coreCount; ++icore) { // create a task to process a segment of keys ulong keyBegin = (ulong)icore; keyBegin *= (ulong)Keys.Length; keyBegin /= (ulong)coreCount; ulong keyEnd = (ulong)icore + 1; keyEnd *= (ulong)Keys.Length; keyEnd /= (ulong)coreCount; int coreID = icore; bool isLastCore = (icore == coreCount - 1); comparisonBatches.Add(Task.Run(() => { PopulateMap(keyBegin, keyEnd, coreID, isLastCore, pm, Map); })); } Task.WaitAll(comparisonBatches.ToArray()); Log.EndTask(); // todo: a histogram would be more informative than this crap. int numCharsUsed = 0; int numCharsUsedOnce = 0; CharInfo mostUsedChar = null; int numRepetitions = 0; foreach (var ci in this.CharInfo) { if (mostUsedChar == null || mostUsedChar.usages < ci.usages) { mostUsedChar = ci; } if (ci.usages > 0) { numCharsUsed++; } if (ci.usages == 1) { numCharsUsedOnce++; } if (ci.usages > 1) { numRepetitions += ci.usages - 1; } } Log.WriteLine("Process currently using {0:0.00} mb of memory)", Utils.BytesToMb(Utils.UsedMemoryBytes)); #if false OutputFullMap(fullMapPath, Map); #endif DistinctMappedChars = Map.DistinctBy(o => o.icharInfo).Select(o => this.CharInfo[o.icharInfo]).ToArray(); for (int ichar = 0; ichar < DistinctMappedChars.Length; ++ichar) { CharInfo ci = DistinctMappedChars[ichar]; Debug.Assert(ci != null); ci.refFontIndex = ichar; } OutputRefMapAndFont(refMapPath, refFontPath, Map); // save data structures string jsonDistinctMappedChars = Newtonsoft.Json.JsonConvert.SerializeObject(DistinctMappedChars, Newtonsoft.Json.Formatting.Indented); System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\DistinctMappedChars.json"), jsonDistinctMappedChars); //string jsonKeys = Newtonsoft.Json.JsonConvert.SerializeObject(Keys, Newtonsoft.Json.Formatting.Indented); //System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\Keys.json"), jsonKeys); string jsonCharInfo = Newtonsoft.Json.JsonConvert.SerializeObject(CharInfo, Newtonsoft.Json.Formatting.Indented); System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\CharInfo.json"), jsonCharInfo); //string jsonMap = Newtonsoft.Json.JsonConvert.SerializeObject(Map, Newtonsoft.Json.Formatting.Indented); //System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\Map.json"), jsonMap); Log.WriteLine("Post-map stats:"); Log.WriteLine(" Used char count: " + numCharsUsed); Log.WriteLine(" Number of unused char: " + (this.CharInfo.Length - numCharsUsed)); Log.WriteLine(" Number of chars used exactly once: " + numCharsUsedOnce); Log.WriteLine(" Most-used char: " + mostUsedChar + " (" + mostUsedChar.usages + ") usages"); Log.WriteLine(" Number of total char repetitions: " + numRepetitions); }
public void Add(Mapping m) { Add__(m, Length * 2); }