protected override ICallable CreateCallable(Type I, Type O) { var fields = I.GetFields().OrderBy(f => f.Name).ToArray(); IgnorableAssert.Assert(fields.Length == 2, $"Controlled must always accept two args: an array of control qubits and the operation normal input tuple. Got {I.FullName}"); IgnorableAssert.Assert(O == typeof(QVoid), $"Controlled can only be applied to Operations that return void. Received: {O.FullName}"); var baseArgsType = fields[1].FieldType; var op = this.BaseOp.FindCallable(baseArgsType, O); var ctrlOp = typeof(ControlledOperation <,>).MakeGenericType(MatchOperationTypes(baseArgsType, O, op.GetType())); var result = (ICallable)Activator.CreateInstance(ctrlOp, op); return(result); }
internal static A PopNextArgs <A>(Func <A[], A> build, int nrUndefined, Stack <A> args) { IgnorableAssert.Assert(args.Count != 0, "shape mismatch in partial tuple"); if (nrUndefined != 1 || args.Count == 1) { return(args.Pop()); } else { var content = new A[args.Count]; for (var i = 0; i < content.Length; i++) { content[i] = args.Pop(); } return(build(content)); } }
/// <summary> /// Because C# can't automatically cast from (IUnitary, long) to (ICallable, long), sigh... /// we do the work for it here... /// </summary> static public object CastTuple(Type targetType, object value) { if (targetType == typeof(QVoid)) { return(QVoid.Instance); } if (value == null) { return(null); } var valueType = value.GetType(); if (targetType.IsAssignableFrom(valueType)) { return(value); } if (valueType.BaseType.IsQTuple()) { return(CastTuple(targetType, valueType.BaseType.GetProperty("Data").GetValue(value))); } // See bug #779 if (targetType == typeof(Double)) { return(Double.Parse(value.ToString())); } else if (targetType == typeof(Int64)) { return(Int64.Parse(value.ToString())); } else if (targetType.IsTuple() && valueType.IsTuple()) { var targetFields = targetType.GetFields().OrderBy(f => f.Name).ToArray(); var valueFields = valueType.GetFields().OrderBy(f => f.Name).ToArray(); var values = new object[targetFields.Length]; Debug.Assert(targetFields.Length == valueFields.Length, $"Trying to cast tuples of different length. Expected {targetFields.Length}, but got {valueFields.Length}"); for (var i = 0; i < targetFields.Length; i++) { values[i] = CastTuple(targetFields[i].FieldType, valueFields[i].GetValue(value)); } return(Activator.CreateInstance(targetType, values)); } else if (targetType.IsQArray() && valueType.IsQArray()) { Debug.Assert(targetType.GenericTypeArguments[0].IsAssignableFrom(valueType.GenericTypeArguments[0]), "Trying to cast Arrays of different types."); return(Activator.CreateInstance(targetType, value)); } else if (targetType.IsPartialMapper() && valueType.IsPartialMapper()) { var tp = targetType.GenericTypeArguments[0]; var ti = targetType.GenericTypeArguments[1]; var vp = valueType.GenericTypeArguments[0]; var vi = valueType.GenericTypeArguments[1]; var gen = typeof(PartialMapper).GetMethod(nameof(CastPartialMapper), BindingFlags.NonPublic | BindingFlags.Static); var m = gen.MakeGenericMethod(tp, ti, vp, vi); return(m.Invoke(null, new object[] { value })); } else { IgnorableAssert.Assert(targetType.IsInstanceOfType(value) || (value == null && targetType.IsValueType == false), $"Invalid resolved value. Expected {targetType} but got {valueType}"); return(value); } }