/// <summary> /// Evaluates dot operation of vector/matrix lazily. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="x"> [<c>x.Rank == 1 || x.Rank == 2</c>] </param> /// <param name="y"> [<c>y.Rank == 1 || y.Rank == 2</c>] </param> /// <returns> /// <para> The result of dot operation of <paramref name="x"/> and <paramref name="y"/>. </para> /// <para> - If <c>x.Shape == {p} && y.Rank == {p}</c>, then <c>$ReturnValue.Shape == {1}</c>. </para> /// <para> - If <c>x.Shape == {p} && y.Shape == {p, n}</c>, then <c>$ReturnValue.Shape == {n}</c>. </para> /// <para> - If <c>x.Shape == {m, p} && y.Shape == {p}</c>, then <c>$ReturnValue.Shape == {m}</c>. </para> /// <para> - If <c>x.Shape == {m, p} && y.Shape == {p, n}</c>, then <c>$ReturnValue.Shape == {m, n}</c>. </para> /// <para> - If the shape patterns does not match with above patterns, throw <see cref="ShapeMismatchException"/>. </para> /// </returns> /// <exception cref="ShapeMismatchException"></exception> public static NdArray <T> Dot <T>(this NdArray <T> x, NdArray <T> y) { var xEntity = x.GetOrCopyBuffer(); switch (y.Rank) { case 1: var yEntity = y.GetOrCopyBuffer(); switch (x.Rank) { case 1: return(Dot1x1(xEntity, yEntity)); case 2: return(Dot2x1(xEntity, yEntity)); default: break; } break; case 2: var yTEntity = y.Transpose().ToMutable().GetOrCopyBuffer(); switch (x.Rank) { case 1: return(Dot1x2(xEntity, yTEntity)); case 2: return(Dot2x2(xEntity, yTEntity)); default: break; } break; default: break; } Guard.ThrowShapeMismatch($"The ranks of x and y must be 1 or 2. (x.Rank={x.Rank}, y.Rank={y.Rank})"); throw new NotSupportedException(); }