AdjointAbstractBoundaryOperator<BasisFunctionType, ResultType>::
AdjointAbstractBoundaryOperator(
        const BoundaryOperator<BasisFunctionType, ResultType>& boundaryOp,
        int symmetry) :
    Base(boundaryOp.dualToRange(),
         boundaryOp.domain() == boundaryOp.range() ?
             boundaryOp.dualToRange() :
             // assume that domain == dualToRange, we'll verify it
             // in the body of the constructor
             boundaryOp.range(),
         boundaryOp.domain(),
         "adj(" + boundaryOp.label() + ")",
         symmetry & AUTO_SYMMETRY ?
             boundaryOp.abstractOperator()->symmetry() :
             symmetry),
    m_operator(boundaryOp)
{
    if (boost::is_complex<BasisFunctionType>())
        throw std::logic_error(
            "AdjointAbstractBoundaryOperator(): Taking the adjoint of operators "
            "acting on complex-valued basis functions is not supported");
    if (boundaryOp.domain() != boundaryOp.range() &&
            boundaryOp.domain() != boundaryOp.dualToRange())
        throw std::runtime_error(
                "AdjointAbstractBoundaryOperator::"
                "AdjointAbstractBoundaryOperator(): "
                "Dual to the domain of the operator to invert cannot be determined "
                "since the domain is different from both "
                "the range and the space dual to its range");
}
AbstractBoundaryOperatorPseudoinverse<BasisFunctionType, ResultType>::
AbstractBoundaryOperatorPseudoinverse(
        // TODO: add a solver argument specifying how to calculate the pseudoinv.
        const BoundaryOperator<BasisFunctionType, ResultType>& operatorToInvert) :
    Base(operatorToInvert.range(), operatorToInvert.domain(),
         operatorToInvert.domain() == operatorToInvert.range() ?
             operatorToInvert.dualToRange() :
             // assume that domain == dualToRange, we'll verify it
             // in the body of the constructor
             operatorToInvert.range(),
         "pinv(" + operatorToInvert.label() + ")",
         throwIfUninitialized(operatorToInvert,
                              "AbstractBoundaryOperatorPseudoinverse::"
                              "AbstractBoundaryOperatorPseudoinverse(): "
                              "the boundary operator to be inverted must be "
                              "initialized"
                              ).abstractOperator()->symmetry()),
    m_operator(operatorToInvert),
    m_id(boost::make_shared<AbstractBoundaryOperatorPseudoinverseId<
         BasisFunctionType, ResultType> >(
             operatorToInvert))
{
    if (operatorToInvert.domain() != operatorToInvert.range() &&
            operatorToInvert.domain() != operatorToInvert.dualToRange())
        throw std::runtime_error(
                "AbstractBoundaryOperatorPseudoinverse::"
                "AbstractBoundaryOperatorPseudoinverse(): "
                "Dual to the domain of the operator to invert cannot be determined "
                "since the domain is different from both "
                "the range and the space dual to its range");
}
AbstractBoundaryOperatorPseudoinverse<BasisFunctionType, ResultType>::
AbstractBoundaryOperatorPseudoinverse(
        // TODO: add a solver argument specifying how to calculate the pseudoinv.
        const BoundaryOperator<BasisFunctionType, ResultType>& operatorToInvert,
        const shared_ptr<const Space<BasisFunctionType> >& dualToRange) :
    Base(operatorToInvert.range(), operatorToInvert.domain(),dualToRange,
         "pinv(" + operatorToInvert.label() + ")",
         throwIfUninitialized(operatorToInvert,
                              "AbstractBoundaryOperatorPseudoinverse::"
                              "AbstractBoundaryOperatorPseudoinverse(): "
                              "the boundary operator to be inverted must be "
                              "initialized"
                              ).abstractOperator()->symmetry()),
    m_operator(operatorToInvert),
    m_id(boost::make_shared<AbstractBoundaryOperatorPseudoinverseId<
         BasisFunctionType, ResultType> >(
             operatorToInvert))
{
}