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

Last change on this file since 17831 was 17831, checked in by bburlacu, 17 months ago

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

File size: 5.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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;
27using HEAL.Attic;
28using System.Collections.ObjectModel;
29
30namespace HeuristicLab.Data {
31  [Item("TriangularMatrix", "Represents a lower triangular matrix.")]
32  [StorableType("5C09A4FC-887E-4C40-8926-81325C09FA67")]
33  public class TriangularMatrix<T> : ValueTypeArray<T>, IStringConvertibleArray where T : struct {
34    [Storable]
35    private readonly int dimension;
36    public int Dimension { get { return dimension; } }
37
38    public ReadOnlyCollection<T> Data {
39      get { return Array.AsReadOnly(array); }
40    }
41
42    private TriangularMatrix() { }
43
44    public TriangularMatrix(int dimension) : base(dimension * (dimension + 1) / 2) {
45      this.dimension = dimension;
46      resizable = false;
47    }
48
49    [StorableConstructor]
50    protected TriangularMatrix(StorableConstructorFlag _) : base(_) { }
51
52    protected TriangularMatrix(TriangularMatrix<T> original, Cloner cloner) : base(original, cloner) {
53      dimension = original.dimension;
54      array = (T[])original.array.Clone();
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
62    public T this[int rowIndex, int columnIndex] {
63      get {
64        // provide symmetry of returned values
65        if (columnIndex > rowIndex) return this[columnIndex, rowIndex];
66        return array[rowIndex * (rowIndex + 1) / 2 + columnIndex];
67      }
68      set {
69        if (columnIndex > rowIndex) this[columnIndex, rowIndex] = value;
70        else array[rowIndex * (rowIndex + 1) / 2 + columnIndex] = value;
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() {
97      return array.Cast<T>().GetEnumerator();
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
170    #region IStringConvertibleArray members
171    bool IStringConvertibleArray.Validate(string value, out string errorMessage) {
172      return Validate(value, out errorMessage);
173    }
174
175    public string GetValue(int index) {
176      return array[index].ToString();
177    }
178
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));
185    }
186    #endregion
187  }
188}
Note: See TracBrowser for help on using the repository browser.