public unsafe ComposedLut(IComposableLut[] luts, BufferCache<int> cache, BufferCache<double> doubleCache) { //luts.Validate(); int lutCount; IComposableLut firstLut, lastLut; GetFirstAndLastLut(luts, out firstLut, out lastLut, out lutCount); _minInputValue = (int) Math.Round(firstLut.MinInputValue); _maxInputValue = (int) Math.Round(firstLut.MaxInputValue); _minOutputValue = (int) Math.Round(lastLut.MinOutputValue); _maxOutputValue = (int) Math.Round(lastLut.MaxOutputValue); _length = _maxInputValue - _minInputValue + 1; _data = cache != null ? cache.Allocate(_length) : MemoryManager.Allocate<int>(_length); const int intermediateDataSize = 8192; // each double entry is 8 bytes so the entire array is 64kB - just small enough to stay off the large object heap var intermediateData = doubleCache != null ? doubleCache.Allocate(intermediateDataSize) : MemoryManager.Allocate<double>(intermediateDataSize); try { fixed (double* intermediateLutData = intermediateData) fixed (int* composedLutData = _data) { var min = _minInputValue; var max = _maxInputValue + 1; var pComposed = composedLutData; // performs the bulk lookups in 64kB chunks (8k entries @ 8 bytes per) in order to keep the intermediate buffer off the large object heap for (var start = min; start < max; start += intermediateDataSize) { var stop = Math.Min(max, start + intermediateDataSize); var count = stop - start; var pIntermediate = intermediateLutData; for (var i = start; i < stop; ++i) *pIntermediate++ = i; for (var j = 0; j < lutCount; ++j) luts[j].LookupValues(intermediateData, intermediateData, count); pIntermediate = intermediateLutData; for (var i = 0; i < count; ++i) *pComposed++ = (int) Math.Round(*pIntermediate++); } } } finally { if (doubleCache != null) doubleCache.Return(intermediateData); } }
public ComposedLut(LutCollection luts, BufferCache <int> cache) { //luts.Validate(); int lutCount; IComposableLut firstLut, lastLut; GetFirstAndLastLut(luts, out firstLut, out lastLut, out lutCount); _minInputValue = (int)Math.Round(firstLut.MinInputValue); _maxInputValue = (int)Math.Round(firstLut.MaxInputValue); _length = _maxInputValue - _minInputValue + 1; _data = cache != null?cache.Allocate(_length) : MemoryManager.Allocate <int>(_length); //copy to array because accessing ObservableList's indexer in a tight loop is very expensive IComposableLut[] lutArray = new IComposableLut[lutCount]; luts.CopyTo(lutArray, 0); unsafe { fixed(int *composedLutData = _data) { int *pLutData = composedLutData; int min = _minInputValue; int max = _maxInputValue + 1; for (int i = min; i < max; ++i) { double val = i; for (int j = 0; j < lutCount; ++j) { val = lutArray[j][val]; } *pLutData = (int)Math.Round(val); ++pLutData; } } } }
public ComposedLut(IComposableLut[] luts, BufferCache<int> cache) { //luts.Validate(); int lutCount; IComposableLut firstLut, lastLut; GetFirstAndLastLut(luts, out firstLut, out lastLut, out lutCount); _minInputValue = (int)Math.Round(firstLut.MinInputValue); _maxInputValue = (int)Math.Round(firstLut.MaxInputValue); _minOutputValue = (int)Math.Round(lastLut.MinOutputValue); _maxOutputValue = (int)Math.Round(lastLut.MaxOutputValue); _length = _maxInputValue - _minInputValue + 1; _data = cache != null ? cache.Allocate(_length) : MemoryManager.Allocate<int>(_length); //copy to array because accessing ObservableList's indexer in a tight loop is very expensive unsafe { fixed (int* composedLutData = _data) { int* pLutData = composedLutData; int min = _minInputValue; int max = _maxInputValue + 1; for (int i = min; i < max; ++i) { double val = i; for (int j = 0; j < lutCount; ++j) val = luts[j][val]; *pLutData = (int) Math.Round(val); ++pLutData; } } } }
public unsafe ComposedLut(IComposableLut[] luts, BufferCache <int> cache, BufferCache <double> doubleCache) { //luts.Validate(); int lutCount; IComposableLut firstLut, lastLut; GetFirstAndLastLut(luts, out firstLut, out lastLut, out lutCount); _minInputValue = (int)Math.Round(firstLut.MinInputValue); _maxInputValue = (int)Math.Round(firstLut.MaxInputValue); _minOutputValue = (int)Math.Round(lastLut.MinOutputValue); _maxOutputValue = (int)Math.Round(lastLut.MaxOutputValue); _length = _maxInputValue - _minInputValue + 1; _data = cache != null?cache.Allocate(_length) : MemoryManager.Allocate <int>(_length); const int intermediateDataSize = 8192; // each double entry is 8 bytes so the entire array is 64kB - just small enough to stay off the large object heap var intermediateData = doubleCache != null?doubleCache.Allocate(intermediateDataSize) : MemoryManager.Allocate <double>(intermediateDataSize); try { fixed(double *intermediateLutData = intermediateData) fixed(int *composedLutData = _data) { var min = _minInputValue; var max = _maxInputValue + 1; var pComposed = composedLutData; // performs the bulk lookups in 64kB chunks (8k entries @ 8 bytes per) in order to keep the intermediate buffer off the large object heap for (var start = min; start < max; start += intermediateDataSize) { var stop = Math.Min(max, start + intermediateDataSize); var count = stop - start; var pIntermediate = intermediateLutData; for (var i = start; i < stop; ++i) { *pIntermediate++ = i; } for (var j = 0; j < lutCount; ++j) { luts[j].LookupValues(intermediateData, intermediateData, count); } pIntermediate = intermediateLutData; for (var i = 0; i < count; ++i) { *pComposed++ = (int)Math.Round(*pIntermediate++); } } } } finally { if (doubleCache != null) { doubleCache.Return(intermediateData); } } }