Пример #1
0
        /// <summary>
        /// Repeats elements of the array
        /// </summary>
        /// <param name="repeats">The number of repeats to perform</param>
        /// <param name="axis">The axis to repeat, if not speficied, repeat is done on a flattened array</param>
        /// <returns>A repeated copy of the input data</returns>
        public NdArray <T> Repeat(long repeats, long?axis = null)
        {
            long real_axis =
                axis.HasValue ?
                (axis.Value < 0 ? this.Shape.Dimensions.LongLength - (axis.Value + 1) : (axis.Value + 1))
                : this.Shape.Dimensions.LongLength;

            //First we add a new axis so all elements are in their own dimension
            var lv = this.Subview(Range.NewAxis, real_axis);

            //Then we extend the element dimension, and make the shapes match
            long[] targetDims = lv.Shape.Dimensions.Select(x => x.Length).ToArray();
            targetDims[real_axis] = repeats;
            var tp = Shape.ToBroadcastShapes(lv.Shape, new Shape(targetDims));

            //And then we can just copy data as normal
            var res = UFunc.Apply <T, CopyOp <T> >(lv.Reshape(tp.Item1), new NdArray <T>(tp.Item2));

            //With no axis specified, we return a flat view
            if (!axis.HasValue)
            {
                return(new NdArray <T>(res.m_data));
            }
            else
            {
                //With a specified axis, we return a reshaped array
                long[] newDims = this.Shape.Dimensions.Select(x => x.Length).ToArray();
                newDims[real_axis - 1] = repeats * newDims[real_axis - 1];
                return(res.Reshape(newDims));
            }
        }
Пример #2
0
        /// <summary>
        /// Sets all elements in the view to a specific value
        /// </summary>
        /// <param name="value">The value to set the elements to</param>
        public void Set(T value)
        {
            var tmp = new NdArray <T>(value);

            tmp = tmp.Reshape(Shape.ToBroadcastShapes(tmp.Shape, this.Shape).Item1);
            UFunc.Apply <T, CopyOp <T> >(tmp, this);
        }
Пример #3
0
        /// <summary>
        /// Generates an NdArray with all elements set to a random value
        /// </summary>
        /// <param name="shape">The shape of the generated array</param>
        /// <returns>An NdArray with all elements set to a random value</returns>
        public virtual NdArray <T> Random(Shape shape)
        {
            var x = new NdArray <T>(shape);

            UFunc.Apply <T, TRand>(new TRand(), x);
            return(x);
        }
Пример #4
0
        /// <summary>
        /// Generates an NdArray with sequential integers, starting with zero
        /// </summary>
        /// <param name="shape">The shape of the generated array</param>
        /// <returns>A shaped NdArray with sequential integers, starting with zero</returns>
        public NdArray <T> Range(Shape shape)
        {
            var x = new NdArray <T>(shape);

            UFunc.Apply <T, TRange>(new TRange(), x);
            return(x);
        }
Пример #5
0
        /// <summary>
        /// Generates an NdArray with all elements set to a random value
        /// </summary>
        /// <param name="size">The length of the generated array</param>
        /// <returns>An NdArray with all elements set to a random value</returns>
        public virtual NdArray <T> Random(long size)
        {
            var x = new NdArray <T>(new Shape(size));

            UFunc.Apply <T, TRand>(new TRand(), x);
            return(x);
        }
Пример #6
0
        /// <summary>
        /// Generates an NdArray with sequential integers, starting with zero
        /// </summary>
        /// <param name="size">The length of the generated array</param>
        /// <returns>An NdArray with sequential integers, starting with zero</returns>
        public NdArray <T> Range(long size)
        {
            var x = new NdArray <T>(new Shape(size));

            UFunc.Apply <T, TRange>(new TRange(), x);
            return(x);
        }
Пример #7
0
 /// <summary>
 /// Gets a subview on the array, collapses all single dimensions
 /// </summary>
 /// <param name="ranges">The range get the view from</param>
 /// <returns>A view on the selected element</returns>
 public NdArray <T> this[params Range[] ranges]
 {
     get
     {
         return(this.Subview(ranges, true));
     }
     set
     {
         NdArray <T> lv = this[ranges];
         var         broadcastShapes = Shape.ToBroadcastShapes(value.Shape, lv.Shape);
         UFunc.Apply <T, NumCIL.CopyOp <T> >(value.Reshape(broadcastShapes.Item1), lv.Reshape(broadcastShapes.Item2));
     }
 }
Пример #8
0
        /// <summary>
        /// Returns a transposed view of this array. If <paramref name="out"/> is supplied, the contents are copied into that array.
        /// </summary>
        /// <param name="out">Optional output array</param>
        /// <returns>A transposed view or copy</returns>
        public NdArray <T> Transpose(NdArray <T> @out = null)
        {
            if (this.Shape.Dimensions.LongLength == 1)
            {
                return(new NdArray <T>(this));
            }

            //Optimal case, just reshape the array
            if (@out == null)
            {
                return(this.Reshape(new Shape(this.Shape.Dimensions.Reverse().ToArray())));
            }

            var lv = this.Reshape(new Shape(this.Shape.Dimensions.Select(x => x.Length).Reverse().ToArray()));

            UFunc.Apply <T, CopyOp <T> >(lv, @out);
            return(@out);
        }
Пример #9
0
        /// <summary>
        /// Gets a subview on the array
        /// </summary>
        /// <param name="index">The element to get the view from</param>
        /// <returns>A view on the selected element</returns>
        public NdArray <T> this[params long[] index]
        {
            get
            {
                NdArray <T> v = this;
                foreach (long n in index)
                {
                    v = v.Subview(n);
                }

                return(v);
            }
            set
            {
                NdArray <T> lv = this[index];

                //Self-assignment
                if (lv.Shape.Equals(value.Shape) && value.m_data == this.m_data)
                {
                    return;
                }


                if (lv.Shape.Dimensions.Length != value.Shape.Dimensions.Length)
                {
                    throw new Exception("Cannot assign incompatible arrays");
                }

                for (long i = 0; i < lv.Shape.Dimensions.Length; i++)
                {
                    if (lv.Shape.Dimensions[i].Length != value.Shape.Dimensions[i].Length)
                    {
                        throw new Exception("Cannot assign incompatible arrays");
                    }
                }

                UFunc.Apply <T, NumCIL.CopyOp <T> >(value, lv);
            }
        }
Пример #10
0
        /// <summary>
        /// Concatenates multiple arrays into a single array, joined at the axis
        /// </summary>
        /// <param name="axis">The axis to join at</param>
        /// <param name="args">The arrays to join</param>
        /// <returns>The joined array</returns>
        public static NdArray <T> Concatenate(NdArray <T>[] args, long axis = 0)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            if (args.LongLength == 1)
            {
                return(args[0]);
            }

            Shape basicShape = args[0].Shape.Plain;

            NdArray <T>[] ext = new NdArray <T> [args.LongLength];

            foreach (var a in args)
            {
                if (a.Shape.Elements != 1)
                {
                    basicShape = a.Shape.Plain;
                    break;
                }
            }

            for (long i = 0; i < args.LongLength; i++)
            {
                var lv = args[i];
                while (lv.Shape.Dimensions.LongLength <= axis)
                {
                    lv = lv.Subview(Range.NewAxis, 0);
                }

                ext[i] = lv;
            }

            long newAxisSize = 0;

            foreach (var a in ext)
            {
                newAxisSize += a.Shape.Dimensions[axis].Length;
            }

            long[] dims = basicShape.Plain.Dimensions.Select(x => x.Length).ToArray();
            dims[Math.Min(axis, dims.LongLength - 1)] = newAxisSize;
            var res   = new NdArray <T>(new Shape(dims));
            var reslv = res;

            while (reslv.Shape.Dimensions.LongLength <= axis)
            {
                reslv = reslv.Subview(Range.NewAxis, 0);
            }


            foreach (var a in ext)
            {
                if (a.Shape.Dimensions.LongLength != reslv.Shape.Dimensions.LongLength)
                {
                    throw new Exception(string.Format("Incompatible shapes, size {0} vs {1}", a.Shape.Dimensions.LongLength, reslv.Shape.Dimensions.LongLength));
                }

                for (long i = 0; i < dims.LongLength; i++)
                {
                    if (i != axis && reslv.Shape.Dimensions[i].Length != a.Shape.Dimensions[i].Length)
                    {
                        throw new Exception(string.Format("Incompatible shapes, sizes in dimension {0} is {1} vs {2}", i, a.Shape.Dimensions[i].Length, reslv.Shape.Dimensions[i].Length));
                    }
                }
            }

            long startOffset = 0;

            foreach (NdArray <T> a in ext)
            {
                long endOffset = startOffset + a.Shape.Dimensions[axis].Length;
                var  lv        = reslv.Subview(new Range(startOffset, endOffset), axis);
                UFunc.Apply <T, CopyOp <T> >(a, lv);
                startOffset = endOffset;
            }

            return(res);
        }
Пример #11
0
        /// <summary>
        /// Repeats elements of the array
        /// </summary>
        /// <param name="repeats">The number of repeats to perform in each axis</param>
        /// <param name="axis">The axis to repeat, if not specified, repeat is done on a flattened array</param>
        /// <returns>A repeated copy of the input data</returns>
        public NdArray <T> Repeat(long[] repeats, long?axis = null)
        {
            long real_axis =
                axis.HasValue ?
                (axis.Value < 0 ? this.Shape.Dimensions.LongLength - axis.Value : axis.Value)
                : this.Shape.Dimensions.LongLength;

            if (!axis.HasValue)
            {
                //Inefficient because we need to access each element

                long elements = this.Shape.Elements;
                if (elements % repeats.LongLength != 0)
                {
                    throw new ArgumentException(string.Format("The repeats array has length {0} and is not broadcast-able to length {1}", repeats.LongLength, elements), "repeats");
                }

                //We need to be able to address each element individually,
                // so we do not use tricks stride tricks and
                // just copy each element individually
                long resultSize = 0;
                for (long i = 0; i < elements; i++)
                {
                    resultSize += repeats[i % repeats.LongLength];
                }

                T[] result = new T[resultSize];

                long[] counters = new long[this.Shape.Dimensions.LongLength];
                long[] limits   = this.Shape.Dimensions.Select(x => x.Length).ToArray();
                var    va       = this.Value;
                long   resCount = 0;
                //The we remove all the outer axis definitions, but preserve the stride for each element
                for (long i = 0; i < elements; i++)
                {
                    T value = va[counters];
                    for (long j = 0; j < repeats[i % repeats.LongLength]; j++)
                    {
                        result[resCount++] = value;
                    }

                    //Basically a ripple carry adder
                    long p = counters.LongLength - 1;
                    while (++counters[p] == limits[p] && p > 0)
                    {
                        counters[p] = 0;
                        p--;
                    }
                }

                return(new NdArray <T>(result));
            }
            else
            {
                if (this.Shape.Dimensions[real_axis].Length % repeats.LongLength != 0)
                {
                    throw new ArgumentException(string.Format("The repeats array has length {0} and is not broadcast-able to length {1}", repeats.LongLength, this.Shape.Dimensions[real_axis].Length), "repeats");
                }

                long resultSize = 1;
                if (repeats.LongLength != this.Shape.Dimensions[real_axis].Length)
                {
                    long[] tmp = new long[this.Shape.Dimensions[real_axis].Length];
                    for (long i = 0; i < tmp.LongLength; i++)
                    {
                        tmp[i] = repeats[i % repeats.LongLength];
                    }
                    repeats = tmp;
                }

                long extendedSize = repeats.Aggregate((a, b) => a + b);

                for (long i = 0; i < this.Shape.Dimensions.LongLength; i++)
                {
                    if (i == real_axis)
                    {
                        resultSize *= extendedSize;
                    }
                    else
                    {
                        resultSize *= this.Shape.Dimensions[i].Length;
                    }
                }

                long[] resultDims = this.Shape.Dimensions.Select(x => x.Length).ToArray();
                resultDims[real_axis] = extendedSize;
                var resultShape = new Shape(resultDims);
                var result      = new NdArray <T>(resultShape);

                long curStart = 0;
                for (long i = 0; i < repeats.LongLength; i++)
                {
                    var lv = this.Subview(Range.El(i), real_axis);
                    var xv = result.Subview(new Range(curStart, curStart + repeats[i]), real_axis);
                    var broadcastShapes = Shape.ToBroadcastShapes(lv.Shape, xv.Shape);
                    UFunc.Apply <T, CopyOp <T> >(lv.Reshape(broadcastShapes.Item1), xv.Reshape(broadcastShapes.Item2));
                    curStart += repeats[i];
                }

                return(result);
            }
        }
Пример #12
0
 /// <summary>
 /// Returns a copy of the underlying data, shaped as this view
 /// </summary>
 /// <returns>A copy of the view data</returns>
 public NdArray <T> Clone()
 {
     return(UFunc.Apply <T, CopyOp <T> >(this));
 }
Пример #13
0
        /// <summary>
        /// Sets the values in this view to values from another view, i.e. copies data
        /// </summary>
        /// <param name="value">The data to assign to this view</param>
        public void Set(NdArray <T> value)
        {
            var broadcastShapes = Shape.ToBroadcastShapes(value.Shape, this.Shape);

            UFunc.Apply <T, NumCIL.CopyOp <T> >(value.Reshape(broadcastShapes.Item1), this.Reshape(broadcastShapes.Item2));
        }
Пример #14
0
        public static void RunTests()
        {
            var an = Generate.Empty(2000);
            var bn = Generate.Ones(2000);

            var cn = Generate.Empty(2000);
            var dn = Generate.Ones(2000);

            var an0 = an.Value[0];
            var bn0 = bn.Value[0];

            if (bn0 != 1)
            {
                throw new Exception("Error in accessor");
            }

            cn.Value[0] = 1;
            dn.Value[0] = 2;

            var cn0 = cn.Value[0];
            var dn0 = dn.Value[0];

            if (cn0 != 1 || dn0 != 2)
            {
                throw new Exception("Error in accessor");
            }

            var test = Generate.Range(3) * 4;

            test.Transpose();

            Shape s = new Shape(
                new long[] { 2, 1, 2, 3 },  //Dimension sizes
                6,                          //Offset
                new long[] { 18, 18, 6, 1 } //Strides
                );

            var a = Generate.Range(s.Length);
            var b = a.Reshape(s);
            var c = b[1][0][1];
            var d = c[2];
            var e = b.Flatten();

            if (e.AsArray().LongLength != 12 || e.AsArray()[3] != 12)
            {
                throw new Exception("Failure in flatten");
            }

            List <T> fln = new List <T>(b[1, 0, 1].Value);

            if (fln.Count != 3)
            {
                throw new Exception("Failure in basic test 1");
            }
            if (fln[0] != 30)
            {
                throw new Exception("Failure in basic test 2");
            }
            if (fln[1] != 31)
            {
                throw new Exception("Failure in basic test 3");
            }
            if (fln[2] != 32)
            {
                throw new Exception("Failure in basic test 4");
            }

            T n = b.Value[1, 0, 1, 2];

            if (n != 32)
            {
                throw new Exception("Failure in basic test 5");
            }
            if (c.Value[2] != 32)
            {
                throw new Exception("Failure in basic test 6");
            }
            if (c.Value[0] != 30)
            {
                throw new Exception("Failure in basic test 7");
            }
            if (c.Value[1] != 31)
            {
                throw new Exception("Failure in basic test 8");
            }
            if (b.Sum() != 228)
            {
                throw new Exception("Failure in basic test 9");
            }

            var r1 = Generate.Range(12).Reshape(new long[] { 2, 1, 2, 3 });

            if (!Equals(r1.AsArray(), new T[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }))
            {
                throw new Exception("Failure in basic test 10");
            }
            var r2 = r1.Reduce <Add>(0);

            //if (!Equals(r2.AsArray(), new T[] { 6, 8, 10, 12, 14, 16 })) throw new Exception("Failure in basic test 11");
            r2 = r1.Reduce <Add>(1);
            var xxx = r2.AsArray();

            if (!Equals(xxx, new T[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }))
            {
                throw new Exception("Failure in basic test 12");
            }

            r2 = r1.Reduce <Add>(2);
            var yyy = r2.AsArray();

            if (!Equals(yyy, new T[] { 3, 5, 7, 15, 17, 19 }))
            {
                throw new Exception("Failure in basic test 13");
            }

            //r2 = Add.Reduce(r1, 3);

            Console.WriteLine("Running problem test");
            r2 = r1.Reduce <Add>(3);
            var nnn = r2.AsArray();

            if (!Equals(nnn, new T[] { 3, 12, 21, 30 }))
            {
                throw new Exception(string.Format("Failure in basic test 14: {0}", string.Join(", ", nnn.Select(x => x.ToString()))));
            }

            var r3 = b.Reduce <Add>();

            if (!Equals(r3.AsArray(), new T[] { 30, 32, 34, 42, 44, 46 }))
            {
                throw new Exception("Failure in basic test 15");
            }

            var x1 = Generate.Range(12).Reshape(new long[] { 4, 3 });
            var x2 = Generate.Range(3);

            var x3 = x1 + x2;

            var sqrd = x3.Sqrt();

            sqrd *= sqrd;
            sqrd  = sqrd.Round();
            sqrd += 4;
            sqrd++;

            if (UFunc.Reduce <T, Add>(UFunc.Reduce <T, Add>(sqrd, 0)).Value[0] != 138)
            {
                throw new Exception("Failure in basic arithmetics");
            }
            if (UFunc.Reduce <T, Add>(UFunc.Reduce <T, Add>(sqrd, 1)).Value[0] != 138)
            {
                throw new Exception("Failure in basic arithmetics");
            }

            var x5 = sqrd.Apply((x) => x % 2 == 0 ? x : -x);

            if (!Equals(x5.AsArray(), new T[] { -5, -7, -9, 8, 10, 12, -11, -13, -15, 14, 16, 18 }))
            {
                throw new Exception("Failure in basic test 16");
            }

            NumCIL.UFunc.Apply <T, Add>(x1, x2, x3);
            NumCIL.Double.NdArray x4 = (NumCIL.Double.NdArray)x3;
            if (!Equals(x4.AsArray(), new double[] { 0, 2, 4, 3, 5, 7, 6, 8, 10, 9, 11, 13 }))
            {
                throw new Exception("Failure in basic test 17");
            }

            var x6 = Generate.Range(6).Reshape(new long[] { 2, 3 });

            var x7 = x6.Reduce <Add>();

            var rx7 = x7.AsArray();

            if (!Equals(rx7, new T[] { 3, 5, 7 }))
            {
                throw new Exception(string.Format("Failure in basic test: [{0}]", string.Join(", ", rx7.Select(x => x.ToString()).ToArray())));
            }

            var x8  = Generate.Range(10) * 0.5f;
            var rx8 = x8.Reduce <Add>().Value[0];

            if (rx8 != 22.5)
            {
                throw new Exception(string.Format("Failure in broadcast multiply 1: {0}", rx8));
            }

            var x9  = Mul.Apply(Generate.Range(10), 0.5f);
            var rx9 = x9.Reduce <Add>().Value[0];

            if (rx9 != 22.5)
            {
                throw new Exception(string.Format("Failure in broadcast multiply 2: {0}", rx9));
            }

            var x10 = 5 - Generate.Range(10);
            var x11 = Generate.Range(10) - 5;

            if (x10.Sum() != 5 || x11.Sum() != -5)
            {
                throw new Exception("Failure in scalar rhs/lhs");
            }

            var n0 = Generate.Range(4);
            var n1 = n0[new Range(1, 4)];
            var n2 = n0[new Range(0, 3)];
            var n3 = n1 - n2;

            if (n3.Reduce <Add>().Value[0] != 3)
            {
                throw new Exception("Failure in basic slicing");
            }

            var z0 = Generate.Range(new long[] { 2, 2, 3 });
            var z1 = z0[Range.All, Range.All, Range.El(1)];
            var z2 = z0[Range.All, Range.El(1), Range.El(1)];
            var z3 = z0[Range.El(1), Range.El(1), Range.All];
            var z4 = z0[Range.El(0), Range.El(1), Range.El(1)];
            var z5 = z0[Range.El(0)];

            if (z1.Shape.Elements != 4)
            {
                throw new Exception("Reduced range failed");
            }
            if (z2.Shape.Elements != 2 || z2.Shape.Dimensions.LongLength != 1)
            {
                throw new Exception("Reduced range failed");
            }
            if (z3.Shape.Elements != 3 || z3.Shape.Dimensions.LongLength != 1)
            {
                throw new Exception("Reduced range failed");
            }
            if (z4.Shape.Elements != 1 || z4.Shape.Dimensions.LongLength != 1)
            {
                throw new Exception("Reduced range failed");
            }
            if (z5.Shape.Elements != 6 || z5.Shape.Dimensions.LongLength != 2)
            {
                throw new Exception("Reduced range failed");
            }


            var y1 = Generate.Range(9).Reshape(new long[] { 3, 3 });
            var y2 = y1.Transposed;

            y1 = y1.Transposed;
            var y3 = y1 + y2;

            if (y3.Value[0, 2] != 12)
            {
                throw new Exception("Failure with double transpose");
            }

            var y4 = Generate.Range(2 * 2 * 2 * 2 * 2).Reshape(new long[] { 2, 2, 2, 2, 2 });
            var y5 = y4 * (Generate.Range(2) + 1);

            if (y5.Sum() != 752)
            {
                throw new Exception("Failure with 5 dimensions");
            }

            var y6 = Generate.Range(2 * 2 * 2 * 2 * 2 * 2).Reshape(new long[] { 2, 2, 2, 2, 2, 2 });
            var y7 = y6 * (Generate.Range(2) + 1);

            if (y7.Sum() != 3040)
            {
                throw new Exception("Failure with 6 dimensions");
            }

            var r    = Generate.Random(2000);
            var rmin = Min.Aggregate(r);
            var rmax = Max.Aggregate(r);
            var ravg = Add.Aggregate(r) / r.DataAccessor.Length;

            if (rmin < 0 || rmax > 1.0)
            {
                throw new Exception("Error in random");
            }
            if (ravg < 0.4 || ravg > 0.6)
            {
                throw new Exception("Deviation in random average");
            }
        }