Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3087_Ceres_Integration/HeuristicLab.Data/3.3/TriangularMatrix.cs

Last change on this file was 17831, checked in by bburlacu, 4 years ago

#3100: Use ValueTypeArray as base class for TriangularMatrix. A Data property exposes the underlying array as a ReadOnlyCollection.

File size: 5.9 KB
RevLine 
[15931]1#region License Information
2/* HeuristicLab
[17180]3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[15931]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
[16565]27using HEAL.Attic;
[17831]28using System.Collections.ObjectModel;
[15931]29
30namespace HeuristicLab.Data {
31  [Item("TriangularMatrix", "Represents a lower triangular matrix.")]
[16565]32  [StorableType("5C09A4FC-887E-4C40-8926-81325C09FA67")]
[17831]33  public class TriangularMatrix<T> : ValueTypeArray<T>, IStringConvertibleArray where T : struct {
[15931]34    [Storable]
35    private readonly int dimension;
[17831]36    public int Dimension { get { return dimension; } }
[15931]37
[17831]38    public ReadOnlyCollection<T> Data {
39      get { return Array.AsReadOnly(array); }
40    }
41
[15931]42    private TriangularMatrix() { }
43
[17831]44    public TriangularMatrix(int dimension) : base(dimension * (dimension + 1) / 2) {
[15931]45      this.dimension = dimension;
[17831]46      resizable = false;
[15931]47    }
48
49    [StorableConstructor]
[16565]50    protected TriangularMatrix(StorableConstructorFlag _) : base(_) { }
[15931]51
52    protected TriangularMatrix(TriangularMatrix<T> original, Cloner cloner) : base(original, cloner) {
53      dimension = original.dimension;
[17831]54      array = (T[])original.array.Clone();
[15931]55    }
56
57    public override IDeepCloneable Clone(Cloner cloner) {
58      return new TriangularMatrix<T>(this, cloner);
59    }
60
61    // the indexing rule for the (lower-)triangular matrix is that always i <= j, otherwise an IndexOutOfBounds exception will occur
[17831]62    public T this[int rowIndex, int columnIndex] {
[15931]63      get {
[15932]64        // provide symmetry of returned values
65        if (columnIndex > rowIndex) return this[columnIndex, rowIndex];
[17831]66        return array[rowIndex * (rowIndex + 1) / 2 + columnIndex];
[15931]67      }
68      set {
[15932]69        if (columnIndex > rowIndex) this[columnIndex, rowIndex] = value;
[17831]70        else array[rowIndex * (rowIndex + 1) / 2 + columnIndex] = value;
[15931]71      }
72    }
73
74    protected virtual string GetValue(int rowIndex, int columnIndex) {
75      return this[rowIndex, columnIndex].ToString(); // see above indexing rule
76    }
77
78    protected virtual bool SetValue(string value, int rowIndex, int columnIndex) {
79      T val;
80      if (!TryParse(value, out val))
81        return false;
82      this[rowIndex, columnIndex] = val;
83      return true;
84    }
85
86    protected virtual bool Validate(string value, out string errorMessage) {
87      T val;
88      errorMessage = "";
89      if (!TryParse(value, out val)) {
90        errorMessage = string.Format("Could not parse string \"{0}\" as {1}.", value, typeof(T));
91        return false;
92      }
93      return true;
94    }
95
96    public override IEnumerator<T> GetEnumerator() {
[17831]97      return array.Cast<T>().GetEnumerator();
[15931]98    }
99
100    private static bool TryParse(string value, out T val) {
101      if (typeof(T) == typeof(sbyte)) {
102        sbyte v;
103        if (sbyte.TryParse(value, out v)) {
104          val = (T)(object)v;
105          return true;
106        }
107      } else if (typeof(T) == typeof(byte)) {
108        byte v;
109        if (byte.TryParse(value, out v)) {
110          val = (T)(object)v;
111          return true;
112        }
113      } else if (typeof(T) == typeof(char)) {
114        char v;
115        if (char.TryParse(value, out v)) {
116          val = (T)(object)v;
117          return true;
118        }
119      } else if (typeof(T) == typeof(short)) {
120        short v;
121        if (short.TryParse(value, out v)) {
122          val = (T)(object)v;
123          return true;
124        }
125      } else if (typeof(T) == typeof(ushort)) {
126        ushort v;
127        if (ushort.TryParse(value, out v)) {
128          val = (T)(object)v;
129          return true;
130        }
131      } else if (typeof(T) == typeof(int)) {
132        int v;
133        if (int.TryParse(value, out v)) {
134          val = (T)(object)v;
135          return true;
136        }
137      } else if (typeof(T) == typeof(uint)) {
138        uint v;
139        if (uint.TryParse(value, out v)) {
140          val = (T)(object)v;
141          return true;
142        }
143      } else if (typeof(T) == typeof(long)) {
144        long v;
145        if (long.TryParse(value, out v)) {
146          val = (T)(object)v;
147          return true;
148        }
149      } else if (typeof(T) == typeof(ulong)) {
150        ulong v;
151        if (ulong.TryParse(value, out v)) {
152          val = (T)(object)v;
153          return true;
154        }
155      }
156      val = default(T);
157      return false;
158    }
159
160    public void GetMatrixCoordinates(int index, out int row, out int col) {
161      var root = TriangularRoot(index);
162      row = (int)Math.Floor(root);
163      col = index - row * (row + 1) / 2;
164    }
165
166    private static double TriangularRoot(double x) {
167      return (Math.Sqrt(8 * x + 1) - 1) / 2;
168    }
169
[17831]170    #region IStringConvertibleArray members
171    bool IStringConvertibleArray.Validate(string value, out string errorMessage) {
172      return Validate(value, out errorMessage);
[15931]173    }
174
[17831]175    public string GetValue(int index) {
176      return array[index].ToString();
[15931]177    }
178
[17831]179    public bool SetValue(string value, int index) {
180      if (TryParse(value, out T val)) {
181        this[index] = val;
182        return true;
183      }
184      throw new ArgumentException("Coult not parse value " + value + " as " + typeof(T));
[15931]185    }
186    #endregion
187  }
188}
Note: See TracBrowser for help on using the repository browser.