diff --git a/cmake/libakantu/v3/printers.py b/cmake/libakantu/v3/printers.py index de6356340..a8ca32bee 100755 --- a/cmake/libakantu/v3/printers.py +++ b/cmake/libakantu/v3/printers.py @@ -1,234 +1,339 @@ #!/usr/bin/env python3 # encoding: utf-8 # # Inspired from boost's pretty printers from # Rüdiger Sonderfeld # and from Pretty-printers for libstc++ from Free Software Foundation, Inc. # - import gdb import re -#import sys -# import libstdcxx.v6.printers as std +import sys __use_gdb_pp__ = True try: import gdb.printing except ImportError: __use_gdb_pp__ = False class AkantuPrinter(object): regex = None @classmethod def supports(cls, typename): #print('{0} ~= {1}'.format(typename, cls.regex), file=sys.stderr) return cls.regex.search(typename) @classmethod def get_basic_type(cls, value): """ Determines the type associated to a value""" _type = value.type # If it points to a reference, get the reference. if _type.code == gdb.TYPE_CODE_REF: _type = _type.target() # Get the unqualified type, stripped of typedefs. _type = _type.unqualified().strip_typedefs() return _type.tag if __use_gdb_pp__: __akantu_pretty_printers__ = \ gdb.printing.RegexpCollectionPrettyPrinter("libakantu-v3") else: class AkantuPrettyPrinters(object): def __init__(self, name): super(AkantuPrettyPrinters, self).__init__() self.name = name self.printers = {} @property def enabled(self): return True def add_printer(self, name, regex, printer): self.printers[name] = printer def __call__(self, val): typename = AkantuPrinter.get_basic_type(val) if not typename: return None for name, printer in self.printers.items(): if(printer.supports(typename)): return printer return None __akantu_pretty_printers__ = AkantuPrettyPrinters("libakantu-v3") def register_pretty_printer(pretty_printer): "Registers a Pretty Printer" __akantu_pretty_printers__.add_printer(pretty_printer.name, pretty_printer.regex, pretty_printer) return pretty_printer @register_pretty_printer class AkaArrayPrinter(AkantuPrinter): """Pretty printer for akantu::Array""" regex = re.compile('^akantu::Array<(.*?), (true|false)>$') name = 'akantu::Array' def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.ptr = self.value['values'] self.size = int(self.value['size_']) self.nb_component = int(self.value['nb_component']) def display_hint(self): return 'array' def to_string(self): m = self.regex.search(self.typename) return 'Array<{0}>({1}, {2}) stored at {3}'.format( m.group(1), self.size, self.nb_component, self.ptr) def children(self): _ptr = self.ptr for i in range(self.size): _values = ["{0}".format((_ptr + j).dereference()) for j in range(self.nb_component)] _ptr = _ptr + self.nb_component yield ('[{0}]'.format(i), ('{0}' if self.nb_component == 1 else '[{0}]').format( ', '.join(_values))) -# @register_pretty_printer -# class AkaArrayIteratorPrinter(AkantuPrinter): -# """Pretty printer for akantu::Array""" -# regex = re.compile('^akantu::Array<(.*?), (true|false)>::internal_iterator<(.*?), (.*?), (false|true)>$') -# name = 'akantu::Array::iterator' - -# def __init__(self, value): -# self.typename = self.get_basic_type(value) -# self.value = value -# self.ret = self.value['ret'].dereference() - -# def to_string(self): -# m = self.regex.search(self.typename) -# return 'Array<{0}>::iterator<{3}>'.format( -# m.group(1), m.group(1)) - -# def children(self): -# yield ('[data]', self.ret) +if sys.version_info[0] > 2: + ### Python 3 stuff + Iterator = object +else: + ### Python 2 stuff + class Iterator: + """Compatibility mixin for iterators + + Instead of writing next() methods for iterators, write + __next__() methods and use this mixin to make them work in + Python 2 as well as Python 3. + + Idea stolen from the "six" documentation: + + """ + def next(self): + return self.__next__() + + +class RbtreeIterator(Iterator): + """ + Turn an RB-tree-based container (std::map, std::set etc.) into + a Python iterable object. + """ + + def __init__(self, rbtree): + self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] + self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] + self.count = 0 + + def __iter__(self): + return self + + def __len__(self): + return int (self.size) + + def __next__(self): + if self.count == self.size: + raise StopIteration + result = self.node + self.count = self.count + 1 + if self.count < self.size: + # Compute the next node. + node = self.node + if node.dereference()['_M_right']: + node = node.dereference()['_M_right'] + while node.dereference()['_M_left']: + node = node.dereference()['_M_left'] + else: + parent = node.dereference()['_M_parent'] + while node == parent.dereference()['_M_right']: + node = parent + parent = parent.dereference()['_M_parent'] + if node.dereference()['_M_right'] != parent: + node = parent + self.node = node + return result + +def get_value_from_Rb_tree_node(node): + """Returns the value held in an _Rb_tree_node<_Val>""" + try: + member = node.type.fields()[1].name + if member == '_M_value_field': + # C++03 implementation, node contains the value as a member + return node['_M_value_field'] + elif member == '_M_storage': + # C++11 implementation, node stores value in __aligned_membuf + valtype = node.type.template_argument(0) + return get_value_from_aligned_membuf(node['_M_storage'], valtype) + except: + pass + raise ValueError("Unsupported implementation for %s" % str(node.type)) + +@register_pretty_printer +class AkaElementTypeMapArrayPrinter(AkantuPrinter): + """Pretty printer for akantu::ElementTypeMap>""" + regex = re.compile('^akantu::ElementTypeMap\*, akantu::(.*?)>$') + name = 'akantu::ElementTypeMapArray' + + # Turn an RbtreeIterator into a pretty-print iterator. + class _iter(Iterator): + def __init__(self, rbiter, type): + self.rbiter = rbiter + self.count = 0 + self.type = type + + def __iter__(self): + return self + + def __next__(self): + if self.count % 2 == 0: + n = next(self.rbiter) + n = n.cast(self.type).dereference() + n = get_value_from_Rb_tree_node(n) + self.pair = n + item = n['first'] + else: + item = self.pair['second'] + result = ('[{0}]'.format(self.count), item.dereference()) + self.count = self.count + 1 + return result + + def __init__(self, value): + self.typename = self.get_basic_type(value) + self.value = value + self.data = self.value['data'] + self.ghost_data = self.value['ghost_data'] + + def to_string(self): + m = self.regex.search(self.typename) + return 'ElementTypMapArray<{0}> with {1} _not_ghost and {2} _ghost'.format( + m.group(1), len(RbtreeIterator(self.data)), len(RbtreeIterator(self.ghost_data))) + + def children(self): + m = self.regex.search(self.typename) + try: + _type = gdb.lookup_type("akantu::Array<{0}, {1}>".format( + m.group(1), m.group(2))).strip_typedefs().pointer() + yield ('[_not_ghost]', self._iter(RbtreeIterator(self.data), _type)) + yield ('[_ghost]', self._iter(RbtreeIterator(self.ghost_data), _type)) + except RuntimeError: + pass + + def display_hint(self): + return 'map' # @register_pretty_printer class AkaTensorPrinter(AkantuPrinter): """Pretty printer for akantu::Tensor""" regex = re.compile('^akantu::Tensor<(.*), +(.*), +(.*)>$') name = 'akantu::Tensor' value = None typename = "" ptr = None dims = [] ndims = 0 def pretty_print(self): def ij2str(i, j, m): return "{0}".format((self.ptr+m*j + i).dereference()) def line(i, m, n): return "[{0}]".format(", ".join((ij2str(i, j, m) for j in range(n)))) m = int(self.dims[0]) if (self.ndims == 1): n = 1 else: n = int(self.dims[1]) return "[{0}]".format(", ".join(line(i, m, n) for i in range(m))) def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.ptr = self.value['values'] self.dims = self.value['n'] def children(self): yield ('values', self.pretty_print()) yield ('wrapped', self.value['wrapped']) @register_pretty_printer class AkaVectorPrinter(AkaTensorPrinter): """Pretty printer for akantu::Vector""" regex = re.compile('^akantu::Vector<(.*)>$') name = 'akantu::Vector' n = 0 ptr = 0x0 def __init__(self, value): super(AkaVectorPrinter, self).__init__(value) self.ndims = 1 def to_string(self): m = self.regex.search(self.typename) return 'Vector<{0}>({1}) [{2}]'.format(m.group(1), int(self.dims[0]), str(self.ptr)) @register_pretty_printer class AkaMatrixPrinter(AkaTensorPrinter): """Pretty printer for akantu::Matrix""" regex = re.compile('^akantu::Matrix<(.*)>$') name = 'akantu::Matrix' def __init__(self, value): super(AkaMatrixPrinter, self).__init__(value) self.ndims = 2 def to_string(self): m = self.regex.search(self.typename) return 'Matrix<%s>(%d, %d) [%s]' % (m.group(1), int(self.dims[0]), int(self.dims[1]), str(self.ptr)) @register_pretty_printer class AkaElementPrinter(AkantuPrinter): """Pretty printer for akantu::Element""" regex = re.compile('^akantu::Element$') name = 'akantu::Element' def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.element = self.value['element'] self.eltype = self.value['type'] self.ghost_type = self.value['ghost_type'] def to_string(self): return 'Element({0}, {1}, {2})'.format(self.element, self.eltype, self.ghost_type) def register_akantu_printers(obj): "Register Akantu Pretty Printers." if __use_gdb_pp__: gdb.printing.register_pretty_printer(obj, __akantu_pretty_printers__) else: if obj is None: obj = gdb obj.pretty_printers.append(__akantu_pretty_printers__) diff --git a/src/common/aka_array_tmpl.hh b/src/common/aka_array_tmpl.hh index a5c46d45c..ac1b92fd9 100644 --- a/src/common/aka_array_tmpl.hh +++ b/src/common/aka_array_tmpl.hh @@ -1,1260 +1,1263 @@ /** * @file aka_array_tmpl.hh * * @author Nicolas Richart * * @date creation: Thu Jul 15 2010 * @date last modification: Fri Jan 22 2016 * * @brief Inline functions of the classes Array and ArrayBase * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* Inline Functions Array */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_ARRAY_TMPL_HH__ #define __AKANTU_AKA_ARRAY_TMPL_HH__ namespace akantu { namespace debug { struct ArrayException : public Exception {}; } // namespace debug /* -------------------------------------------------------------------------- */ template inline T & Array::operator()(UInt i, UInt j) { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in array \"" << id << "\""); return values[i * nb_component + j]; } /* -------------------------------------------------------------------------- */ template inline const T & Array::operator()(UInt i, UInt j) const { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in array \"" << id << "\""); return values[i * nb_component + j]; } template inline T & Array::operator[](UInt i) { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_ * nb_component), "The value at position [" << i << "] is out of range in array \"" << id << "\""); return values[i]; } /* -------------------------------------------------------------------------- */ template inline const T & Array::operator[](UInt i) const { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_ * nb_component), "The value at position [" << i << "] is out of range in array \"" << id << "\""); return values[i]; } /* -------------------------------------------------------------------------- */ /** * append a tuple to the array with the value value for all components * @param value the new last tuple or the array will contain nb_component copies * of value */ template inline void Array::push_back(const T & value) { resizeUnitialized(size_ + 1, true, value); } /* -------------------------------------------------------------------------- */ /** * append a tuple to the array * @param new_elem a C-array containing the values to be copied to the end of * the array */ // template // inline void Array::push_back(const T new_elem[]) { // UInt pos = size_; // resizeUnitialized(size_ + 1, false); // T * tmp = values + nb_component * pos; // std::uninitialized_copy(new_elem, new_elem + nb_component, tmp); // } /* -------------------------------------------------------------------------- */ #ifndef SWIG /** * append a matrix or a vector to the array * @param new_elem a reference to a Matrix or Vector */ template template