private Action <PingerArgument> MakePinger(DataViewRow input, ForecastingStateBase state) { _host.AssertValue(input); var srcGetter = input.GetGetter <TInput>(input.Schema[_inputColumnIndex]); Action <PingerArgument> pinger = (PingerArgument args) => { state.LocalConfidenceLevel = args.ConfidenceLevel; state.LocalHorizon = args.Horizon; // This means don't call srcGetter in getters. if (args.DontConsumeSource) { _dontFetchSrcValue = true; return; } _dontFetchSrcValue = false; TInput src = default; srcGetter(ref src); state.UpdateState(ref src, args.RowPosition, _parent.WindowSize > 0); }; return(pinger); }
private static ValueGetter <TDst> GetGetterAsCore <TSrc, TDst>(DataViewType typeSrc, DataViewType typeDst, DataViewRow row, int col) { Contracts.Assert(typeof(TSrc) == typeSrc.RawType); Contracts.Assert(typeof(TDst) == typeDst.RawType); var getter = row.GetGetter <TSrc>(row.Schema[col]); bool identity; var conv = Conversions.Instance.GetStandardConversion <TSrc, TDst>(typeSrc, typeDst, out identity); if (identity) { Contracts.Assert(typeof(TSrc) == typeof(TDst)); return((ValueGetter <TDst>)(Delegate) getter); } var src = default(TSrc); return ((ref TDst dst) => { getter(ref src); conv(in src, ref dst); }); }
private static CountAggregator GetVecAggregator <T>(DataViewRow row, VectorType colType, int colSrc) { return(new CountAggregator <T>(colType, row.GetGetter <VBuffer <T> >(row.Schema[colSrc]))); }
private static CountAggregator GetOneAggregator <T>(DataViewRow row, DataViewType colType, int colSrc) { return(new CountAggregator <T>(colType, row.GetGetter <T>(row.Schema[colSrc]))); }
private protected override Delegate[] CreateGettersCore(DataViewRow input, Func <int, bool> activeCols, out Action disposer) { Host.Assert(LabelIndex >= 0); Host.Assert(ScoreIndex >= 0); disposer = null; long cachedPosition = -1; var label = default(VBuffer <float>); var score = default(VBuffer <float>); ValueGetter <VBuffer <float> > nullGetter = (ref VBuffer <float> vec) => vec = default(VBuffer <float>); var labelGetter = activeCols(LabelOutput) || activeCols(L1Output) || activeCols(L2Output) || activeCols(DistCol) ? RowCursorUtils.GetVecGetterAs <float>(NumberDataViewType.Single, input, LabelIndex) : nullGetter; var scoreGetter = activeCols(ScoreOutput) || activeCols(L1Output) || activeCols(L2Output) || activeCols(DistCol) ? input.GetGetter <VBuffer <float> >(input.Schema[ScoreIndex]) : nullGetter; Action updateCacheIfNeeded = () => { if (cachedPosition != input.Position) { labelGetter(ref label); scoreGetter(ref score); cachedPosition = input.Position; } }; var getters = new Delegate[5]; if (activeCols(LabelOutput)) { ValueGetter <VBuffer <float> > labelFn = (ref VBuffer <float> dst) => { updateCacheIfNeeded(); label.CopyTo(ref dst); }; getters[LabelOutput] = labelFn; } if (activeCols(ScoreOutput)) { ValueGetter <VBuffer <float> > scoreFn = (ref VBuffer <float> dst) => { updateCacheIfNeeded(); score.CopyTo(ref dst); }; getters[ScoreOutput] = scoreFn; } if (activeCols(L1Output)) { ValueGetter <double> l1Fn = (ref double dst) => { updateCacheIfNeeded(); dst = VectorUtils.L1Distance(in label, in score); }; getters[L1Output] = l1Fn; }
protected override ValueGetter <Single> GetScoreGetter(DataViewRow row) { return(row.GetGetter <Single>(row.Schema[_bindings.ScoreIndex])); }
private static ValueGetter <TDst> GetGetterAsCore <TSrc, TDst>(DataViewType typeSrc, DataViewType typeDst, DataViewRow row, DataViewSchema.Column col) { Contracts.Assert(typeof(TSrc) == typeSrc.RawType); Contracts.Assert(typeof(TDst) == typeDst.RawType); bool identity; if (typeSrc.RawKind() == DataKind.UInt32 && typeDst.RawKind() == DataKind.UInt32) { var getter = row.GetGetter <uint>(col); // Multiclass future issue uint plus = (typeDst.IsKey() ? (uint)1 : (uint)0) - (typeSrc.IsKey() ? (uint)1 : (uint)0); identity = true; var src = default(uint); ValueGetter <uint> mapu = (ref uint dst) => { getter(ref src); dst = src + plus; }; return(mapu as ValueGetter <TDst>); } else if (typeSrc.RawKind() == DataKind.Single && typeDst.RawKind() == DataKind.UInt32) { var getter = row.GetGetter <float>(col); // Multiclass future issue uint plus = (typeDst.IsKey() ? (uint)1 : (uint)0) - (typeSrc.IsKey() ? (uint)1 : (uint)0); identity = true; var src = default(float); ValueGetter <uint> mapu = (ref uint dst) => { getter(ref src); dst = (uint)src + plus; }; return(mapu as ValueGetter <TDst>); } else if (typeSrc.RawKind() == DataKind.Int64 && typeDst.RawKind() == DataKind.UInt64) { ulong plus = (typeDst.IsKey() ? (ulong)1 : (ulong)0) - (typeSrc.IsKey() ? (ulong)1 : (ulong)0); var getter = row.GetGetter <long>(col); identity = true; var src = default(long); ValueGetter <ulong> mapu = (ref ulong dst) => { getter(ref src); CheckRange(src, dst); dst = (ulong)src + plus; }; return(mapu as ValueGetter <TDst>); } else if (typeSrc.RawKind() == DataKind.Single && typeDst.RawKind() == DataKind.UInt64) { ulong plus = (ulong)((typeDst.IsKey() ? 1 : 0) - (typeSrc.IsKey() ? 1 : 0)); var getter = row.GetGetter <ulong>(col); identity = true; var src = default(ulong); ValueGetter <ulong> mapu = (ref ulong dst) => { getter(ref src); CheckRange(src, dst); dst = (ulong)src + plus; }; return(mapu as ValueGetter <TDst>); } else if (typeSrc.RawKind() == DataKind.Int64 && typeDst.RawKind() == DataKind.UInt32) { // Multiclass future issue uint plus = (typeDst.IsKey() ? (uint)1 : (uint)0) - (typeSrc.IsKey() ? (uint)1 : (uint)0); var getter = row.GetGetter <long>(col); identity = true; var src = default(long); ValueGetter <uint> mapu = (ref uint dst) => { getter(ref src); CheckRange(src, dst); dst = (uint)src + plus; }; return(mapu as ValueGetter <TDst>); } else if (typeSrc.RawKind() == DataKind.Single && typeDst.RawKind() == DataKind.String) { // Multiclass future issue var getter = row.GetGetter <float>(col); identity = true; var src = default(float); ValueGetter <DvText> mapu = (ref DvText dst) => { getter(ref src); dst = new DvText(string.Format("{0}", (int)src)); }; return(mapu as ValueGetter <TDst>); } else { var getter = row.GetGetter <TSrc>(col); var conv = Conversions.DefaultInstance.GetStandardConversion <TSrc, TDst>(typeSrc, typeDst, out identity); if (identity) { Contracts.Assert(typeof(TSrc) == typeof(TDst)); return((ValueGetter <TDst>)(Delegate) getter); } var src = default(TSrc); return ((ref TDst dst) => { getter(ref src); conv(in src, ref dst); }); } }
private static Delegate GetGetterAsDelegateCore <TValue>(DataViewRow row, int col) { return(row.GetGetter <TValue>(col)); }
private ValueGetter <VBuffer <ushort> > MakeGetterVec(DataViewRow input, int iinfo) { Host.AssertValue(input); int cv = input.Schema[ColMapNewToOld[iinfo]].Type.GetVectorSize(); Contracts.Assert(cv >= 0); var getSrc = input.GetGetter <VBuffer <ReadOnlyMemory <char> > >(input.Schema[ColMapNewToOld[iinfo]]); var src = default(VBuffer <ReadOnlyMemory <char> >); ValueGetter <VBuffer <ushort> > getterWithStartEndSep = (ref VBuffer <ushort> dst) => { getSrc(ref src); int len = 0; var srcValues = src.GetValues(); for (int i = 0; i < srcValues.Length; i++) { if (!srcValues[i].IsEmpty) { len += srcValues[i].Length; if (_parent._useMarkerChars) { len += TextMarkersCount; } } } var editor = VBufferEditor.Create(ref dst, len); if (len > 0) { int index = 0; for (int i = 0; i < srcValues.Length; i++) { if (srcValues[i].IsEmpty) { continue; } if (_parent._useMarkerChars) { editor.Values[index++] = TextStartMarker; } var span = srcValues[i].Span; for (int ich = 0; ich < srcValues[i].Length; ich++) { editor.Values[index++] = span[ich]; } if (_parent._useMarkerChars) { editor.Values[index++] = TextEndMarker; } } Contracts.Assert(index == len); } dst = editor.Commit(); }; ValueGetter <VBuffer <ushort> > getterWithUnitSep = (ref VBuffer <ushort> dst) => { getSrc(ref src); int len = 0; var srcValues = src.GetValues(); for (int i = 0; i < srcValues.Length; i++) { if (!srcValues[i].IsEmpty) { len += srcValues[i].Length; if (i > 0) { len += 1; // add UnitSeparator character to len that will be added } } } if (_parent._useMarkerChars) { len += TextMarkersCount; } var editor = VBufferEditor.Create(ref dst, len); if (len > 0) { int index = 0; // ReadOnlyMemory can be a result of either concatenating text columns together // or application of word tokenizer before char tokenizer in TextFeaturizingEstimator. // // Considering VBuffer<ReadOnlyMemory> as a single text stream. // Therefore, prepend and append start and end markers only once i.e. at the start and at end of vector. // Insert UnitSeparator after every piece of text in the vector. if (_parent._useMarkerChars) { editor.Values[index++] = TextStartMarker; } for (int i = 0; i < srcValues.Length; i++) { if (srcValues[i].IsEmpty) { continue; } if (i > 0) { editor.Values[index++] = UnitSeparator; } var span = srcValues[i].Span; for (int ich = 0; ich < srcValues[i].Length; ich++) { editor.Values[index++] = span[ich]; } } if (_parent._useMarkerChars) { editor.Values[index++] = TextEndMarker; } Contracts.Assert(index == len); } dst = editor.Commit(); }; return(_parent._isSeparatorStartEnd ? getterWithStartEndSep : getterWithUnitSep); }
private protected override Delegate[] CreateGettersCore(DataViewRow input, Func <int, bool> activeCols, out Action disposer) { disposer = null; var getters = new Delegate[3]; if (!activeCols(ClusterIdCol) && !activeCols(SortedClusterCol) && !activeCols(SortedClusterScoreCol)) { return(getters); } long cachedPosition = -1; VBuffer <Single> scores = default(VBuffer <Single>); var scoresArr = new Single[_numClusters]; int[] sortedIndices = new int[_numClusters]; var scoreGetter = input.GetGetter <VBuffer <Single> >(ScoreIndex); Action updateCacheIfNeeded = () => { if (cachedPosition != input.Position) { scoreGetter(ref scores); scores.CopyTo(scoresArr); int j = 0; foreach (var index in Enumerable.Range(0, scoresArr.Length).OrderBy(i => scoresArr[i])) { sortedIndices[j++] = index; } cachedPosition = input.Position; } }; if (activeCols(ClusterIdCol)) { ValueGetter <uint> assignedFn = (ref uint dst) => { updateCacheIfNeeded(); dst = (uint)sortedIndices[0] + 1; }; getters[ClusterIdCol] = assignedFn; } if (activeCols(SortedClusterScoreCol)) { ValueGetter <VBuffer <Single> > topKScoresFn = (ref VBuffer <Single> dst) => { updateCacheIfNeeded(); var editor = VBufferEditor.Create(ref dst, _numClusters); for (int i = 0; i < _numClusters; i++) { editor.Values[i] = scores.GetItemOrDefault(sortedIndices[i]); } dst = editor.Commit(); }; getters[SortedClusterScoreCol] = topKScoresFn; } if (activeCols(SortedClusterCol)) { ValueGetter <VBuffer <uint> > topKClassesFn = (ref VBuffer <uint> dst) => { updateCacheIfNeeded(); var editor = VBufferEditor.Create(ref dst, _numClusters); for (int i = 0; i < _numClusters; i++) { editor.Values[i] = (uint)sortedIndices[i] + 1; } dst = editor.Commit(); }; getters[SortedClusterCol] = topKClassesFn; } return(getters); }
protected Func <bool> GetColumnComparer(DataViewRow r1, DataViewRow r2, int col, DataViewType type, bool exactDoubles) { if (type is VectorDataViewType vecType) { int size = vecType.Size; Contracts.Assert(size >= 0); var result = vecType.ItemType.RawType.TryGetDataKind(out var kind); Contracts.Assert(result); switch (kind) { case InternalDataKind.I1: return(GetComparerVec <sbyte>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.U1: return(GetComparerVec <byte>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.I2: return(GetComparerVec <short>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.U2: return(GetComparerVec <ushort>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.I4: return(GetComparerVec <int>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.U4: return(GetComparerVec <uint>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.I8: return(GetComparerVec <long>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.U8: return(GetComparerVec <ulong>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.R4: return(GetComparerVec <Single>(r1, r2, col, size, (x, y) => FloatUtils.GetBits(x) == FloatUtils.GetBits(y))); case InternalDataKind.R8: if (exactDoubles) { return(GetComparerVec <Double>(r1, r2, col, size, (x, y) => FloatUtils.GetBits(x) == FloatUtils.GetBits(y))); } else { return(GetComparerVec <Double>(r1, r2, col, size, EqualWithEps)); } case InternalDataKind.Text: return(GetComparerVec <ReadOnlyMemory <char> >(r1, r2, col, size, (a, b) => a.Span.SequenceEqual(b.Span))); case InternalDataKind.Bool: return(GetComparerVec <bool>(r1, r2, col, size, (x, y) => x == y)); case InternalDataKind.TimeSpan: return(GetComparerVec <TimeSpan>(r1, r2, col, size, (x, y) => x.Ticks == y.Ticks)); case InternalDataKind.DT: return(GetComparerVec <DateTime>(r1, r2, col, size, (x, y) => x.Ticks == y.Ticks)); case InternalDataKind.DZ: return(GetComparerVec <DateTimeOffset>(r1, r2, col, size, (x, y) => x.Equals(y))); case InternalDataKind.UG: return(GetComparerVec <DataViewRowId>(r1, r2, col, size, (x, y) => x.Equals(y))); } } else { var result = type.RawType.TryGetDataKind(out var kind); Contracts.Assert(result); switch (kind) { case InternalDataKind.I1: return(GetComparerOne <sbyte>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.U1: return(GetComparerOne <byte>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.I2: return(GetComparerOne <short>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.U2: return(GetComparerOne <ushort>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.I4: return(GetComparerOne <int>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.U4: return(GetComparerOne <uint>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.I8: return(GetComparerOne <long>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.U8: return(GetComparerOne <ulong>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.R4: return(GetComparerOne <Single>(r1, r2, col, (x, y) => FloatUtils.GetBits(x) == FloatUtils.GetBits(y))); case InternalDataKind.R8: if (exactDoubles) { return(GetComparerOne <Double>(r1, r2, col, (x, y) => FloatUtils.GetBits(x) == FloatUtils.GetBits(y))); } else { return(GetComparerOne <Double>(r1, r2, col, EqualWithEps)); } case InternalDataKind.Text: return(GetComparerOne <ReadOnlyMemory <char> >(r1, r2, col, (a, b) => a.Span.SequenceEqual(b.Span))); case InternalDataKind.Bool: return(GetComparerOne <bool>(r1, r2, col, (x, y) => x == y)); case InternalDataKind.TimeSpan: return(GetComparerOne <TimeSpan>(r1, r2, col, (x, y) => x.Ticks == y.Ticks)); case InternalDataKind.DT: return(GetComparerOne <DateTime>(r1, r2, col, (x, y) => x.Ticks == y.Ticks)); case InternalDataKind.DZ: return(GetComparerOne <DateTimeOffset>(r1, r2, col, (x, y) => x.Equals(y))); case InternalDataKind.UG: return(GetComparerOne <DataViewRowId>(r1, r2, col, (x, y) => x.Equals(y))); } } #if !CORECLR // REVIEW: Port Picture type to CoreTLC. if (type is PictureType) { var g1 = r1.GetGetter <Picture>(col); var g2 = r2.GetGetter <Picture>(col); Picture v1 = null; Picture v2 = null; return (() => { g1(ref v1); g2(ref v2); return ComparePicture(v1, v2); }); } #endif throw Contracts.Except("Unknown type in GetColumnComparer: '{0}'", type); }
/// <summary> /// Returns a value getter delegate to fetch the value of column with the given columnIndex, from the row. /// This throws if the column is not active in this row, or if the type /// <typeparamref name="TValue"/> differs from this column's type. /// </summary> /// <typeparam name="TValue"> is the column's content type.</typeparam> /// <param name="column"> is the output column whose getter should be returned.</param> public override ValueGetter <TValue> GetGetter <TValue>(DataViewSchema.Column column) => _row.GetGetter <TValue>(column);
public ListAggregator(DataViewRow row, int col) { Contracts.AssertValue(row); _srcGetter = row.GetGetter <TValue>(row.Schema[col]); _getter = (ValueGetter <VBuffer <TValue> >)Getter; }
private Delegate[] CreateGetters(DataViewRow input, bool[] active) { Contracts.Assert(Utils.Size(active) == 2); Contracts.Assert(_parent._distMapper != null); var getters = new Delegate[2]; if (active[0] || active[1]) { // Put all captured locals at this scope. var featureGetter = InputRoleMappedSchema.Feature?.Index is int idx?input.GetGetter <VBuffer <float> >(idx) : null; float prob = 0; float score = 0; long cachedPosition = -1; var features = default(VBuffer <float>); ValueMapper <VBuffer <float>, float, float> mapper; mapper = _parent._distMapper.GetMapper <VBuffer <float>, float, float>(); if (active[0]) { ValueGetter <float> getScore = (ref float dst) => { EnsureCachedResultValueMapper(mapper, ref cachedPosition, featureGetter, ref features, ref score, ref prob, input); dst = score; }; getters[0] = getScore; } if (active[1]) { ValueGetter <float> getProb = (ref float dst) => { EnsureCachedResultValueMapper(mapper, ref cachedPosition, featureGetter, ref features, ref score, ref prob, input); dst = prob; }; getters[1] = getProb; } } return(getters); }
public NameOnnxValueGetter(DataViewRow input, string colName, int colIndex) { _colName = colName; _srcgetter = input.GetGetter <T>(input.Schema[colIndex]); }
private ValueGetter <T> GetSrcGetter <T>(DataViewRow input, int iinfo) { return(input.GetGetter <T>(_bindings.SrcCols[iinfo])); }
public override ValueGetter <TValue> GetGetter <TValue>() { return(_row.GetGetter <TValue>(_row.Schema[_col])); }
public override ValueGetter <TValue> GetGetter <TValue>() { return(_row.GetGetter <TValue>(_col)); }
public override ValueGetter <TValue> GetGetter <TValue>(int col) => _row.GetGetter <TValue>(col);
private Delegate MakeGetter <T>(DataViewRow input, int iinfo) { var getter = input.GetGetter <long>(input.Schema[_parent._column.Source]); ValueGetter <T> result = (ref T dst) => { long dateTime = default; getter(ref dateTime); if (!_cache.TryGetValue(dateTime, out TimePoint timePoint)) { _cache[dateTime] = _parent._column.Transform(dateTime); _oldestKeys.Enqueue(dateTime); timePoint = _cache[dateTime]; // If more than 100 cached items, remove 20 if (_cache.Count > 100) { for (int i = 0; i < 20; i++) { long key; while (!_oldestKeys.TryDequeue(out key)) { } while (!_cache.TryRemove(key, out TimePoint removedValue)) { } } } } if (iinfo == 0) { dst = (T)Convert.ChangeType(timePoint.Year, typeof(T)); } else if (iinfo == 1) { dst = (T)Convert.ChangeType(timePoint.Month, typeof(T)); } else if (iinfo == 2) { dst = (T)Convert.ChangeType(timePoint.Day, typeof(T)); } else if (iinfo == 3) { dst = (T)Convert.ChangeType(timePoint.Hour, typeof(T)); } else if (iinfo == 4) { dst = (T)Convert.ChangeType(timePoint.Minute, typeof(T)); } else if (iinfo == 5) { dst = (T)Convert.ChangeType(timePoint.Second, typeof(T)); } else if (iinfo == 6) { dst = (T)Convert.ChangeType(timePoint.AmPm, typeof(T)); } else if (iinfo == 7) { dst = (T)Convert.ChangeType(timePoint.Hour12, typeof(T)); } else if (iinfo == 8) { dst = (T)Convert.ChangeType(timePoint.DayOfWeek, typeof(T)); } else if (iinfo == 9) { dst = (T)Convert.ChangeType(timePoint.DayOfQuarter, typeof(T)); } else if (iinfo == 10) { dst = (T)Convert.ChangeType(timePoint.DayOfYear, typeof(T)); } else if (iinfo == 11) { dst = (T)Convert.ChangeType(timePoint.WeekOfMonth, typeof(T)); } else if (iinfo == 12) { dst = (T)Convert.ChangeType(timePoint.QuarterOfYear, typeof(T)); } else if (iinfo == 13) { dst = (T)Convert.ChangeType(timePoint.HalfOfYear, typeof(T)); } else if (iinfo == 14) { dst = (T)Convert.ChangeType(timePoint.WeekIso, typeof(T)); } else if (iinfo == 15) { dst = (T)Convert.ChangeType(timePoint.YearIso, typeof(T)); } else if (iinfo == 16) { dst = (T)Convert.ChangeType(timePoint.MonthLabel.AsMemory(), typeof(T)); } else if (iinfo == 17) { dst = (T)Convert.ChangeType(timePoint.AmPmLabel.AsMemory(), typeof(T)); } else if (iinfo == 18) { dst = (T)Convert.ChangeType(timePoint.DayOfWeekLabel.AsMemory(), typeof(T)); } else if (iinfo == 19) { dst = (T)Convert.ChangeType(timePoint.HolidayName.AsMemory(), typeof(T)); } else { dst = (T)Convert.ChangeType(timePoint.IsPaidTimeOff, typeof(T)); } }; return(result); }
private ValueGetter <long> GetLabelGetter(DataViewRow row, DataViewSchema.Column col) { // The label column type is checked as part of args validation. var type = col.Type; _host.Assert(type is KeyDataViewType || type is NumberDataViewType || type is BooleanDataViewType); if (type is BooleanDataViewType) { bool src = default; var getSrc = row.GetGetter <bool>(col); return ((ref long dst) => { getSrc(ref src); if (src) { dst = 1; } else { dst = 0; } }); } if (type is KeyDataViewType) { _host.Assert(type.GetKeyCount() > 0); int size = type.GetKeyCountAsInt32(); ulong src = 0; var getSrc = RowCursorUtils.GetGetterAs <ulong>(NumberDataViewType.UInt64, row, col.Index); return ((ref long dst) => { getSrc(ref src); // The value should fall between 0 and size inclusive, where 0 is considered // missing/invalid (this is the contract of the KeyType). However, we still handle the // cases of too large values correctly (by treating them as invalid). if (src <= (ulong)size) { dst = (long)src - 1; } else { dst = -1; } }); } else { double src = 0; var getSrc = RowCursorUtils.GetGetterAs <double>(NumberDataViewType.Double, row, col.Index); return ((ref long dst) => { getSrc(ref src); // NaN maps to -1. if (double.IsNaN(src)) { dst = -1; } else { dst = (long)src; } }); } }