Source code for ffc.uflacs.backends.ufc.utils

# -*- coding: utf-8 -*-
# Copyright (C) 2015-2017 Martin Sandve Alnæs
#
# This file is part of UFLACS.
#
# UFLACS 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.
#
# UFLACS 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 UFLACS. If not, see <http://www.gnu.org/licenses/>.

# TODO: Move these to uflacs.language utils?


[docs]def generate_return_new(L, classname, factory): if factory: return L.Return(L.Call("create_" + classname)) else:
return L.Return(L.New(classname))
[docs]def generate_return_new_switch(L, i, classnames, args=None, factory=False): # TODO: UFC functions of this type could be replaced with return vector<shared_ptr<T>>{objects}. if isinstance(i, str): i = L.Symbol(i) if factory: def create(classname): return L.Call("create_" + classname) else: def create(classname): return L.New(classname) default = L.Return(L.Null()) if classnames: cases = [] if args is None: args = list(range(len(classnames))) for j, classname in zip(args, classnames): if classname: cases.append((j, L.Return(create(classname)))) return L.Switch(i, cases, default=default) else:
return default
[docs]def generate_return_literal_switch(L, i, values, default, literal_type, typename=None): # TODO: UFC functions of this type could be replaced with return vector<T>{values}. if isinstance(i, str): i = L.Symbol(i) return_default = L.Return(literal_type(default)) if values and typename is not None: # Store values in static table and return from there V = L.Symbol("return_values") decl = L.ArrayDecl("static const %s" % typename, V, len(values), [literal_type(k) for k in values]) return L.StatementList([ decl, L.If(L.GE(i, len(values)), return_default), L.Return(V[i]) ]) elif values: # Need typename to create static array, fallback to switch cases = [(j, L.Return(literal_type(k))) for j, k in enumerate(values)] return L.Switch(i, cases, default=return_default) else: # No values, just return default
return return_default
[docs]def generate_return_sizet_switch(L, i, values, default):
return generate_return_literal_switch(L, i, values, default, L.LiteralInt, "std::size_t")
[docs]def generate_return_int_switch(L, i, values, default):
return generate_return_literal_switch(L, i, values, default, L.LiteralInt, "int")
[docs]def generate_return_bool_switch(L, i, values, default):
return generate_return_literal_switch(L, i, values, default, L.LiteralBool, "bool") # TODO: Better error handling
[docs]def generate_error(L, msg, emit_warning): if emit_warning: return L.VerbatimStatement('std::cerr << "*** FFC warning: " << "%s" << std::endl;' % (msg,)) else:
return L.Throw('std::runtime_error', msg) """ // TODO: UFC functions that return constant arrays // could use something like this to reduce copying, // returning pointers to static data: template<T> class array_view { public: array_view(std::size_t size, const T * data): size(size), data(data) const std::size_t size; const T * data; const T operator[](std::size_t i) const { return data[i]; } }; array_view<int> form::original_coefficient_positions() const { static const int data = { 0, 1, 2, 5 }; return array_view<int>{4, data}; } array_view<bool> integral::enabled_coefficients() const { static const bool data = { true, true, true, false, false, true }; return array_view<bool>{6, data}; } """