public static Array <Real> Mul(this Array <Real> a, Array <Real> b, Array <Real> result = null)
 {
     return(Array_.ElementwiseOp(a, b, result,
                                 (n, x, offsetx, incx, y, offsety, incy, z, offsetz, incz) =>
     {
         if (incx == 1 && incy == 1 && incz == 1)
         {
             Blas.vmul(n, x, offsetx, y, offsety, z, offsetz);
         }
         else if (incx == 0)   // x[offsetx] is broadcast: y[:] * x[offsetx]
         {
             Blas.gemv(Order.RowMajor, Transpose.NoTrans, n, 1, 1, y, offsety, incy, x, offsetx, 1, 0, z, offsetz, incz);
         }
         //else if (incy == 0)   // y[offsety] is broadcast: x[:] * y[offsety]
         //    Blas.gemv(Order.RowMajor, Transpose.NoTrans, n, 1, 1, x, offsetx, incx, y, offsety, 1, 0, z, offsetz, incz);
         else    // when everything else fails, fallback to slow version
         {
             for (int i = 0; i < n; i++)
             {
                 z[offsetz] = x[offsetx] * y[offsety];
                 offsetx += incx;
                 offsety += incy;
                 offsetz += incz;
             }
         }
     }));
 }
Exemple #2
0
        private static void _EinsteinSum(int n, Einstein[] einstein,
                                         Array <float> x, int offX,
                                         Array <float> y, int offY,
                                         Array <float> z, int offZ
                                         )
        {
            if (n == einstein.Length)
            {
                z.Values[offZ] += x.Values[offX] * y.Values[offY];
                return;
            }

            var e = einstein[n];

            if (n == einstein.Length - 1)
            {
                switch (e.mode)
                {
                case EinsteinMode.ELEMENTWISE:
                    int axisX = (int)e.axisX, axisY = (int)e.axisY, axisZ = (int)e.axisZ;
                    if (x.Stride[axisX] == 1 && y.Stride[axisY] == 1 && z.Stride[axisZ] == 1)
                    {
                        Blas.vmul(x.Shape[axisX], x.Values, offX, y.Values, offY, z.Values, offZ);
                        return;
                    }
                    break;

                case EinsteinMode.OUTERX:
                    var axis = (int)e.axisX;
                    Blas.axpy(x.Shape[axis], y.Values[offY], x.Values, offX, x.Stride[axis], z.Values, offZ, z.Stride[(int)e.axisZ]);
                    return;

                case EinsteinMode.OUTERY:
                    axis = (int)e.axisY;
                    Blas.axpy(y.Shape[axis], x.Values[offX], y.Values, offY, y.Stride[axis], z.Values, offZ, z.Stride[(int)e.axisZ]);
                    return;
                }
            }

            switch (e.mode)
            {
            case EinsteinMode.INNER:
                for (int i = 0; i < x.Shape[(int)e.axisX]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offX += x.Stride[(int)e.axisX];
                    offY += y.Stride[(int)e.axisY];
                }
                return;

            case EinsteinMode.ELEMENTWISE:
                for (int i = 0; i < x.Shape[(int)e.axisX]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offX += x.Stride[(int)e.axisX];
                    offY += y.Stride[(int)e.axisY];
                    offZ += z.Stride[(int)e.axisZ];
                }
                return;

            case EinsteinMode.OUTERX:
                var axis = (int)e.axisX;
                for (int i = 0; i < x.Shape[axis]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offX += x.Stride[axis];
                    offZ += z.Stride[(int)e.axisZ];
                }
                return;

            case EinsteinMode.OUTERY:
                axis = (int)e.axisY;
                for (int i = 0; i < y.Shape[axis]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offY += y.Stride[axis];
                    offZ += z.Stride[(int)e.axisZ];
                }
                return;

            case EinsteinMode.SUMX:
                axis = (int)e.axisX;
                for (int i = 0; i < x.Shape[axis]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offX += x.Stride[axis];
                }
                return;

            case EinsteinMode.SUMY:
                axis = (int)e.axisY;
                for (int i = 0; i < y.Shape[axis]; ++i)
                {
                    _EinsteinSum(n + 1, einstein, x, offX, y, offY, z, offZ);
                    offY += y.Stride[axis];
                }
                return;
            }
        }