private ReadOnlyMemory <char> GetSlotName(int index, VBuffer <ReadOnlyMemory <char> > slotNames)
            {
                _env.Assert(0 <= index && index < slotNames.Length);
                var slotName = slotNames.GetItemOrDefault(index);

                return(slotName.IsEmpty
                    ? new ReadOnlyMemory <char>($"f{index}".ToCharArray())
                    : slotName);
            }
            private ReadOnlyMemory <char> GetSlotName(int index, VBuffer <ReadOnlyMemory <char> > slotNames)
            {
                var count = slotNames.GetValues().Length;

                _env.Assert(count > index || count == 0 && slotNames.Length > index);
                var slotName = slotNames.GetItemOrDefault(index);

                return(slotName.IsEmpty
                    ? new ReadOnlyMemory <char>($"f{index}".ToCharArray())
                    : slotName);
            }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the mapping from T into a StringBuilder representation, using various heuristics.
        /// This StringBuilder representation will be a component of the composed KeyValues for the
        /// hash outputs.
        /// </summary>
        public static ValueMapper <T, StringBuilder> GetSimpleMapper <T>(ISchema schema, int col)
        {
            Contracts.AssertValue(schema);
            Contracts.Assert(0 <= col && col < schema.ColumnCount);
            var type = schema.GetColumnType(col).ItemType;

            Contracts.Assert(type.RawType == typeof(T));
            var conv = Conversion.Conversions.Instance;

            // First: if not key, then get the standard string converison.
            if (!type.IsKey)
            {
                return(conv.GetStringConversion <T>(type));
            }

            bool identity;

            // Second choice: if key, utilize the KeyValues metadata for that key, if it has one and is text.
            if (schema.HasKeyNames(col, type.KeyCount))
            {
                // REVIEW: Non-textual KeyValues are certainly possible. Should we handle them?
                // Get the key names.
                VBuffer <ReadOnlyMemory <char> > keyValues = default;
                schema.GetMetadata(MetadataUtils.Kinds.KeyValues, col, ref keyValues);
                ReadOnlyMemory <char> value = default;

                // REVIEW: We could optimize for identity, but it's probably not worthwhile.
                var keyMapper = conv.GetStandardConversion <T, uint>(type, NumberType.U4, out identity);
                return
                    ((ref T src, ref StringBuilder dst) =>
                {
                    ClearDst(ref dst);
                    uint intermediate = 0;
                    keyMapper(ref src, ref intermediate);
                    if (intermediate == 0)
                    {
                        return;
                    }
                    keyValues.GetItemOrDefault((int)(intermediate - 1), ref value);
                    dst.AppendMemory(value);
                });
            }

            // Third choice: just use the key value itself, subject to offsetting by the min.
            return(conv.GetKeyStringConversion <T>(type.AsKey));
        }
Exemplo n.º 4
0
        public override Delegate[] CreateGetters(IRow input, Func <int, bool> activeOutput, out Action disposer)
        {
            disposer = null;

            var getters = new Delegate[3];

            if (!activeOutput(ClusterIdCol) && !activeOutput(SortedClusterCol) && !activeOutput(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 (activeOutput(ClusterIdCol))
            {
                ValueGetter <uint> assignedFn =
                    (ref uint dst) =>
                {
                    updateCacheIfNeeded();
                    dst = (uint)sortedIndices[0] + 1;
                };
                getters[ClusterIdCol] = assignedFn;
            }

            if (activeOutput(SortedClusterScoreCol))
            {
                ValueGetter <VBuffer <Single> > topKScoresFn =
                    (ref VBuffer <Single> dst) =>
                {
                    updateCacheIfNeeded();
                    var values = dst.Values;
                    if (Utils.Size(values) < _numClusters)
                    {
                        values = new Single[_numClusters];
                    }
                    for (int i = 0; i < _numClusters; i++)
                    {
                        values[i] = scores.GetItemOrDefault(sortedIndices[i]);
                    }
                    dst = new VBuffer <Single>(_numClusters, values);
                };
                getters[SortedClusterScoreCol] = topKScoresFn;
            }

            if (activeOutput(SortedClusterCol))
            {
                ValueGetter <VBuffer <uint> > topKClassesFn =
                    (ref VBuffer <uint> dst) =>
                {
                    updateCacheIfNeeded();
                    var values = dst.Values;
                    if (Utils.Size(values) < _numClusters)
                    {
                        values = new uint[_numClusters];
                    }
                    for (int i = 0; i < _numClusters; i++)
                    {
                        values[i] = (uint)sortedIndices[i] + 1;
                    }
                    dst = new VBuffer <uint>(_numClusters, values);
                };
                getters[SortedClusterCol] = topKClassesFn;
            }
            return(getters);
        }