diff options
Diffstat (limited to 'eigen/debug/gdb/printers.py')
-rw-r--r-- | eigen/debug/gdb/printers.py | 174 |
1 files changed, 140 insertions, 34 deletions
diff --git a/eigen/debug/gdb/printers.py b/eigen/debug/gdb/printers.py index 86996a4..24961d1 100644 --- a/eigen/debug/gdb/printers.py +++ b/eigen/debug/gdb/printers.py @@ -10,8 +10,7 @@ # Pretty printers for Eigen::Matrix # This is still pretty basic as the python extension to gdb is still pretty basic. -# It cannot handle complex eigen types and it doesn't support any of the other eigen types -# Such as quaternion or some other type. +# It cannot handle complex eigen types and it doesn't support many of the other eigen types # This code supports fixed size as well as dynamic size matrices # To use it: @@ -29,7 +28,45 @@ import gdb import re import itertools +from bisect import bisect_left +# Basic row/column iteration code for use with Sparse and Dense matrices +class _MatrixEntryIterator(object): + + def __init__ (self, rows, cols, rowMajor): + self.rows = rows + self.cols = cols + self.currentRow = 0 + self.currentCol = 0 + self.rowMajor = rowMajor + + def __iter__ (self): + return self + + def next(self): + return self.__next__() # Python 2.x compatibility + + def __next__(self): + row = self.currentRow + col = self.currentCol + if self.rowMajor == 0: + if self.currentCol >= self.cols: + raise StopIteration + + self.currentRow = self.currentRow + 1 + if self.currentRow >= self.rows: + self.currentRow = 0 + self.currentCol = self.currentCol + 1 + else: + if self.currentRow >= self.rows: + raise StopIteration + + self.currentCol = self.currentCol + 1 + if self.currentCol >= self.cols: + self.currentCol = 0 + self.currentRow = self.currentRow + 1 + + return (row, col) class EigenMatrixPrinter: "Print Eigen Matrix or Array of some kind" @@ -49,7 +86,7 @@ class EigenMatrixPrinter: regex = re.compile('\<.*\>') m = regex.findall(tag)[0][1:-1] template_params = m.split(',') - template_params = map(lambda x:x.replace(" ", ""), template_params) + template_params = [x.replace(" ", "") for x in template_params] if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001' or template_params[1] == '-1': self.rows = val['m_storage']['m_rows'] @@ -77,39 +114,15 @@ class EigenMatrixPrinter: self.data = self.data['array'] self.data = self.data.cast(self.innerType.pointer()) - class _iterator: + class _iterator(_MatrixEntryIterator): def __init__ (self, rows, cols, dataPtr, rowMajor): - self.rows = rows - self.cols = cols + super(EigenMatrixPrinter._iterator, self).__init__(rows, cols, rowMajor) + self.dataPtr = dataPtr - self.currentRow = 0 - self.currentCol = 0 - self.rowMajor = rowMajor - - def __iter__ (self): - return self - - def next(self): + + def __next__(self): - row = self.currentRow - col = self.currentCol - if self.rowMajor == 0: - if self.currentCol >= self.cols: - raise StopIteration - - self.currentRow = self.currentRow + 1 - if self.currentRow >= self.rows: - self.currentRow = 0 - self.currentCol = self.currentCol + 1 - else: - if self.currentRow >= self.rows: - raise StopIteration - - self.currentCol = self.currentCol + 1 - if self.currentCol >= self.cols: - self.currentCol = 0 - self.currentRow = self.currentRow + 1 - + row, col = super(EigenMatrixPrinter._iterator, self).__next__() item = self.dataPtr.dereference() self.dataPtr = self.dataPtr + 1 @@ -126,6 +139,95 @@ class EigenMatrixPrinter: def to_string(self): return "Eigen::%s<%s,%d,%d,%s> (data ptr: %s)" % (self.variety, self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else "ColMajor", self.data) +class EigenSparseMatrixPrinter: + "Print an Eigen SparseMatrix" + + def __init__(self, val): + "Extract all the necessary information" + + type = val.type + if type.code == gdb.TYPE_CODE_REF: + type = type.target() + self.type = type.unqualified().strip_typedefs() + tag = self.type.tag + regex = re.compile('\<.*\>') + m = regex.findall(tag)[0][1:-1] + template_params = m.split(',') + template_params = [x.replace(" ", "") for x in template_params] + + self.options = 0 + if len(template_params) > 1: + self.options = template_params[1]; + + self.rowMajor = (int(self.options) & 0x1) + + self.innerType = self.type.template_argument(0) + + self.val = val + + self.data = self.val['m_data'] + self.data = self.data.cast(self.innerType.pointer()) + + class _iterator(_MatrixEntryIterator): + def __init__ (self, rows, cols, val, rowMajor): + super(EigenSparseMatrixPrinter._iterator, self).__init__(rows, cols, rowMajor) + + self.val = val + + def __next__(self): + + row, col = super(EigenSparseMatrixPrinter._iterator, self).__next__() + + # repeat calculations from SparseMatrix.h: + outer = row if self.rowMajor else col + inner = col if self.rowMajor else row + start = self.val['m_outerIndex'][outer] + end = ((start + self.val['m_innerNonZeros'][outer]) if self.val['m_innerNonZeros'] else + self.val['m_outerIndex'][outer+1]) + + # and from CompressedStorage.h: + data = self.val['m_data'] + if start >= end: + item = 0 + elif (end > start) and (inner == data['m_indices'][end-1]): + item = data['m_values'][end-1] + else: + # create Python index list from the target range within m_indices + indices = [data['m_indices'][x] for x in range(int(start), int(end)-1)] + # find the index with binary search + idx = int(start) + bisect_left(indices, inner) + if ((idx < end) and (data['m_indices'][idx] == inner)): + item = data['m_values'][idx] + else: + item = 0 + + return ('[%d,%d]' % (row, col), item) + + def children(self): + if self.data: + return self._iterator(self.rows(), self.cols(), self.val, self.rowMajor) + + return iter([]) # empty matrix, for now + + + def rows(self): + return self.val['m_outerSize'] if self.rowMajor else self.val['m_innerSize'] + + def cols(self): + return self.val['m_innerSize'] if self.rowMajor else self.val['m_outerSize'] + + def to_string(self): + + if self.data: + status = ("not compressed" if self.val['m_innerNonZeros'] else "compressed") + else: + status = "empty" + dimensions = "%d x %d" % (self.rows(), self.cols()) + layout = "row" if self.rowMajor else "column" + + return "Eigen::SparseMatrix<%s>, %s, %s major, %s" % ( + self.innerType, dimensions, layout, status ) + class EigenQuaternionPrinter: "Print an Eigen Quaternion" @@ -151,8 +253,11 @@ class EigenQuaternionPrinter: def __iter__ (self): return self - + def next(self): + return self.__next__() # Python 2.x compatibility + + def __next__(self): element = self.currentElement if self.currentElement >= 4: #there are 4 elements in a quanternion @@ -174,6 +279,7 @@ class EigenQuaternionPrinter: def build_eigen_dictionary (): pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val) pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter("Matrix", val) + pretty_printers_dict[re.compile('^Eigen::SparseMatrix<.*>$')] = lambda val: EigenSparseMatrixPrinter(val) pretty_printers_dict[re.compile('^Eigen::Array<.*>$')] = lambda val: EigenMatrixPrinter("Array", val) def register_eigen_printers(obj): |