internal static void Reduce <T, C>(C op, long axis, NdArray <T> in1, NdArray <T> @out) where C : struct, IBinaryOp <T> { bool largeInput = in1.Shape.Dimensions[0].Length >= _no_blocks; bool largeOutput = @out.Shape.Dimensions[0].Length >= _no_blocks && @out.Shape.Dimensions[Math.Max(0, axis - 1)].Length >= _no_blocks; bool scalarReduction = axis == 0 && in1.Shape.Dimensions.LongLength == 1; bool doubleLargeInput = in1.Shape.Dimensions[0].Length >= (_no_blocks * 2); if ((SINGLE_CORE_THREAD || _no_blocks > 1) && ((largeInput && largeOutput) || (doubleLargeInput && scalarReduction))) { int totalblocks = _no_blocks; in1.DataAccessor.Allocate(); @out.DataAccessor.Allocate(); //Special handling required for 1D to scalar if (axis == 0 && in1.Shape.Dimensions.LongLength == 1) { //Allocate some temp storage T[] tmpout = new T[totalblocks]; _threads.RunParallel((block) => UFunc.UFunc_Reduce_Inner_Flush( op, axis, Reshape(in1, block, totalblocks), new NdArray <T>(tmpout, new Shape(new long[] { 1 }, block)) ) ); //Make the final reduction on the thread results T r = tmpout[0]; for (var i = 1; i < totalblocks; i++) { r = op.Op(r, tmpout[i]); } @out.Value[@out.Shape.Offset] = r; } else { _threads.RunParallel((block) => { var v1 = Reshape(in1, block, totalblocks, axis == 0 ? 1 : axis - 1); var v2 = Reshape(@out, block, totalblocks, axis == 0 ? 0 : axis - 1); UFunc.UFunc_Reduce_Inner_Flush(op, axis, v1, v2); }); } } else { UFunc.UFunc_Reduce_Inner_Flush(op, axis, in1, @out); } }
/// <summary> /// Calculates the scalar result of applying the binary operation to all elements /// </summary> /// <typeparam name="T">The value to operate on</typeparam> /// <typeparam name="C">The operation to perform</typeparam> /// <param name="op">The operation to reduce with</param> /// <param name="in1">The array to aggregate</param> /// <param name="result">A scalar value that is the result of aggregating all elements</param> /// <returns>True if the operation was applied, false otherwise</returns> public static void ApplyAggregate <T, C>(C op, NdArray <T> in1, out T result) where C : struct, IBinaryOp <T> { foreach (var n in _handlers) { if (n.Item2.ApplyAggregate <T, C>(op, in1, out result)) { return; } } //Fallback result = UFunc.UFunc_Aggregate_Inner_Flush <T, C>(op, in1); }
/// <summary> /// Performs matrix multiplication on the two operands, using the supplied methods, /// without using lazy evaluation. /// </summary> /// <typeparam name="T">The type of data to operate on</typeparam> /// <typeparam name="CADD">The typed add operator</typeparam> /// <typeparam name="CMUL">The typed multiply operator</typeparam> /// <param name="addop">The add operator</param> /// <param name="mulop">The multiply operator</param> /// <param name="in1">The left-hand-side argument</param> /// <param name="in2">The right-hand-side argument</param> /// <param name="out">An optional output argument, use for in-place operations</param> /// <returns>True if the operation was applied, false otherwise</returns> public static void ApplyMatmul <T, CADD, CMUL>(CADD addop, CMUL mulop, NdArray <T> in1, NdArray <T> in2, NdArray <T> @out = null) where CADD : struct, IBinaryOp <T> where CMUL : struct, IBinaryOp <T> { foreach (var n in _handlers) { if (n.Item2.ApplyMatmul <T, CADD, CMUL>(addop, mulop, in1, in2, @out)) { return; } } //Fallback UFunc.UFunc_Matmul_Inner_Flush <T, CADD, CMUL>(addop, mulop, in1, in2, @out); }
internal static void NullaryOp <T, C>(C op, NdArray <T> @out) where C : struct, INullaryOp <T> { if ((SINGLE_CORE_THREAD || _no_blocks > 1) && @out.Shape.Dimensions[0].Length >= _no_blocks) { int totalblocks = _no_blocks; @out.DataAccessor.Allocate(); _threads.RunParallel((block) => UFunc.UFunc_Op_Inner_Nullary_Flush(op, Reshape(@out, block, totalblocks)) ); } else { UFunc.UFunc_Op_Inner_Nullary_Flush(op, @out); } }
internal static void UnaryConvOp <Ta, Tb, C>(IUnaryConvOp <Ta, Tb> op, NdArray <Ta> in1, NdArray <Tb> @out) where C : struct, IUnaryConvOp <Ta, Tb> { if ((SINGLE_CORE_THREAD || _no_blocks > 1) && @out.Shape.Dimensions[0].Length >= _no_blocks) { int totalblocks = _no_blocks; in1.DataAccessor.Allocate(); @out.DataAccessor.Allocate(); _threads.RunParallel((block) => UFunc.UFunc_Op_Inner_UnaryConv_Flush( op, Reshape(in1, block, totalblocks), Reshape(@out, block, totalblocks) ) ); } else { UFunc.UFunc_Op_Inner_UnaryConv_Flush(op, in1, @out); } }