/// <summary> /// Constructs a potentially multi-dimensional vector type. /// </summary> /// <param name="itemType">The type of the items contained in the vector.</param> /// <param name="dimensions">The dimensions. Note that, like <see cref="Dimensions"/>, must be non-empty, with all /// non-negative values. Also, because <see cref="Size"/> is the product of <see cref="Dimensions"/>, the result of /// multiplying all these values together must not overflow <see cref="int"/>.</param> public VectorDataViewType(PrimitiveDataViewType itemType, ImmutableArray <int> dimensions) : base(GetRawType(itemType)) { Contracts.CheckParam(dimensions.Length > 0, nameof(dimensions)); Contracts.CheckParam(dimensions.All(d => d >= 0), nameof(dimensions)); ItemType = itemType; Dimensions = dimensions; Size = ComputeSize(Dimensions); }
/// <summary> /// Constructs a potentially multi-dimensional vector type. /// </summary> /// <param name="itemType">The type of the items contained in the vector.</param> /// <param name="dimensions">The dimensions. Note that, like <see cref="Dimensions"/>, must be non-empty, with all /// non-negative values. Also, because <see cref="Size"/> is the product of <see cref="Dimensions"/>, the result of /// multiplying all these values together must not overflow <see cref="int"/>.</param> public VectorDataViewType(PrimitiveDataViewType itemType, params int[] dimensions) : base(GetRawType(itemType)) { Contracts.CheckParam(ArrayUtils.Size(dimensions) > 0, nameof(dimensions)); Contracts.CheckParam(dimensions.All(d => d >= 0), nameof(dimensions)); ItemType = itemType; Dimensions = dimensions.ToImmutableArray(); Size = ComputeSize(Dimensions); }
internal VectorType(PrimitiveDataViewType itemType, VectorType template, params int[] dims) : base(GetRawType(itemType)) { Contracts.CheckValue(template, nameof(template)); Contracts.CheckParam(Utils.Size(dims) > 0, nameof(dims)); Contracts.CheckParam(dims.All(d => d >= 0), nameof(dims)); ItemType = itemType; Dimensions = template.Dimensions.AddRange(dims); Size = ComputeSize(Dimensions); }
internal static ValueGetter <VBuffer <TDst> > GetVecGetterAs <TDst>(PrimitiveDataViewType typeDst, SlotCursor cursor) { Contracts.CheckValue(typeDst, nameof(typeDst)); Contracts.CheckParam(typeDst.RawType == typeof(TDst), nameof(typeDst)); var typeSrc = cursor.GetSlotType(); Func <VectorType, PrimitiveDataViewType, GetterFactory, ValueGetter <VBuffer <TDst> > > del = GetVecGetterAsCore <int, TDst>; var methodInfo = del.GetMethodInfo().GetGenericMethodDefinition().MakeGenericMethod(typeSrc.ItemType.RawType, typeof(TDst)); return((ValueGetter <VBuffer <TDst> >)methodInfo.Invoke(null, new object[] { typeSrc, typeDst, GetterFactory.Create(cursor) })); }
public static ColInfo Create(string name, PrimitiveDataViewType itemType, Segment[] segs, bool user) { Contracts.AssertNonEmpty(name); Contracts.AssertValue(itemType); Contracts.AssertValueOrNull(segs); int size = 0; DataViewType type = itemType; if (segs != null) { var order = Utils.GetIdentityPermutation(segs.Length); if ((segs.Length != 0) && (segs[0].Name is null)) { Array.Sort(order, (x, y) => segs[x].Min.CompareTo(segs[y].Min)); // Check that the segments are disjoint. for (int i = 1; i < order.Length; i++) { int a = order[i - 1]; int b = order[i]; Contracts.Assert(segs[a].Min <= segs[b].Min); if (segs[a].Lim > segs[b].Min) { throw user? Contracts.ExceptUserArg(nameof(Column.Source), "Intervals specified for column '{0}' overlap", name) : Contracts.ExceptDecode("Intervals specified for column '{0}' overlap", name); } } } // Note: since we know that the segments don't overlap, we're guaranteed that // the sum of their sizes doesn't overflow. for (int i = 0; i < segs.Length; i++) { var seg = segs[i]; size += (seg.Name is null) ? seg.Lim - seg.Min : 1; } Contracts.Assert(size >= segs.Length); if (size > 1 || segs[0].ForceVector) { type = new VectorDataViewType(itemType, size); } } else { size++; } return(new ColInfo(name, type, segs, size)); }
/// <summary> /// Tries to get the annotation kind of the specified type for a column. /// </summary> /// <typeparam name="T">The raw type of the annotation, should match the PrimitiveType type</typeparam> /// <param name="schema">The schema</param> /// <param name="type">The type of the annotation</param> /// <param name="kind">The annotation kind</param> /// <param name="col">The column</param> /// <param name="value">The value to return, if successful</param> /// <returns>True if the annotation of the right type exists, false otherwise</returns> public static bool TryGetAnnotation <T>(this DataViewSchema schema, PrimitiveDataViewType type, string kind, int col, ref T value) { Contracts.CheckValue(schema, nameof(schema)); Contracts.CheckValue(type, nameof(type)); var annotationType = schema[col].Annotations.Schema.GetColumnOrNull(kind)?.Type; if (!type.Equals(annotationType)) { return(false); } schema[col].Annotations.GetValue(kind, ref value); return(true); }
/// <summary> /// Given the item type, typeDst, a row, and column index, return a ValueGetter for the vector-valued /// column with a conversion to a vector of typeDst, if needed. This is the weakly typed version of /// <see cref="GetVecGetterAs{TDst}(PrimitiveDataViewType, DataViewRow, int)"/>. /// </summary> public static Delegate GetVecGetterAs(PrimitiveDataViewType typeDst, DataViewRow row, int col) { Contracts.CheckValue(typeDst, nameof(typeDst)); Contracts.CheckValue(row, nameof(row)); Contracts.CheckParam(0 <= col && col < row.Schema.Count, nameof(col)); Contracts.CheckParam(row.IsColumnActive(col), nameof(col), "column was not active"); var typeSrc = row.Schema[col].Type as VectorType; Contracts.Check(typeSrc != null, "Source column type must be vector"); Func <VectorType, PrimitiveDataViewType, GetterFactory, ValueGetter <VBuffer <int> > > del = GetVecGetterAsCore <int, int>; var methodInfo = del.GetMethodInfo().GetGenericMethodDefinition().MakeGenericMethod(typeSrc.ItemType.RawType, typeDst.RawType); return((Delegate)methodInfo.Invoke(null, new object[] { typeSrc, typeDst, GetterFactory.Create(row, col) })); }
private static ValueGetter <VBuffer <TDst> > GetVecGetterAsCore <TSrc, TDst>(VectorType typeSrc, PrimitiveDataViewType typeDst, GetterFactory getterFact) { Contracts.Assert(typeof(TSrc) == typeSrc.ItemType.RawType); Contracts.Assert(typeof(TDst) == typeDst.RawType); Contracts.AssertValue(getterFact); var getter = getterFact.GetGetter <VBuffer <TSrc> >(); bool identity; var conv = Conversions.Instance.GetStandardConversion <TSrc, TDst>(typeSrc.ItemType, typeDst, out identity); if (identity) { Contracts.Assert(typeof(TSrc) == typeof(TDst)); return((ValueGetter <VBuffer <TDst> >)(Delegate) getter); } int size = typeSrc.Size; var src = default(VBuffer <TSrc>); return((ref VBuffer <TDst> dst) => { getter(ref src); if (size > 0) { Contracts.Check(src.Length == size); } var srcValues = src.GetValues(); int count = srcValues.Length; var editor = VBufferEditor.Create(ref dst, src.Length, count); if (count > 0) { // REVIEW: This would be faster if there were loops for each std conversion. // Consider adding those to the Conversions class. for (int i = 0; i < count; i++) { conv(in srcValues[i], ref editor.Values[i]); } if (!src.IsDense) { var srcIndices = src.GetIndices(); srcIndices.CopyTo(editor.Indices); } } dst = editor.Commit(); }); }
public AssignmentColumn(PrimitiveDataViewType type, T[] values) : base(type, values) { }
/// <summary> /// Adds a VBuffer{T} valued column. /// </summary> public void AddColumn <T>(string name, ValueGetter <VBuffer <ReadOnlyMemory <char> > > getNames, PrimitiveDataViewType itemType, params VBuffer <T>[] values) { _host.CheckValue(getNames, nameof(getNames)); _host.CheckParam(itemType != null && itemType.RawType == typeof(T), nameof(itemType)); CheckLength(name, values); _columns.Add(new VBufferColumn <T>(itemType, values)); _getSlotNames.Add(name, getNames); _names.Add(name); }
/// <summary> /// Add key values metadata. /// </summary> /// <typeparam name="TValue">The value type of key values.</typeparam> /// <param name="builder">The <see cref="DataViewSchema.Metadata.Builder"/> to which to add the key values.</param> /// <param name="size">The size of key values vector.</param> /// <param name="valueType">The value type of key values. Its raw type must match <typeparamref name="TValue"/>.</param> /// <param name="getter">The getter delegate for the key values.</param> public static void AddKeyValues <TValue>(this DataViewSchema.Metadata.Builder builder, int size, PrimitiveDataViewType valueType, ValueGetter <VBuffer <TValue> > getter) => builder.Add(MetadataUtils.Kinds.KeyValues, new VectorType(valueType, size), getter);
public static InternalSchemaDefinition Create(Type userType, SchemaDefinition userSchemaDefinition) { Contracts.AssertValue(userType); Contracts.AssertValueOrNull(userSchemaDefinition); if (userSchemaDefinition == null) { userSchemaDefinition = SchemaDefinition.Create(userType); } Column[] dstCols = new Column[userSchemaDefinition.Count]; for (int i = 0; i < userSchemaDefinition.Count; ++i) { var col = userSchemaDefinition[i]; if (col.MemberName == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Null field name detected in schema definition"); } bool isVector; Type dataItemType; MemberInfo memberInfo = null; if (col.Generator == null) { memberInfo = userType.GetField(col.MemberName); if (memberInfo == null) { memberInfo = userType.GetProperty(col.MemberName); } if (memberInfo == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "No field or property with name '{0}' found in type '{1}'", col.MemberName, userType.FullName); } //Clause to handle the field that may be used to expose the cursor channel. //This field does not need a column. if ((memberInfo is FieldInfo && (memberInfo as FieldInfo).FieldType == typeof(IChannel)) || (memberInfo is PropertyInfo && (memberInfo as PropertyInfo).PropertyType == typeof(IChannel))) { continue; } GetVectorAndItemType(memberInfo, out isVector, out dataItemType); } else { var parameterType = col.ReturnType; if (parameterType == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "No return parameter found in computed column."); } GetVectorAndItemType("returnType", parameterType, null, out isVector, out dataItemType); } // Infer the column name. var colName = string.IsNullOrEmpty(col.ColumnName) ? col.MemberName : col.ColumnName; // REVIEW: Because order is defined, we allow duplicate column names, since producing an IDataView // with duplicate column names is completely legal. Possible objection is that we should make it less // convenient to produce "hidden" columns, since this may not be of practical use to users. DataViewType colType; if (col.ColumnType == null) { // Infer a type as best we can. PrimitiveDataViewType itemType = ColumnTypeExtensions.PrimitiveTypeFromType(dataItemType); colType = isVector ? new VectorDataViewType(itemType) : (DataViewType)itemType; } else { // Make sure that the types are compatible with the declared type, including // whether it is a vector type. VectorDataViewType columnVectorType = col.ColumnType as VectorDataViewType; if (isVector != (columnVectorType != null)) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Column '{0}' is supposed to be {1}, but type of associated field '{2}' is {3}", colName, columnVectorType != null ? "vector" : "scalar", col.MemberName, isVector ? "vector" : "scalar"); } DataViewType itemType = columnVectorType?.ItemType ?? col.ColumnType; if (itemType.RawType != dataItemType) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Column '{0}' is supposed to have item type {1}, but associated field has type {2}", colName, itemType.RawType, dataItemType); } colType = col.ColumnType; } dstCols[i] = col.Generator != null ? new Column(colName, colType, col.Generator, col.AnnotationInfos) : new Column(colName, colType, memberInfo, col.AnnotationInfos); } return(new InternalSchemaDefinition(dstCols)); }
private static Type GetRawType(PrimitiveDataViewType itemType) { Contracts.CheckValue(itemType, nameof(itemType)); return(typeof(VBuffer <>).MakeGenericType(itemType.RawType)); }