ArmNN
 22.11
armnnDeserializer Namespace Reference

Classes

struct  BindingPointInfo
 
class  IDeserializer
 

Typedefs

using IDeserializerPtr = std::unique_ptr< IDeserializer, void(*)(IDeserializer *parser)>
 
using ConstTensorRawPtr = const armnnSerializer::ConstTensor *
 
using GraphPtr = const armnnSerializer::SerializedGraph *
 
using TensorRawPtr = const armnnSerializer::TensorInfo *
 
using Pooling2dDescriptor = const armnnSerializer::Pooling2dDescriptor *
 
using Pooling3dDescriptor = const armnnSerializer::Pooling3dDescriptor *
 
using NormalizationDescriptorPtr = const armnnSerializer::NormalizationDescriptor *
 
using LstmDescriptorPtr = const armnnSerializer::LstmDescriptor *
 
using LstmInputParamsPtr = const armnnSerializer::LstmInputParams *
 
using QLstmDescriptorPtr = const armnnSerializer::QLstmDescriptor *
 
using QunatizedLstmInputParamsPtr = const armnnSerializer::QuantizedLstmInputParams *
 
using TensorRawPtrVector = std::vector< TensorRawPtr >
 
using LayerRawPtr = const armnnSerializer::LayerBase *
 
using LayerBaseRawPtr = const armnnSerializer::LayerBase *
 
using LayerBaseRawPtrVector = std::vector< LayerBaseRawPtr >
 
using UnidirectionalSequenceLstmDescriptorPtr = const armnnSerializer::UnidirectionalSequenceLstmDescriptor *
 

Functions

bool CheckShape (const armnn::TensorShape &actual, const std::vector< uint32_t > &expected)
 
armnn::DataLayout ToDataLayout (armnnSerializer::DataLayout dataLayout)
 
armnn::ActivationFunction ToActivationFunction (armnnSerializer::ActivationFunction function)
 
armnn::ArgMinMaxFunction ToArgMinMaxFunction (armnnSerializer::ArgMinMaxFunction function)
 
armnn::ComparisonOperation ToComparisonOperation (armnnSerializer::ComparisonOperation operation)
 
armnn::ReduceOperation ToReduceOperation (armnnSerializer::ReduceOperation operation)
 
armnn::LogicalBinaryOperation ToLogicalBinaryOperation (armnnSerializer::LogicalBinaryOperation operation)
 
armnn::UnaryOperation ToUnaryOperation (armnnSerializer::UnaryOperation operation)
 
armnn::PaddingMode ToPaddingMode (armnnSerializer::PaddingMode paddingMode)
 
armnn::ResizeMethod ToResizeMethod (armnnSerializer::ResizeMethod method)
 
armnn::TensorInfo ToTensorInfo (TensorRawPtr tensorPtr)
 
armnn::ConstTensor ToConstTensor (ConstTensorRawPtr constTensorPtr)
 
const armnnSerializer::OriginsDescriptor * GetOriginsDescriptor (const armnnSerializer::SerializedGraph *graph, unsigned int layerIndex)
 

Typedef Documentation

◆ ConstTensorRawPtr

using ConstTensorRawPtr = const armnnSerializer::ConstTensor *

Definition at line 18 of file Deserializer.hpp.

◆ GraphPtr

using GraphPtr = const armnnSerializer::SerializedGraph *

Definition at line 19 of file Deserializer.hpp.

◆ IDeserializerPtr

using IDeserializerPtr = std::unique_ptr<IDeserializer, void(*)(IDeserializer* parser)>

Definition at line 25 of file IDeserializer.hpp.

◆ LayerBaseRawPtr

using LayerBaseRawPtr = const armnnSerializer::LayerBase *

Definition at line 30 of file Deserializer.hpp.

◆ LayerBaseRawPtrVector

using LayerBaseRawPtrVector = std::vector<LayerBaseRawPtr>

Definition at line 31 of file Deserializer.hpp.

◆ LayerRawPtr

using LayerRawPtr = const armnnSerializer::LayerBase *

Definition at line 29 of file Deserializer.hpp.

◆ LstmDescriptorPtr

using LstmDescriptorPtr = const armnnSerializer::LstmDescriptor *

Definition at line 24 of file Deserializer.hpp.

◆ LstmInputParamsPtr

using LstmInputParamsPtr = const armnnSerializer::LstmInputParams *

Definition at line 25 of file Deserializer.hpp.

◆ NormalizationDescriptorPtr

using NormalizationDescriptorPtr = const armnnSerializer::NormalizationDescriptor *

Definition at line 23 of file Deserializer.hpp.

◆ Pooling2dDescriptor

using Pooling2dDescriptor = const armnnSerializer::Pooling2dDescriptor *

Definition at line 21 of file Deserializer.hpp.

◆ Pooling3dDescriptor

using Pooling3dDescriptor = const armnnSerializer::Pooling3dDescriptor *

Definition at line 22 of file Deserializer.hpp.

◆ QLstmDescriptorPtr

using QLstmDescriptorPtr = const armnnSerializer::QLstmDescriptor *

Definition at line 26 of file Deserializer.hpp.

◆ QunatizedLstmInputParamsPtr

using QunatizedLstmInputParamsPtr = const armnnSerializer::QuantizedLstmInputParams *

Definition at line 27 of file Deserializer.hpp.

◆ TensorRawPtr

using TensorRawPtr = const armnnSerializer::TensorInfo *

Definition at line 20 of file Deserializer.hpp.

◆ TensorRawPtrVector

using TensorRawPtrVector = std::vector<TensorRawPtr>

Definition at line 28 of file Deserializer.hpp.

◆ UnidirectionalSequenceLstmDescriptorPtr

using UnidirectionalSequenceLstmDescriptorPtr = const armnnSerializer::UnidirectionalSequenceLstmDescriptor *

Definition at line 32 of file Deserializer.hpp.

Function Documentation

◆ CheckShape()

bool armnnDeserializer::CheckShape ( const armnn::TensorShape actual,
const std::vector< uint32_t > &  expected 
)

Definition at line 188 of file Deserializer.cpp.

References TensorShape::GetNumDimensions().

Referenced by IDeserializer::DeserializerImpl::OutputShapeOfReshape(), and TfLiteParserImpl::OutputShapeOfReshape().

189 {
190  const unsigned int actualSize = actual.GetNumDimensions();
191  if (actualSize != expected.size())
192  {
193  return false;
194  }
195 
196  for (unsigned int i = 0u; i < actualSize; i++)
197  {
198  if (actual[i] != static_cast<unsigned int>(expected[i]))
199  {
200  return false;
201  }
202  }
203 
204  return true;
205 }
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174

◆ GetOriginsDescriptor()

const armnnSerializer::OriginsDescriptor* armnnDeserializer::GetOriginsDescriptor ( const armnnSerializer::SerializedGraph *  graph,
unsigned int  layerIndex 
)

Definition at line 1967 of file Deserializer.cpp.

References CHECK_LAYERS, CHECK_LOCATION, CHECK_VALID_SIZE, BaseTensor< MemoryType >::GetInfo(), IDeserializer::DeserializerImpl::GetInputs(), IDeserializer::DeserializerImpl::GetLayerName(), FullyConnectedDescriptor::GetNumInputs(), IDeserializer::DeserializerImpl::GetOutputs(), IConnectableLayer::GetOutputSlot(), ChannelShuffleDescriptor::m_Axis, FullyConnectedDescriptor::m_BiasEnabled, FullyConnectedDescriptor::m_ConstantWeights, ComparisonDescriptor::m_Operation, ElementwiseUnaryDescriptor::m_Operation, FullyConnectedDescriptor::m_TransposeWeightMatrix, IOutputSlot::SetTensorInfo(), ToComparisonOperation(), ToConstTensor(), ToPaddingMode(), ToTensorInfo(), and ToUnaryOperation().

1969 {
1970  auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1971 
1972  switch (layerType)
1973  {
1974  case Layer::Layer_ConcatLayer:
1975  return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1976  case Layer::Layer_MergerLayer:
1977  return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1978  default:
1979  throw armnn::Exception("unknown layer type, should be concat or merger");
1980  }
1981 }
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46

◆ ToActivationFunction()

armnn::ActivationFunction armnnDeserializer::ToActivationFunction ( armnnSerializer::ActivationFunction  function)

Definition at line 470 of file Deserializer.cpp.

References armnn::Abs, armnn::BoundedReLu, armnn::Elu, armnn::HardSwish, armnn::LeakyReLu, armnn::Linear, armnn::ReLu, armnn::Sigmoid, armnn::Sqrt, armnn::Square, and armnn::TanH.

Referenced by IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo().

471 {
472  switch (function)
473  {
474  case armnnSerializer::ActivationFunction_Sigmoid:
476  case armnnSerializer::ActivationFunction_TanH:
478  case armnnSerializer::ActivationFunction_Linear:
480  case armnnSerializer::ActivationFunction_ReLu:
482  case armnnSerializer::ActivationFunction_BoundedReLu:
484  case armnnSerializer::ActivationFunction_LeakyReLu:
486  case armnnSerializer::ActivationFunction_Abs:
488  case armnnSerializer::ActivationFunction_Sqrt:
490  case armnnSerializer::ActivationFunction_Square:
492  case armnnSerializer::ActivationFunction_Elu:
494  case armnnSerializer::ActivationFunction_HardSwish:
496  default:
498  }
499 }
min(a, max(b, input)) ReLu1 & ReLu6.

◆ ToArgMinMaxFunction()

armnn::ArgMinMaxFunction armnnDeserializer::ToArgMinMaxFunction ( armnnSerializer::ArgMinMaxFunction  function)

Definition at line 501 of file Deserializer.cpp.

References armnn::Max, and armnn::Min.

Referenced by IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo().

502 {
503  switch (function)
504  {
505  case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Max:
507  case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Min:
508  default:
510  }
511 }

◆ ToComparisonOperation()

armnn::ComparisonOperation armnnDeserializer::ToComparisonOperation ( armnnSerializer::ComparisonOperation  operation)

Definition at line 513 of file Deserializer.cpp.

References armnn::Equal, armnn::Greater, armnn::GreaterOrEqual, armnn::Less, armnn::LessOrEqual, and armnn::NotEqual.

Referenced by GetOriginsDescriptor().

514 {
515  switch (operation)
516  {
517  case armnnSerializer::ComparisonOperation::ComparisonOperation_Equal:
519  case armnnSerializer::ComparisonOperation::ComparisonOperation_Greater:
521  case armnnSerializer::ComparisonOperation::ComparisonOperation_GreaterOrEqual:
523  case armnnSerializer::ComparisonOperation::ComparisonOperation_Less:
525  case armnnSerializer::ComparisonOperation::ComparisonOperation_LessOrEqual:
527  case armnnSerializer::ComparisonOperation::ComparisonOperation_NotEqual:
528  default:
530  }
531 }

◆ ToConstTensor()

armnn::ConstTensor armnnDeserializer::ToConstTensor ( ConstTensorRawPtr  constTensorPtr)

Definition at line 722 of file Deserializer.cpp.

References CheckLocation::AsString(), CHECK_CONST_TENSOR_PTR, CHECK_CONST_TENSOR_SIZE, CHECK_LOCATION, TensorInfo::GetNumElements(), TensorInfo::SetConstant(), and ToTensorInfo().

Referenced by IDeserializer::DeserializerImpl::GetLstmDescriptor(), IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(), GetOriginsDescriptor(), IDeserializer::DeserializerImpl::GetQLstmDescriptor(), and IDeserializer::DeserializerImpl::GetUnidirectionalSequenceLstmDescriptor().

723 {
724  CHECK_CONST_TENSOR_PTR(constTensorPtr);
725  armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
726  tensorInfo.SetConstant();
727 
728  switch (constTensorPtr->data_type())
729  {
730  case ConstTensorData_ByteData:
731  {
732  auto byteData = constTensorPtr->data_as_ByteData()->data();
733  CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
734  return armnn::ConstTensor(tensorInfo, byteData->data());
735  }
736  case ConstTensorData_ShortData:
737  {
738  auto shortData = constTensorPtr->data_as_ShortData()->data();
739  CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
740  return armnn::ConstTensor(tensorInfo, shortData->data());
741  }
742  case ConstTensorData_IntData:
743  {
744  auto intData = constTensorPtr->data_as_IntData()->data();
745  CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
746  return armnn::ConstTensor(tensorInfo, intData->data());
747  }
748  case ConstTensorData_LongData:
749  {
750  auto longData = constTensorPtr->data_as_LongData()->data();
751  CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
752  return armnn::ConstTensor(tensorInfo, longData->data());
753  }
754  default:
755  {
756  CheckLocation location = CHECK_LOCATION();
757  throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
758  constTensorPtr->data_type(),
759  EnumNameConstTensorData(constTensorPtr->data_type()),
760  location.AsString()));
761  }
762  }
763 }
std::string AsString() const
Definition: Exceptions.hpp:29
#define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE)
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
#define CHECK_CONST_TENSOR_PTR(TENSOR_PTR)
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:514
armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
unsigned int GetNumElements() const
Definition: Tensor.hpp:196

◆ ToDataLayout()

armnn::DataLayout armnnDeserializer::ToDataLayout ( armnnSerializer::DataLayout  dataLayout)

Definition at line 454 of file Deserializer.cpp.

References armnn::NCDHW, armnn::NCHW, armnn::NDHWC, and armnn::NHWC.

Referenced by IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(), IDeserializer::DeserializerImpl::GetNormalizationDescriptor(), IDeserializer::DeserializerImpl::GetQLstmDescriptor(), and IDeserializer::DeserializerImpl::OutputShapeOfReshape().

455 {
456  switch (dataLayout)
457  {
458  case armnnSerializer::DataLayout::DataLayout_NHWC:
460  case armnnSerializer::DataLayout::DataLayout_NDHWC:
462  case armnnSerializer::DataLayout::DataLayout_NCDHW:
464  case armnnSerializer::DataLayout::DataLayout_NCHW:
465  default:
467  }
468 }

◆ ToLogicalBinaryOperation()

armnn::LogicalBinaryOperation armnnDeserializer::ToLogicalBinaryOperation ( armnnSerializer::LogicalBinaryOperation  operation)

Definition at line 552 of file Deserializer.cpp.

References armnn::LogicalAnd, and armnn::LogicalOr.

Referenced by IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo().

553 {
554  switch (operation)
555  {
556  case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalAnd:
558  case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalOr:
560  default:
561  throw armnn::InvalidArgumentException("Logical Binary operation unknown");
562  }
563 }

◆ ToPaddingMode()

armnn::PaddingMode armnnDeserializer::ToPaddingMode ( armnnSerializer::PaddingMode  paddingMode)

Definition at line 590 of file Deserializer.cpp.

References armnn::Constant, armnn::Reflect, and armnn::Symmetric.

Referenced by GetOriginsDescriptor().

591 {
592  switch (paddingMode)
593  {
594  case armnnSerializer::PaddingMode::PaddingMode_Reflect:
596  case armnnSerializer::PaddingMode::PaddingMode_Symmetric:
598  default:
600  }
601 }

◆ ToReduceOperation()

armnn::ReduceOperation armnnDeserializer::ToReduceOperation ( armnnSerializer::ReduceOperation  operation)

Definition at line 533 of file Deserializer.cpp.

References armnn::Max, armnn::Mean, armnn::Min, armnn::Prod, and armnn::Sum.

Referenced by IDeserializer::DeserializerImpl::OutputShapeOfReshape().

534 {
535  switch (operation)
536  {
537  case armnnSerializer::ReduceOperation::ReduceOperation_Sum:
539  case armnnSerializer::ReduceOperation::ReduceOperation_Max:
541  case armnnSerializer::ReduceOperation::ReduceOperation_Mean:
543  case armnnSerializer::ReduceOperation::ReduceOperation_Min:
545  case armnnSerializer::ReduceOperation::ReduceOperation_Prod:
547  default:
549  }
550 }

◆ ToResizeMethod()

armnn::ResizeMethod armnnDeserializer::ToResizeMethod ( armnnSerializer::ResizeMethod  method)

Definition at line 603 of file Deserializer.cpp.

References armnn::Bilinear, and armnn::NearestNeighbor.

Referenced by IDeserializer::DeserializerImpl::OutputShapeOfReshape().

604 {
605  switch (method)
606  {
607  case armnnSerializer::ResizeMethod_NearestNeighbor:
609  case armnnSerializer::ResizeMethod_Bilinear:
611  default:
613  }
614 }

◆ ToTensorInfo()

armnn::TensorInfo armnnDeserializer::ToTensorInfo ( TensorRawPtr  tensorPtr)

Definition at line 616 of file Deserializer.cpp.

References CheckLocation::AsString(), armnn::Boolean, CHECK_LOCATION, CHECK_TENSOR_PTR, armnn::Float16, armnn::Float32, armnn::MaxNumOfTensorDimensions, armnn::QAsymmS8, armnn::QAsymmU8, armnn::QSymmS16, armnn::QSymmS8, armnn::Scalar, armnn::Signed32, and armnn::Signed64.

Referenced by armnnTfLiteParser::AsFloatArray(), armnnTfLiteParser::ComputeWrappedIndex(), OnnxParserImpl::CreateNetworkFromString(), TfLiteParserImpl::GetBuffer(), IDeserializer::DeserializerImpl::GetLstmDescriptor(), TfLiteParserImpl::GetNetworkInputBindingInfo(), IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(), TfLiteParserImpl::GetNetworkOutputBindingInfo(), IDeserializer::DeserializerImpl::GetNormalizationDescriptor(), GetOriginsDescriptor(), TfLiteParserImpl::GetOutputTensorIds(), IDeserializer::DeserializerImpl::GetPooling3dDescriptor(), IDeserializer::DeserializerImpl::GetQLstmDescriptor(), IDeserializer::DeserializerImpl::GetUnidirectionalSequenceLstmDescriptor(), IDeserializer::DeserializerImpl::OutputShapeOfReshape(), TfLiteParserImpl::OutputShapeOfReshape(), TfLiteParserImpl::OutputShapeOfSqueeze(), and ToConstTensor().

617 {
618  armnn::DataType type;
619  CHECK_TENSOR_PTR(tensorPtr);
620 
621  switch (tensorPtr->dataType())
622  {
623  case DataType_QAsymmS8:
625  break;
626  case DataType_QSymmS8:
628  break;
629  case DataType_QuantisedAsymm8:
630  case DataType_QAsymmU8:
632  break;
633  case DataType_QSymmS16:
634  case DataType_QuantisedSymm16:
636  break;
637  case DataType_Signed32:
639  break;
640  case DataType_Signed64:
642  break;
643  case DataType_Float32:
645  break;
646  case DataType_Float16:
648  break;
649  case DataType_Boolean:
651  break;
652  default:
653  {
654  CheckLocation location = CHECK_LOCATION();
655  throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
656  tensorPtr->dataType(),
657  EnumNameDataType(tensorPtr->dataType()),
658  location.AsString()));
659  }
660  }
661 
662  float quantizationScale = tensorPtr->quantizationScale();
663  int32_t quantizationOffset = tensorPtr->quantizationOffset();
664 
665  if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
666  {
668  type,
669  quantizationScale,
670  quantizationOffset);
671  }
672  else if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::NotSpecified))
673  {
674  armnn::TensorInfo result(TensorShape{Dimensionality::NotSpecified},
675  type,
676  quantizationScale,
677  quantizationOffset);
678  return result;
679  }
680 
681  auto dimensions = tensorPtr->dimensions();
682  unsigned int size = dimensions->size();
683  std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
684  bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];
685  std::fill_n(dimensionsSpecificity, armnn::MaxNumOfTensorDimensions, true);
686  // For backwards compatibility check if the dimensionSpecificity vector is present first.
687  // The default is to have dimensionSpecificity set to all true's anyway.
688  if (tensorPtr->dimensionSpecificity() != nullptr)
689  {
690  auto dimensionSpecificity = tensorPtr->dimensionSpecificity();
691  size = dimensionSpecificity->size();
692  for (unsigned int i = 0; i < size; ++i)
693  {
694  dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
695  }
696  }
697  // Construct a TensorShape
698  TensorShape shape(size, outputDims.data(), dimensionsSpecificity);
699 
700  auto quantizationScales = tensorPtr->quantizationScales();
701  if (quantizationScales)
702  {
703  unsigned int quantizationScalesSize = quantizationScales->size();
704  std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
705  unsigned int quantizationDim = tensorPtr->quantizationDim();
706  armnn::TensorInfo result(shape,
707  type,
708  scales,
709  quantizationDim);
710  return result;
711  }
712 
713  // two statements (on purpose) for easier debugging:
714  armnn::TensorInfo result(shape,
715  type,
716  quantizationScale,
717  quantizationOffset);
718 
719  return result;
720 }
std::string AsString() const
Definition: Exceptions.hpp:29
#define CHECK_TENSOR_PTR(TENSOR_PTR)
DataType
Definition: Types.hpp:48
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
constexpr unsigned int MaxNumOfTensorDimensions
Definition: Types.hpp:31

◆ ToUnaryOperation()

armnn::UnaryOperation armnnDeserializer::ToUnaryOperation ( armnnSerializer::UnaryOperation  operation)

Definition at line 565 of file Deserializer.cpp.

References armnn::Abs, armnn::Exp, armnn::Log, armnn::LogicalNot, armnn::Neg, armnn::Rsqrt, armnn::Sin, and armnn::Sqrt.

Referenced by GetOriginsDescriptor().

566 {
567  switch (operation)
568  {
569  case armnnSerializer::UnaryOperation::UnaryOperation_Abs:
571  case armnnSerializer::UnaryOperation::UnaryOperation_Rsqrt:
573  case armnnSerializer::UnaryOperation::UnaryOperation_Sqrt:
575  case armnnSerializer::UnaryOperation::UnaryOperation_Exp:
577  case armnnSerializer::UnaryOperation::UnaryOperation_Neg:
579  case armnnSerializer::UnaryOperation::UnaryOperation_LogicalNot:
581  case armnnSerializer::UnaryOperation::UnaryOperation_Log:
583  case armnnSerializer::UnaryOperation::UnaryOperation_Sin:
585  default:
586  throw armnn::InvalidArgumentException("Unary operation unknown");
587  }
588 }