Пример #1
0
        public override double[,,] GetOutput(ref double[,,] input)
        {
            cache_input       = (double[, , ])input.Clone();
            double[,,] output = new double[output_size[0], output_size[1], output_size[2]];

            int depth  = input_size[0];
            int height = input_size[1];
            int width  = input_size[2];

            for (int z = 0; z < depth; z++)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        output[z, y / this.height, x / this.width] = Math.Max(output[z, y / this.height, x / this.width], input[z, y, x]);
                    }
                }
            }

            cache_diff = func.Diff(output);
            output     = func.FastFunc(output);

            cache_sum = (double[, , ])output.Clone();

            return(output);
        }
Пример #2
0
        private static double[,,] processImage(double[,,] arrayImage, Action <ColorCustom> pixelAction)
        {
            double[,,] res = (double[, , ])arrayImage.Clone();

            int width  = arrayImage.GetLength(2),
                height = arrayImage.GetLength(1);

            ColorCustom c = new ColorCustom();

            for (int h = 0; h < height; h++)
            {
                for (int w = 0; w < width; w++)
                {
                    c.r = res[0, h, w];
                    c.g = res[1, h, w];
                    c.b = res[2, h, w];


                    pixelAction(c);

                    res[0, h, w] = c.r;
                    res[1, h, w] = c.g;
                    res[2, h, w] = c.b;
                }
            }

            return(res);
        }
Пример #3
0
        double[][,,] GetBackwardErrors(double[,,] input, double[,,] t, out double err, out List <KeyValuePair <double[, , ], double[, , ]> > getOutput)
        {
            double[][,,] errors = new double[layers.Count][, , ];
            var out_pairs = GetOutAndDiff(input);

            double[,,] output = out_pairs.Last().Key;

            //Console.WriteLine("{0} {1}", (float)output[0, 0, 0], (float)output[0, 0, 1]);

            int depth2  = output.GetLength(0);
            int height2 = output.GetLength(1);
            int width2  = output.GetLength(2);

            double val  = 0;
            double temp = 0;

            double[,,] out_err = (double[, , ])t.Clone();

            double[,,] diff = out_pairs.Last().Value;

            for (int z2 = 0; z2 < depth2; z2++)
            {
                for (int y2 = 0; y2 < height2; y2++)
                {
                    for (int x2 = 0; x2 < width2; x2++)
                    {
                        temp = t[z2, y2, x2] - output[z2, y2, x2];
                        out_err[z2, y2, x2] = -temp * diff[z2, y2, x2];
                        val += temp * temp;
                    }
                }
            }

            errors[errors.Length - 1] = out_err;

            for (int i = layers.Count - 1; i >= 0; i--)
            {
                Layer prev = null;
                if (i != 0)
                {
                    prev = layers[i - 1];
                    if (prev != null)
                    {
                        errors[i - 1] = layers[i].GetError(errors[i], out_pairs[i - 1].Value, out_pairs[i - 1].Key);
                    }
                    else
                    {
                        double[,,] diff2 = (double[, , ])input.Clone();
                        diff2.ForEach(x => 1);
                        errors[i - 1] = layers[i].GetError(errors[i], diff2, input);
                    }
                }
            }

            err       = val;
            getOutput = out_pairs;

            return(errors);
        }
Пример #4
0
 public frmPlotPSO(double[,,] PlotSwarmPsition, double[,] PlotGlobalPosition)
 {
     InitializeComponent();
     plotSwarmPositions  = (double[, , ])PlotSwarmPsition.Clone();
     plotGlobalPositions = (double[, ])PlotGlobalPosition.Clone();
     maxIter             = plotSwarmPositions.GetLength(0);
     maxSwarm            = plotSwarmPositions.GetLength(1);
 }
Пример #5
0
 /// <summary>
 /// Получить вызод сети
 /// </summary>
 /// <param name="input"></param>
 /// <returns></returns>
 public virtual double[,,] GetOutput(double[,,] input)
 {
     double[,,] output = (double[, , ])input.Clone();
     for (int i = 0; i < layers.Count; i++)
     {
         output = layers[i].GetOutput(output);
     }
     return(output);
 }
Пример #6
0
        public double[,,] Func(double[,,] val)
        {
            double sum = 0;

            val.ForEach(x => { sum += x * x; });
            sum += c;
            double[,,] result = (double[, , ])val.Clone();
            result.ForEach(x => x * x / sum);
            return(result);
        }
Пример #7
0
        KeyValuePair <double, double[, , ]> SetBackwardErrors(double[,,] input, double[,,] t)
        {
            double[,,] output = GetOutput(input);

            //Console.WriteLine("{0} {1}", (float)output[0, 0, 0], (float)output[0, 0, 1]);

            int depth2  = output.GetLength(0);
            int height2 = output.GetLength(1);
            int width2  = output.GetLength(2);

            double val  = 0;
            double temp = 0;

            double[,,] out_err = errors.Last();

            double[,,] diff = layers.Last().GetCachedDiff();

            for (int z2 = 0; z2 < depth2; z2++)
            {
                for (int y2 = 0; y2 < height2; y2++)
                {
                    for (int x2 = 0; x2 < width2; x2++)
                    {
                        temp = t[z2, y2, x2] - output[z2, y2, x2];
                        out_err[z2, y2, x2] = -temp * diff[z2, y2, x2];
                        val += temp * temp;
                    }
                }
            }

            errors[errors.Count - 1] = out_err;

            for (int i = layers.Count - 1; i >= 0; i--)
            {
                Layer prev = null;
                if (i != 0)
                {
                    prev = layers[i - 1];
                    if (prev != null)
                    {
                        errors[i - 1] = layers[i].GetError(errors[i], prev.GetCachedDiff(), prev.GetCachedOutpur());
                    }
                    else
                    {
                        double[,,] diff2 = (double[, , ])input.Clone();
                        diff2.ForEach(x => 1);
                        errors[i - 1] = layers[i].GetError(errors[i], diff2, input);
                    }
                }
            }

            return(new KeyValuePair <double, double[, , ]>(val, output));
        }
Пример #8
0
        public List <KeyValuePair <double[, , ], double[, , ]> > GetOutAndDiff(double[,,] input)
        {
            List <KeyValuePair <double[, , ], double[, , ]> > pairs = new List <KeyValuePair <double[, , ], double[, , ]> >();

            double[,,] output = (double[, , ])input.Clone();
            for (int i = 0; i < layers.Count; i++)
            {
                KeyValuePair <double[, , ], double[, , ]> pair = layers[i].GetOutputAndDiff(output);
                output = pair.Key;
                pairs.Add(pair);
            }
            return(pairs);
        }
    /// <summary>
    /// Constructor for temp double image format
    /// </summary>
    /// <param name="input">Input bitmap as three dimensional (widht, height, channels per pixel) double array</param>
    /// <param name="createCopy">True if you want to create copy of data</param>
    public TempDoubleImageFormat(double[,,] input, bool createCopy = false)
    {
        if (createCopy)
        {
            this.content3d = (double[, , ])input.Clone();
        }
        else
        {
            this.content3d = input;
        }

        this.content1d        = null;
        this.width            = input.GetLength(0);
        this.height           = input.GetLength(1);
        this.channelsPerPixel = input.GetLength(2);
    }
        private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileWindow = new OpenFileDialog();

            if (openFileWindow.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmp = new Bitmap(openFileWindow.FileName);

                //storing image info
                m_workImage     = BitmapConverter.BitmapToDoubleRgb(bmp);
                m_originalImage = (double[, , ])m_workImage.Clone();
                m_imageName     = Path.GetFileNameWithoutExtension(openFileWindow.FileName);

                //fill fields with image height and width
                textBox1.Text = String.Format("Ширина: {0}{2}Висота: {1}", bmp.Width, bmp.Height, Environment.NewLine);
                SubdivisionWidthTextBox.Text  = bmp.Width.ToString();
                SubdivisionHeightTextBox.Text = bmp.Height.ToString();

                OutputBitmapOnPictureBox(bmp);
            }
        }
Пример #11
0
        public override double[,,] GetOutput(ref double[,,] input)
        {
            double[,,] output = doubleArrayExtensions.CreateArray(output_size);

            int depth1  = output_size[0];
            int height1 = output_size[1];
            int width1  = output_size[2];

            int depth2  = input.GetLength(0);
            int height2 = input.GetLength(1);
            int width2  = input.GetLength(2);

            for (int z1 = 0; z1 < depth1; z1++)
            {
                for (int y1 = 0; y1 < height1; y1++)
                {
                    for (int x1 = 0; x1 < width1; x1++)
                    {
                        double val = 0;
                        for (int z2 = 0; z2 < depth2; z2++)
                        {
                            for (int y2 = 0; y2 < height2; y2++)
                            {
                                for (int x2 = 0; x2 < width2; x2++)
                                {
                                    val += weights[z1, y1, x1, z2, y2, x2] * input[z2, y2, x2];
                                }
                            }
                        }

                        output[z1, y1, x1] = val;
                    }
                }
            }

            cache_sum = (double[, , ])output.Clone();

            return(func.Func(output));
        }
        private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            segmented = null;

            ResetScrollsBarsValues();

            OpenFileDialog openFileWindow = new OpenFileDialog();

            if (openFileWindow.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmp = new Bitmap(openFileWindow.FileName);
                m_workImage     = BitmapConverter.BitmapToDoubleRgb(bmp);
                m_originalImage = (double[, , ])m_workImage.Clone();


                m_imageName = Path.GetFileNameWithoutExtension(openFileWindow.FileName);

                //pictureBox1.Width = bmp.Width;
                //pictureBox1.Height = bmp.Height;
                //pictureBox1.Image = bmp;

                OutputBitmapOnPictureBox(bmp);
            }
        }
Пример #13
0
        protected virtual double[][,,] GetBackwardErrors(double[,,] input, double[,,] t, out double err, int pos)
        {
            GetOutAndDiff(input, pos);

            double[,,] output = cached_outputs[pos].Last();

            //Console.WriteLine("{0} {1}", (float)output[0, 0, 0], (float)output[0, 0, 1]);

            int depth2  = output.GetLength(0);
            int height2 = output.GetLength(1);
            int width2  = output.GetLength(2);


            double[,,] out_err = (double[, , ])t.Clone();
            loss.Error(output, t, out_err);

            double[,,] diff = cached_diffs[pos].Last();

            #region  асчет ошибки конечного слоя
            for (int z2 = 0; z2 < depth2; z2++)
            {
                for (int y2 = 0; y2 < height2; y2++)
                {
                    for (int x2 = 0; x2 < width2; x2++)
                    {
                        out_err[z2, y2, x2] *= -diff[z2, y2, x2];
                    }
                }
            }
            #endregion


            #region Обратное распостронение ошибки
            cached_errors[pos][cached_errors[pos].Length - 1] = out_err;

            for (int i = layers.Count - 1; i >= 0; i--)
            {
                Layer prev = null;
                if (i != 0)
                {
                    prev = layers[i - 1];
                    if (prev != null)
                    {
                        layers[i].GetError(cached_errors[pos][i], cached_diffs[pos][i - 1], cached_outputs[pos][i - 1], cached_errors[pos][i - 1]);
                        //cached_errors[pos][i - 1].MaxNorm();
                    }
                    else
                    {
                        double[,,] diff2 = (double[, , ])input.Clone();
                        diff2.ForEach(x => 1);
                        layers[i].GetError(errors[i], diff2, input, cached_errors[pos][i - 1]);
                        //cached_errors[pos][i - 1].MaxNorm();
                    }
                }
            }
            #endregion

            err = loss.Metric(output, t);

            return(cached_errors[pos]);
        }
Пример #14
0
        public double[,,] Solve()
        {
            var a = _equation.a;
            var b = _equation.b;

            var hx  = (_params.XBoundRight - _params.XBoundLeft) / _params.XStepCount;
            var hy  = (_params.YBoundRight - _params.YBoundLeft) / _params.YStepCount;
            var tau = _params.TimeLimit / _params.TimeStepCount;

            var alpha0 = _conditions.ConditionParameters[0, 0];
            var betta0 = _conditions.ConditionParameters[0, 1];

            var gamma0 = _conditions.ConditionParameters[1, 0];
            var delta0 = _conditions.ConditionParameters[1, 1];

            var alpha1 = _conditions.ConditionParameters[2, 0];
            var betta1 = _conditions.ConditionParameters[2, 1];

            var gamma1 = _conditions.ConditionParameters[3, 0];
            var delta1 = _conditions.ConditionParameters[3, 1];

            var firstMatrix   = new Matrix(_params.XStepCount + 1, _params.XStepCount + 1);
            var firstD        = new double[_params.XStepCount + 1];
            var halfStepLayer = new double[_params.XStepCount + 1, _params.YStepCount + 1];

            var secondMatrix = new Matrix(_params.YStepCount + 1, _params.YStepCount + 1);
            var secondD      = new double[_params.YStepCount + 1];

            for (int i = 0; i < _params.XStepCount; i++)
            {
                firstMatrix[i, i]     = -2 * a / (hx * hx) - 1 / tau;
                firstMatrix[i, i + 1] = a / (hx * hx);
                firstMatrix[i + 1, i] = a / (hx * hx);
            }

            for (int i = 0; i < _params.YStepCount; i++)
            {
                secondMatrix[i, i]     = -2 * b / (hy * hy) - 1 / tau;
                secondMatrix[i, i + 1] = b / (hy * hy);
                secondMatrix[i + 1, i] = b / (hy * hy);
            }

            switch (_params.BoundaryApproximation)
            {
            case BoundaryApproximationType.FirstDegreeTwoPoints:
                var N = _params.XStepCount;
                firstMatrix[0, 0] = betta0 - alpha0 / hx;
                firstMatrix[0, 1] = alpha0 / hx;

                firstMatrix[N, N - 1] = -gamma0 / hx;
                firstMatrix[N, N]     = delta0 + gamma0 / hx;

                N = _params.YStepCount;
                secondMatrix[0, 0] = betta1 - alpha1 / hy;
                secondMatrix[0, 1] = alpha1 / hx;

                secondMatrix[N, N - 1] = -gamma1 / hy;
                secondMatrix[N, N]     = delta1 + gamma1 / hy;

                break;

            case BoundaryApproximationType.SecondDegreeThreePoints:
                N = _params.XStepCount;
                firstMatrix[0, 0] = betta0 - 3 * alpha0 / (2 * hx);
                firstMatrix[0, 1] = 2 * alpha0 / hx;
                firstMatrix[0, 2] = (-alpha0 / (2 * hx));

                var sim = firstMatrix[0, 2] / firstMatrix[1, 2];
                firstMatrix[0, 0] -= sim * firstMatrix[1, 0];
                firstMatrix[0, 1] -= sim * firstMatrix[1, 1];
                firstMatrix[0, 2] -= sim * firstMatrix[1, 2];
                //d[0] -= sim * d[1];

                firstMatrix[N, N - 2] = gamma0 / (2 * hx);
                firstMatrix[N, N - 1] = -2 * gamma0 / hx;
                firstMatrix[N, N]     = delta0 + 3 * gamma0 / (2 * hx);

                sim = firstMatrix[N, N - 2] / firstMatrix[N - 1, N - 2];
                firstMatrix[N, N]     -= sim * firstMatrix[N - 1, N];
                firstMatrix[N, N - 1] -= sim * firstMatrix[N - 1, N - 1];
                firstMatrix[N, N - 2] -= sim * firstMatrix[N - 1, N - 2];
                //d[N] -= sim * d[N - 1];

                N = _params.YStepCount;
                secondMatrix[0, 0] = betta1 - 3 * alpha1 / (2 * hy);
                secondMatrix[0, 1] = 2 * alpha1 / hy;
                secondMatrix[0, 2] = (-alpha1 / (2 * hy));

                sim = secondMatrix[0, 2] / secondMatrix[1, 2];
                secondMatrix[0, 0] -= sim * secondMatrix[1, 0];
                secondMatrix[0, 1] -= sim * secondMatrix[1, 1];
                secondMatrix[0, 2] -= sim * secondMatrix[1, 2];
                //d[0] -= sim * d[1];

                secondMatrix[N, N - 2] = gamma1 / (2 * hy);
                secondMatrix[N, N - 1] = -2 * gamma1 / hy;
                secondMatrix[N, N]     = delta1 + 3 * gamma1 / (2 * hy);

                sim = secondMatrix[N, N - 2] / secondMatrix[N - 1, N - 2];
                secondMatrix[N, N]     -= sim * secondMatrix[N - 1, N];
                secondMatrix[N, N - 1] -= sim * secondMatrix[N - 1, N - 1];
                secondMatrix[N, N - 2] -= sim * secondMatrix[N - 1, N - 2];
                //d[N] -= sim * d[N - 1];

                break;

            case BoundaryApproximationType.SecondDegreeTwoPoints:
                throw new NotImplementedException();
            }

            for (int k = 1; k <= _params.TimeStepCount; k++)
            {
                var halfStep = k - 0.5d;

                // первый шаг считаем k + 1/2 слой
                for (int j = 1; j < _params.YStepCount; j++)
                {
                    SetFirstD(firstD, firstMatrix, j, k - 1);

                    var newLayer = firstMatrix.SolveTridiagonal(firstD);

                    for (int i = 0; i <= _params.XStepCount; i++)
                    {
                        halfStepLayer[i, j] = newLayer[i];
                    }
                }

                for (int i = 0; i <= _params.XStepCount; i++)
                {
                    var f0 = _conditions.InitialConditions[2](GetXCoordinate(i), GetYCoordinate(0), GetTimeCoordinate(halfStep));
                    var fn = _conditions.InitialConditions[3](GetXCoordinate(i), GetYCoordinate(_params.YStepCount), GetTimeCoordinate(halfStep));

                    switch (_params.BoundaryApproximation)
                    {
                    case BoundaryApproximationType.FirstDegreeTwoPoints:
                        halfStepLayer[i, 0] = -(alpha1 / hy) / (betta1 - alpha1 / hy) * halfStepLayer[i, 1] +
                                              f0 / (betta1 - alpha1 / hy);
                        halfStepLayer[i, _params.YStepCount] = (gamma1 / hy) / (delta1 + gamma1 / hy) * halfStepLayer[i, _params.YStepCount - 1] +
                                                               fn / (delta1 + gamma1 / hy);
                        break;

                    case BoundaryApproximationType.SecondDegreeThreePoints:
                        halfStepLayer[i, 0] = 1 / (-3 * alpha1 / (2 * hy) + betta1) *
                                              (f0 + alpha1 / (2 * hy) * (halfStepLayer[i, 2] - 4 * halfStepLayer[i, 1]));
                        halfStepLayer[i, _params.YStepCount] = 1 / (3 * gamma1 / (2 * hy) + delta1) *
                                                               (fn + gamma1 / (2 * hy) * (4 * halfStepLayer[i, _params.YStepCount - 1] - halfStepLayer[i, _params.YStepCount - 2]));
                        break;
                    }
                }

                //тут второй шаг считаем k + 1 слой
                for (int i = 1; i < _params.XStepCount; i++)
                {
                    SetSecondD(secondD, secondMatrix, halfStepLayer, i, k - 1);

                    var newLayer = secondMatrix.SolveTridiagonal(secondD);

                    for (int j = 0; j <= _params.YStepCount; j++)
                    {
                        _grid[i, j, k] = newLayer[j];
                    }
                }

                for (int j = 0; j <= _params.YStepCount; j++)
                {
                    var f0 = _conditions.InitialConditions[0](GetXCoordinate(0), GetYCoordinate(j), GetTimeCoordinate(k));
                    var fn = _conditions.InitialConditions[1](GetXCoordinate(_params.XStepCount), GetYCoordinate(j), GetTimeCoordinate(k));

                    switch (_params.BoundaryApproximation)
                    {
                    case BoundaryApproximationType.FirstDegreeTwoPoints:
                        _grid[0, j, k] = -(alpha0 / hx) / (betta0 - alpha0 / hx) * _grid[1, j, k] +
                                         f0 / (betta0 - alpha0 / hx);
                        _grid[_params.XStepCount, j, k] = (gamma0 / hx) / (delta0 + gamma0 / hx) * _grid[_params.XStepCount - 1, j, k] +
                                                          fn / (delta0 + gamma0 / hx);
                        break;

                    case BoundaryApproximationType.SecondDegreeThreePoints:
                        _grid[0, j, k] = 1 / (-3 * alpha0 / (2 * hx) + betta0) *
                                         (f0 + alpha0 / (2 * hx) * (_grid[2, j, k] - 4 * _grid[1, j, k]));
                        _grid[_params.XStepCount, j, k] = 1 / (3 * gamma0 / (2 * hx) + delta0) *
                                                          (fn + gamma0 / (2 * hx) * (4 * _grid[_params.XStepCount - 1, j, k] - _grid[_params.XStepCount - 2, j, k]));
                        break;
                    }
                }
            }

            return(_grid.Clone() as double[, , ]);
        }
        public Bitmap DoSegmentation(double[,,] arrayImage, double sigma, double k, int minSize, IColorSheme colorSheme)
        {
            m_height = arrayImage.GetLength(1);
            m_width  = arrayImage.GetLength(2);

            //debug
            System.Diagnostics.Debug.WriteLine("Reading done: " + DateTime.Now);

            m_colorSheme = colorSheme;

            //препроцессинг иображения
            arrayImage = colorSheme.Convert(arrayImage);

            //сохранение для проведения оценки качества сегментации
            m_arrayImageCopy = (double[, , ])arrayImage.Clone();

            //debug
            System.Diagnostics.Debug.WriteLine("color sheme changed: " + DateTime.Now);
            //DebugImageInfo(arrayImage);

            //smoothing
            GaussianBlur gaussianBlur = new GaussianBlur();

            double[][] filter = gaussianBlur.getKernel(sigma);
            double[,,] blurredImage = DoubleArrayImageOperations.ConvolutionFilter(arrayImage, filter);

            //debug
            System.Diagnostics.Debug.WriteLine("Smooting done: " + DateTime.Now);
            //тест размещения преобразования цвета
            //arrayImage = colorSheme.Convert(arrayImage);

            //построение графа
            Edge[] edges = buildGraphByImage(blurredImage)
                           .OrderBy(el => el.w)
                           .ToArray();

            //debug
            System.Diagnostics.Debug.WriteLine("graph builded: " + DateTime.Now);

            //debugging

            System.Diagnostics.Debug.WriteLine("edges total: " + edges.Length);

            //double minWeight = edges.Min(el => el.w);
            //double maxWeight = edges.Max(el => el.w);
            //Edge[] EdgesMoreThanMin = edges.Where(el => el.w > minWeight + 0.1).ToArray();
            //Edge[] EdgesZeroWidth = edges.Where(el => el.w < 0.01).ToArray();
            //
            //Edge[] edgesHor = edges.Where(el => el.neightbourType == NeightbourType.Horizontal).ToArray();
            //Edge[] edgesVer = edges.Where(el => el.neightbourType == NeightbourType.Vertical).ToArray();
            //Edge[] edgesTopDiag = edges.Where(el => el.neightbourType == NeightbourType.TopDiagonal).ToArray();
            //Edge[] edgesBottom = edges.Where(el => el.neightbourType == NeightbourType.BottomDiagonal).ToArray();

            //сегментированный лес непересекающихся деревьев
            DisjointSet segmentedSet = SegmentOnDisjointSet(k, m_height * m_width, edges);  //картинка тут только для передачи размера потому осталась arrayImage

            //запоминание в поле для проведения оценки
            m_segmentedSet = segmentedSet;

            //debug
            System.Diagnostics.Debug.WriteLine("Segmented: " + DateTime.Now);

            //присоеденить те, что меньше min_size к соседу по ребру
            PostProcessSmallComponents(edges, segmentedSet, minSize);

            //debug
            System.Diagnostics.Debug.WriteLine("Small Component Merged: " + DateTime.Now);

            return(SegmentedSetConverter.ConvertToBitmap(segmentedSet, m_height, m_width, out m_componentLength));
            //var a = SegmentedSetConverter.ConvertToRealCoordsSegments(segmentedSet, height, width);
            //return SegmentedSetConverter.RealCoordsSegmentResultToBitmap(a);
        }
 private void вернутьсяКИсходномуToolStripMenuItem_Click(object sender, EventArgs e)
 {
     ResetScrollsBarsValues();
     m_workImage = (double[, , ])m_originalImage.Clone();
     OutputBitmapOnPictureBox(BitmapConverter.DoubleRgbToBitmap(m_workImage));
 }
Пример #17
0
 public double[,,] Func(double[,,] val)
 {
     return((double[, , ])val.Clone());
 }