


'''simple docstring'''







import itertools
import random
import unittest

import numpy as np

from transformers import BatchFeature, SpeechTaFeatureExtractor
from transformers.testing_utils import require_torch
from transformers.utils.import_utils import is_torch_available

from ...test_sequence_feature_extraction_common import SequenceFeatureExtractionTestMixin


if is_torch_available():
   import torch


A				:					List[str]    						=			random.Random()






def 				lowerCAmelCase__	(    lowerCamelCase					:      List[Any]  ,lowerCamelCase					:      Optional[int]=1.0  ,lowerCamelCase					:      Union[str, Any]=None  ,lowerCamelCase					:      List[Any]=None       ):
       if rng is None:
              _A					:     Optional[Any]     = global_rng

       _A					:     Dict     = []
       for batch_idx in range(shape[0]       ):
              values.append([]       )
              for _ in range(shape[1]       ):
                     values[-1].append(rng.random() * scale       )

       return values


@require_torch
class 			__lowerCamelCase			(	unittest.TestCase	):
    """simple docstring"""


    def __init__(  self      :							Tuple				,							SCREAMING_SNAKE_CASE      :							Tuple				,							SCREAMING_SNAKE_CASE      :							str=7				,							SCREAMING_SNAKE_CASE      :							int=400				,							SCREAMING_SNAKE_CASE      :							Union[str, Any]=2000				,							SCREAMING_SNAKE_CASE      :							List[Any]=1				,							SCREAMING_SNAKE_CASE      :							Union[str, Any]=0.0				,							SCREAMING_SNAKE_CASE      :							List[Any]=16000				,							SCREAMING_SNAKE_CASE      :							Tuple=True				,							SCREAMING_SNAKE_CASE      :							int=80				,							SCREAMING_SNAKE_CASE      :							Optional[Any]=16				,							SCREAMING_SNAKE_CASE      :							Optional[Any]=64				,							SCREAMING_SNAKE_CASE      :							str="hann_window"				,							SCREAMING_SNAKE_CASE      :							str=80				,							SCREAMING_SNAKE_CASE      :							Optional[Any]=7600				,							SCREAMING_SNAKE_CASE      :							Tuple=1e-10				,							SCREAMING_SNAKE_CASE      :							Union[str, Any]=True				,							):
           _A					:     str     = parent
           _A					:     Tuple     = batch_size
           _A					:     Optional[Any]     = min_seq_length
           _A					:     str     = max_seq_length
           _A					:     Union[str, Any]     = (self.max_seq_length - self.min_seq_length) // (self.batch_size - 1)
           _A					:     Dict     = feature_size
           _A					:     Optional[Any]     = padding_value
           _A					:     Dict     = sampling_rate
           _A					:     Optional[int]     = do_normalize
           _A					:     int     = num_mel_bins
           _A					:     str     = hop_length
           _A					:     Union[str, Any]     = win_length
           _A					:     List[str]     = win_function
           _A					:     int     = fmin
           _A					:     Any     = fmax
           _A					:     List[str]     = mel_floor
           _A					:     List[str]     = return_attention_mask


    def        A   (  self      :							List[Any]):
           return {
               "feature_size": self.feature_size,
               "padding_value": self.padding_value,
               "sampling_rate": self.sampling_rate,
               "do_normalize": self.do_normalize,
               "num_mel_bins": self.num_mel_bins,
               "hop_length": self.hop_length,
               "win_length": self.win_length,
               "win_function": self.win_function,
               "fmin": self.fmin,
               "fmax": self.fmax,
               "mel_floor": self.mel_floor,
               "return_attention_mask": self.return_attention_mask,
           }


    def        A   (  self      :							Union[str, Any]				,							SCREAMING_SNAKE_CASE      :							Any=False				,							SCREAMING_SNAKE_CASE      :							Any=False):
           def _flatten(SCREAMING_SNAKE_CASE      :							int):
                  return list(itertools.chain(*SCREAMING_SNAKE_CASE))

           if equal_length:
                  _A					:     List[Any]     = floats_list((self.batch_size, self.max_seq_length))
           else:
                  # make sure that inputs increase in size
                  _A					:     List[Any]     = [
                      _flatten(floats_list((x, self.feature_size)))
                      for x in range(self.min_seq_length				,							self.max_seq_length				,							self.seq_length_diff)
                  ]

           if numpify:
                  _A					:     Dict     = [np.asarray(SCREAMING_SNAKE_CASE) for x in speech_inputs]

           return speech_inputs


    def        A   (  self      :							List[Any]				,							SCREAMING_SNAKE_CASE      :							str=False				,							SCREAMING_SNAKE_CASE      :							Optional[int]=False):
           if equal_length:
                  _A					:     List[str]     = [floats_list((self.max_seq_length, self.num_mel_bins)) for _ in range(self.batch_size)]
           else:
                  # make sure that inputs increase in size
                  _A					:     Dict     = [
                      floats_list((x, self.num_mel_bins))
                      for x in range(self.min_seq_length				,							self.max_seq_length				,							self.seq_length_diff)
                  ]

           if numpify:
                  _A					:     List[Any]     = [np.asarray(SCREAMING_SNAKE_CASE) for x in speech_inputs]

           return speech_inputs




@require_torch
class 			__lowerCamelCase			(	a_    , unittest.TestCase	):
    """simple docstring"""
    a													=   SpeechTaFeatureExtractor


    def        A   (  self      :							List[Any]):
           _A					:     Optional[int]     = SpeechTaFeatureExtractionTester(self)


    def        A   (  self      :							Any				,							SCREAMING_SNAKE_CASE      :							List[Any]):
           self.assertTrue(np.all(np.mean(SCREAMING_SNAKE_CASE				,							axis=0) < 1e-3))
           self.assertTrue(np.all(np.abs(np.var(SCREAMING_SNAKE_CASE				,							axis=0) - 1) < 1e-3))


    def        A   (  self      :							Optional[Any]):
           # Tests that all call wrap to encode_plus and batch_encode_plus
           _A					:     Union[str, Any]     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           # create three inputs of length 800, 1000, and 1200
           _A					:     Optional[int]     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]
           _A					:     str     = [np.asarray(SCREAMING_SNAKE_CASE) for speech_input in speech_inputs]

           # Test not batched input
           _A					:     List[str]     = feat_extract(speech_inputs[0]				,							return_tensors='np').input_values
           _A					:     str     = feat_extract(np_speech_inputs[0]				,							return_tensors='np').input_values
           self.assertTrue(np.allclose(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE				,							atol=1e-3))

           # Test batched
           _A					:     str     = feat_extract(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           _A					:     Tuple     = feat_extract(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           for enc_seq_a, enc_seq_a in zip(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  self.assertTrue(np.allclose(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE				,							atol=1e-3))


    def        A   (  self      :							List[str]):
           _A					:     List[Any]     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           _A					:     Optional[Any]     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]

           _A					:     List[Any]     = ['longest', 'max_length', 'do_not_pad']
           _A					:     str     = [None, 1600, None]
           for max_length, padding in zip(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  _A					:     str     = feat_extract(SCREAMING_SNAKE_CASE				,							padding=SCREAMING_SNAKE_CASE				,							max_length=SCREAMING_SNAKE_CASE				,							return_tensors='np')
                  _A					:     Tuple     = processed.input_values

                  self._check_zero_mean_unit_variance(input_values[0][:800])
                  self.assertTrue(input_values[0][800:].sum() < 1e-6)
                  self._check_zero_mean_unit_variance(input_values[1][:1000])
                  self.assertTrue(input_values[0][1000:].sum() < 1e-6)
                  self._check_zero_mean_unit_variance(input_values[2][:1200])


    def        A   (  self      :							Any):
           _A					:     Dict     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           _A					:     Dict     = range(800				,							1400				,							200)
           _A					:     List[str]     = [floats_list((1, x))[0] for x in lengths]

           _A					:     Any     = ['longest', 'max_length', 'do_not_pad']
           _A					:     int     = [None, 1600, None]

           for max_length, padding in zip(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  _A					:     Dict     = feat_extract(SCREAMING_SNAKE_CASE				,							max_length=SCREAMING_SNAKE_CASE				,							padding=SCREAMING_SNAKE_CASE)
                  _A					:     Any     = processed.input_values

                  self._check_zero_mean_unit_variance(input_values[0][:800])
                  self._check_zero_mean_unit_variance(input_values[1][:1000])
                  self._check_zero_mean_unit_variance(input_values[2][:1200])


    def        A   (  self      :							Optional[Any]):
           _A					:     List[str]     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           _A					:     Tuple     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]
           _A					:     List[Any]     = feat_extract(
               SCREAMING_SNAKE_CASE				,							truncation=SCREAMING_SNAKE_CASE				,							max_length=1000				,							padding='max_length'				,							return_tensors='np')
           _A					:     Optional[int]     = processed.input_values

           self._check_zero_mean_unit_variance(input_values[0, :800])
           self._check_zero_mean_unit_variance(input_values[1])
           self._check_zero_mean_unit_variance(input_values[2])


    def        A   (  self      :							Union[str, Any]):
           _A					:     List[Any]     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           _A					:     str     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]
           _A					:     Optional[Any]     = feat_extract(
               SCREAMING_SNAKE_CASE				,							truncation=SCREAMING_SNAKE_CASE				,							max_length=1000				,							padding='longest'				,							return_tensors='np')
           _A					:     int     = processed.input_values

           self._check_zero_mean_unit_variance(input_values[0, :800])
           self._check_zero_mean_unit_variance(input_values[1, :1000])
           self._check_zero_mean_unit_variance(input_values[2])

           # make sure that if max_length < longest -> then pad to max_length
           self.assertTrue(input_values.shape == (3, 1000))

           _A					:     List[Any]     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]
           _A					:     List[Any]     = feat_extract(
               SCREAMING_SNAKE_CASE				,							truncation=SCREAMING_SNAKE_CASE				,							max_length=2000				,							padding='longest'				,							return_tensors='np')
           _A					:     Union[str, Any]     = processed.input_values

           self._check_zero_mean_unit_variance(input_values[0, :800])
           self._check_zero_mean_unit_variance(input_values[1, :1000])
           self._check_zero_mean_unit_variance(input_values[2])

           # make sure that if max_length > longest -> then pad to longest
           self.assertTrue(input_values.shape == (3, 1200))


    def        A   (  self      :							List[str]):
           _A					:     Tuple     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           _A					:     Optional[int]     = np.random.rand(100).astype(np.floataa)
           _A					:     str     = np_speech_inputs.tolist()

           for inputs in [py_speech_inputs, np_speech_inputs]:
                  _A					:     List[Any]     = feature_extractor.pad([{'input_values': inputs}]				,							return_tensors='np')
                  self.assertTrue(np_processed.input_values.dtype == np.floataa)
                  _A					:     Optional[Any]     = feature_extractor.pad([{'input_values': inputs}]				,							return_tensors='pt')
                  self.assertTrue(pt_processed.input_values.dtype == torch.floataa)


    def        A   (  self      :							Any):
           # Tests that all call wrap to encode_plus and batch_encode_plus
           _A					:     Any     = self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict())
           # create three inputs of length 800, 1000, and 1200
           _A					:     Dict     = [floats_list((1, x))[0] for x in range(800				,							1400				,							200)]
           _A					:     Any     = [np.asarray(SCREAMING_SNAKE_CASE) for speech_input in speech_inputs]

           # Test feature size
           _A					:     Optional[Any]     = feature_extractor(audio_target=SCREAMING_SNAKE_CASE				,							padding=SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           self.assertTrue(input_values.ndim == 3)
           self.assertTrue(input_values.shape[-1] == feature_extractor.num_mel_bins)

           # Test not batched input
           _A					:     Optional[int]     = feature_extractor(speech_inputs[0]				,							return_tensors='np').input_values
           _A					:     Tuple     = feature_extractor(np_speech_inputs[0]				,							return_tensors='np').input_values
           self.assertTrue(np.allclose(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE				,							atol=1e-3))

           # Test batched
           _A					:     Optional[int]     = feature_extractor(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           _A					:     Tuple     = feature_extractor(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           for enc_seq_a, enc_seq_a in zip(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  self.assertTrue(np.allclose(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE				,							atol=1e-3))

           # Test 2-D numpy arrays are batched.
           _A					:     Optional[Any]     = [floats_list((1, x))[0] for x in (800, 800, 800)]
           _A					:     Any     = np.asarray(SCREAMING_SNAKE_CASE)
           _A					:     str     = feature_extractor(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           _A					:     Any     = feature_extractor(SCREAMING_SNAKE_CASE				,							return_tensors='np').input_values
           for enc_seq_a, enc_seq_a in zip(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  self.assertTrue(np.allclose(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE				,							atol=1e-3))


    def        A   (  self      :							Optional[Any]):
           _A					:     Dict     = self.feat_extract_tester.prepare_inputs_for_target()
           _A					:     int     = self.feature_extraction_class(**self.feat_extract_dict)
           _A					:     Optional[int]     = feat_extract.model_input_names[0]

           _A					:     Tuple     = BatchFeature({input_name: speech_inputs})

           self.assertTrue(all(len(SCREAMING_SNAKE_CASE) == len(SCREAMING_SNAKE_CASE) for x, y in zip(SCREAMING_SNAKE_CASE				,							processed_features[input_name])))

           _A					:     List[Any]     = self.feat_extract_tester.prepare_inputs_for_target(equal_length=SCREAMING_SNAKE_CASE)
           _A					:     Union[str, Any]     = BatchFeature({input_name: speech_inputs}				,							tensor_type='np')

           _A					:     Tuple     = processed_features[input_name]

           if len(batch_features_input.shape) < 3:
                  _A					:     Any     = batch_features_input[:, :, None]

           self.assertTrue(
               batch_features_input.shape
               == (self.feat_extract_tester.batch_size, len(speech_inputs[0]), self.feat_extract_tester.num_mel_bins))


    @require_torch
    def        A   (  self      :							Union[str, Any]):
           _A					:     Tuple     = self.feat_extract_tester.prepare_inputs_for_target(equal_length=SCREAMING_SNAKE_CASE)
           _A					:     str     = self.feature_extraction_class(**self.feat_extract_dict)
           _A					:     Dict     = feat_extract.model_input_names[0]

           _A					:     Any     = BatchFeature({input_name: speech_inputs}				,							tensor_type='pt')

           _A					:     List[Any]     = processed_features[input_name]

           if len(batch_features_input.shape) < 3:
                  _A					:     List[Any]     = batch_features_input[:, :, None]

           self.assertTrue(
               batch_features_input.shape
               == (self.feat_extract_tester.batch_size, len(speech_inputs[0]), self.feat_extract_tester.num_mel_bins))


    @require_torch
    def        A   (  self      :							List[Any]):
           _A					:     Optional[int]     = self.feature_extraction_class(**self.feat_extract_dict)
           _A					:     List[str]     = self.feat_extract_tester.prepare_inputs_for_target()
           _A					:     List[Any]     = feat_extract.model_input_names[0]

           _A					:     List[str]     = BatchFeature({input_name: speech_inputs})

           _A					:     int     = feat_extract.num_mel_bins  # hack!

           _A					:     List[Any]     = feat_extract.pad(SCREAMING_SNAKE_CASE				,							padding='longest'				,							return_tensors='np')[input_name]
           _A					:     Tuple     = feat_extract.pad(SCREAMING_SNAKE_CASE				,							padding='longest'				,							return_tensors='pt')[input_name]

           self.assertTrue(abs(input_np.astype(np.floataa).sum() - input_pt.numpy().astype(np.floataa).sum()) < 1e-2)


    def        A   (  self      :							Tuple):
           _A					:     int     = self.feat_extract_dict
           _A					:     List[str]     = True
           _A					:     Tuple     = self.feature_extraction_class(**SCREAMING_SNAKE_CASE)
           _A					:     str     = self.feat_extract_tester.prepare_inputs_for_target()
           _A					:     Any     = [len(SCREAMING_SNAKE_CASE) for x in speech_inputs]
           _A					:     Union[str, Any]     = feat_extract.model_input_names[0]

           _A					:     List[str]     = BatchFeature({input_name: speech_inputs})

           _A					:     Optional[Any]     = feat_extract.num_mel_bins  # hack!

           _A					:     str     = feat_extract.pad(SCREAMING_SNAKE_CASE				,							padding='longest'				,							return_tensors='np')
           self.assertIn('attention_mask'				,							SCREAMING_SNAKE_CASE)
           self.assertListEqual(list(processed.attention_mask.shape)				,							list(processed[input_name].shape[:2]))
           self.assertListEqual(processed.attention_mask.sum(-1).tolist()				,							SCREAMING_SNAKE_CASE)


    def        A   (  self      :							int):
           _A					:     Optional[int]     = self.feat_extract_dict
           _A					:     Optional[int]     = True
           _A					:     List[str]     = self.feature_extraction_class(**SCREAMING_SNAKE_CASE)
           _A					:     Optional[Any]     = self.feat_extract_tester.prepare_inputs_for_target()
           _A					:     List[Any]     = [len(SCREAMING_SNAKE_CASE) for x in speech_inputs]
           _A					:     Dict     = feat_extract.model_input_names[0]

           _A					:     Optional[int]     = BatchFeature({input_name: speech_inputs})
           _A					:     Any     = min(SCREAMING_SNAKE_CASE)

           _A					:     Tuple     = feat_extract.num_mel_bins  # hack!

           _A					:     Any     = feat_extract.pad(
               SCREAMING_SNAKE_CASE				,							padding='max_length'				,							max_length=SCREAMING_SNAKE_CASE				,							truncation=SCREAMING_SNAKE_CASE				,							return_tensors='np')
           self.assertIn('attention_mask'				,							SCREAMING_SNAKE_CASE)
           self.assertListEqual(
               list(processed_pad.attention_mask.shape)				,							[processed_pad[input_name].shape[0], max_length])
           self.assertListEqual(
               processed_pad.attention_mask[:, :max_length].sum(-1).tolist()				,							[max_length for x in speech_inputs])


    def        A   (  self      :							Dict				,							SCREAMING_SNAKE_CASE      :							int):
           from datasets import load_dataset

           _A					:     int     = load_dataset('hf-internal-testing/librispeech_asr_dummy'				,							'clean'				,							split='validation')
           # automatic decoding with librispeech
           _A					:     Optional[int]     = ds.sort('id').select(range(SCREAMING_SNAKE_CASE))[:num_samples]['audio']

           return [x["array"] for x in speech_samples]


    def        A   (  self      :							List[str]):
           # fmt: off
           _A					:     List[Any]     = torch.tensor(
               [2.38_04e-03, 2.07_52e-03, 1.98_36e-03, 2.10_57e-03, 1.61_74e-03,
                3.05_18e-04, 9.15_53e-05, 3.35_69e-04, 9.76_56e-04, 1.83_11e-03,
                2.01_42e-03, 2.10_57e-03, 1.73_95e-03, 4.57_76e-04, -3.96_73e-04,
                4.57_76e-04, 1.00_71e-03, 9.15_53e-05, 4.88_28e-04, 1.15_97e-03,
                7.32_42e-04, 9.46_04e-04, 1.80_05e-03, 1.83_11e-03, 8.85_01e-04,
                4.27_25e-04, 4.88_28e-04, 7.32_42e-04, 1.09_86e-03, 2.10_57e-03])
           # fmt: on

           _A					:     Any     = self._load_datasamples(1)
           _A					:     Tuple     = SpeechTaFeatureExtractor()
           _A					:     List[str]     = feature_extractor(SCREAMING_SNAKE_CASE				,							return_tensors='pt').input_values
           self.assertEquals(input_values.shape				,							(1, 93680))
           self.assertTrue(torch.allclose(input_values[0, :30]				,							SCREAMING_SNAKE_CASE				,							atol=1e-6))


    def        A   (  self      :							List[Any]):
           # fmt: off
           _A					:     List[str]     = torch.tensor(
               [-2.6870, -3.0104, -3.1356, -3.5352, -3.0044, -3.0353, -3.4719, -3.6777,
                -3.1520, -2.9435, -2.6553, -2.8795, -2.9944, -2.5921, -3.0279, -3.0386,
                -3.0864, -3.1291, -3.2353, -2.7444, -2.6831, -2.7287, -3.1761, -3.1571,
                -3.2726, -3.0582, -3.1007, -3.4533, -3.4695, -3.0998])
           # fmt: on

           _A					:     str     = self._load_datasamples(1)
           _A					:     List[str]     = SpeechTaFeatureExtractor()
           _A					:     List[str]     = feature_extractor(audio_target=SCREAMING_SNAKE_CASE				,							return_tensors='pt').input_values
           self.assertEquals(input_values.shape				,							(1, 366, 80))
           self.assertTrue(torch.allclose(input_values[0, 0, :30]				,							SCREAMING_SNAKE_CASE				,							atol=1e-4))










'''simple docstring'''







from typing import TYPE_CHECKING

from ...utils import OptionalDependencyNotAvailable, _LazyModule, is_torch_available, is_vision_available


A				:					Optional[int]    						=			{
    '''configuration_mask2former''': [
        '''MASK2FORMER_PRETRAINED_CONFIG_ARCHIVE_MAP''',
        '''Mask2FormerConfig''',
    ],
}

try:
   if not is_vision_available():
      raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
   pass
else:
   A				:					Tuple    						=			['''Mask2FormerImageProcessor''']

try:
   if not is_torch_available():
      raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
   pass
else:
   A				:					Dict    						=			[
       '''MASK2FORMER_PRETRAINED_MODEL_ARCHIVE_LIST''',
       '''Mask2FormerForUniversalSegmentation''',
       '''Mask2FormerModel''',
       '''Mask2FormerPreTrainedModel''',
   ]

if TYPE_CHECKING:
   from .configuration_maskaformer import MASK2FORMER_PRETRAINED_CONFIG_ARCHIVE_MAP, MaskaFormerConfig

   try:
      if not is_vision_available():
         raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
      pass
   else:
      from .image_processing_maskaformer import MaskaFormerImageProcessor

   try:
      if not is_torch_available():
         raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
      pass
   else:
      from .modeling_maskaformer import (
          MASK2FORMER_PRETRAINED_MODEL_ARCHIVE_LIST,
          MaskaFormerForUniversalSegmentation,
          MaskaFormerModel,
          MaskaFormerPreTrainedModel,
      )


else:
   import sys

   A				:					Optional[Any]    						=			_LazyModule(__name__, globals()['''__file__'''], _import_structure)






