





import importlib.metadata
import warnings
from copy import deepcopy

from packaging import version

from ..utils import logging
from .import_utils import is_accelerate_available, is_bitsandbytes_available


if is_bitsandbytes_available():
 import bitsandbytes as bnb
 import torch
 import torch.nn as nn

 from ..pytorch_utils import ConvaD

if is_accelerate_available():
 from accelerate import init_empty_weights
 from accelerate.utils import find_tied_parameters

__A							:			List[Any]         =			logging.get_logger(__name__)





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=None				)							-> Dict:




    """simple docstring"""




    if "." in tensor_name:
        _A     =							tensor_name.split('.'				)
        for split in splits[:-1]:
            _A     =							getattr(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)
            if new_module is None:
                raise ValueError(F"{module} has no attribute {split}."				)
            _A     =							new_module
        _A     =							splits[-1]

    if tensor_name not in module._parameters and tensor_name not in module._buffers:
        raise ValueError(F"{module} does not have a parameter or a buffer named {tensor_name}."				)
    _A     =							tensor_name in module._buffers
    _A     =							getattr(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)

    if old_value.device == torch.device('meta'				) and device not in ["meta", torch.device('meta'				)] and value is None:
        raise ValueError(F"{tensor_name} is on the meta device, we need a `value` to put in on {device}."				)

    _A     =							False
    _A     =							False
    if is_buffer or not is_bitsandbytes_available():
        _A     =							False
        _A     =							False
    else:
        _A     =							hasattr(bnb.nn							,     'Params4bit'				) and isinstance(module._parameters[tensor_name]							,     bnb.nn.Paramsabit				)
        _A     =							isinstance(module._parameters[tensor_name]							,     bnb.nn.IntaParams				)

    if is_abit or is_abit:
        _A     =							module._parameters[tensor_name]
        if param.device.type != "cuda":
            if value is None:
                _A     =							old_value.to(_SCREAMING_SNAKE_CASE				)
            elif isinstance(_SCREAMING_SNAKE_CASE							,     torch.Tensor				):
                _A     =							value.to('cpu'				)
                if value.dtype == torch.inta:
                    _A     =							version.parse(importlib.metadata.version('bitsandbytes'				)				) > version.parse(
                        '0.37.2'				)
                    if not is_abit_serializable:
                        raise ValueError(
                            'Detected int8 weights but the version of bitsandbytes is not compatible with int8 serialization. '
                            'Make sure to download the latest `bitsandbytes` version. `pip install --upgrade bitsandbytes`.'				)
            else:
                _A     =							torch.tensor(_SCREAMING_SNAKE_CASE							,     device='cpu'				)

            # Support models using `Conv1D` in place of `nn.Linear` (e.g. gpt2) by transposing the weight matrix prior to quantization.
            # Since weights are saved in the correct "orientation", we skip transposing when loading.
            if issubclass(module.source_cls							,     _SCREAMING_SNAKE_CASE				) and fpaa_statistics is None:
                _A     =							new_value.T

            _A     =							old_value.__dict__
            if is_abit:
                _A     =							bnb.nn.IntaParams(_SCREAMING_SNAKE_CASE							,     requires_grad=_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				).to(_SCREAMING_SNAKE_CASE				)
            elif is_abit:
                _A     =							bnb.nn.Paramsabit(_SCREAMING_SNAKE_CASE							,     requires_grad=_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				).to(_SCREAMING_SNAKE_CASE				)

            _A     =							new_value
            if fpaa_statistics is not None:
                setattr(module.weight							,     'SCB'							,     fpaa_statistics.to(_SCREAMING_SNAKE_CASE				)				)

    else:
        if value is None:
            _A     =							old_value.to(_SCREAMING_SNAKE_CASE				)
        elif isinstance(_SCREAMING_SNAKE_CASE							,     torch.Tensor				):
            _A     =							value.to(_SCREAMING_SNAKE_CASE				)
        else:
            _A     =							torch.tensor(_SCREAMING_SNAKE_CASE							,     device=_SCREAMING_SNAKE_CASE				)

        if is_buffer:
            _A     =							new_value
        else:
            _A     =							nn.Parameter(_SCREAMING_SNAKE_CASE							,     requires_grad=old_value.requires_grad				)
            _A     =							new_value





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=False				)							-> Dict:




    """simple docstring"""




    for name, module in model.named_children():
        if current_key_name is None:
            _A     =							[]
        current_key_name.append(_SCREAMING_SNAKE_CASE				)

        if (isinstance(_SCREAMING_SNAKE_CASE							,     nn.Linear				) or isinstance(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)) and name not in modules_to_not_convert:
            # Check if the current key is not in the `modules_to_not_convert`
            if not any(key in '.'.join(_SCREAMING_SNAKE_CASE				) for key in modules_to_not_convert				):
                with init_empty_weights():
                    if isinstance(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				):
                        _A,			_A     =							module.weight.shape
                    else:
                        _A     =							module.in_features
                        _A     =							module.out_features

                    if quantization_config.quantization_method() == "llm_int8":
                        _A     =							bnb.nn.LinearabitLt(
                            _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     module.bias is not None							,     has_fpaa_weights=quantization_config.llm_inta_has_fpaa_weight							,     threshold=quantization_config.llm_inta_threshold							,     )
                        _A     =							True
                    else:
                        if (
                            quantization_config.llm_inta_skip_modules is not None
                            and name in quantization_config.llm_inta_skip_modules
                        ):
                            pass
                        else:
                            _A     =							bnb.nn.Linearabit(
                                _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     module.bias is not None							,     quantization_config.bnb_abit_compute_dtype							,     compress_statistics=quantization_config.bnb_abit_use_double_quant							,     quant_type=quantization_config.bnb_abit_quant_type							,     )
                            _A     =							True
                    # Store the module class in case we need to transpose the weight later
                    _A     =							type(_SCREAMING_SNAKE_CASE				)
                    # Force requires grad to False to avoid unexpected errors
                    model._modules[name].requires_grad_(_SCREAMING_SNAKE_CASE				)
        if len(list(module.children()				)				) > 0:
            _A,			_A     =							_replace_with_bnb_linear(
                _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     has_been_replaced=_SCREAMING_SNAKE_CASE							,     )
        # Remove the last key for recursion
        current_key_name.pop(-1				)
    return model, has_been_replaced





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=None							,     _SCREAMING_SNAKE_CASE=None				)							-> Tuple:




    """simple docstring"""




    _A     =							['lm_head'] if modules_to_not_convert is None else modules_to_not_convert
    _A,			_A     =							_replace_with_bnb_linear(
        _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)

    if not has_been_replaced:
        logger.warning(
            'You are loading your model in 8bit or 4bit but no linear modules were found in your model.'
            ' Please double check your model architecture, or submit an issue on github if you think this is'
            ' a bug.'				)

    return model





def 				__lowerCAmelCase(       *_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				)							-> Tuple:




    """simple docstring"""




    warnings.warn(
        '`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead'							,     _SCREAMING_SNAKE_CASE							,     )
    return replace_with_bnb_linear(*_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				)





def 				__lowerCAmelCase(       *_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				)							-> Optional[Any]:




    """simple docstring"""




    warnings.warn(
        '`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead'							,     _SCREAMING_SNAKE_CASE							,     )
    return set_module_quantized_tensor_to_device(*_SCREAMING_SNAKE_CASE							,     **_SCREAMING_SNAKE_CASE				)





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> Optional[int]:




    """simple docstring"""




    _A     =							deepcopy(_SCREAMING_SNAKE_CASE				)  # this has 0 cost since it is done inside `init_empty_weights` context manager`
    tied_model.tie_weights()

    _A     =							find_tied_parameters(_SCREAMING_SNAKE_CASE				)
    # For compatibility with Accelerate < 0.18
    if isinstance(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				):
        _A     =							sum(list(tied_params.values()				)							,     []				) + list(tied_params.keys()				)
    else:
        _A     =							sum(_SCREAMING_SNAKE_CASE							,     []				)
    _A     =							len(_SCREAMING_SNAKE_CASE				) > 0

    # Check if it is a base model
    _A     =							not hasattr(_SCREAMING_SNAKE_CASE							,     model.base_model_prefix				)

    # Ignore this for base models (BertModel, GPT2Model, etc.)
    if (not has_tied_params) and is_base_model:
        return []

    # otherwise they have an attached head
    _A     =							list(model.named_children()				)
    _A     =							[list_modules[-1][0]]

    # add last module together with tied weights
    _A     =							set(_SCREAMING_SNAKE_CASE				) - set(_SCREAMING_SNAKE_CASE				)
    _A     =							list(set(_SCREAMING_SNAKE_CASE				)				) + list(_SCREAMING_SNAKE_CASE				)

    # remove ".weight" from the keys
    _A     =							['.weight', '.bias']
    _A     =							[]
    for name in list_untouched:
        for name_to_remove in names_to_remove:
            if name_to_remove in name:
                _A     =							name.replace(_SCREAMING_SNAKE_CASE							,     ''				)
        filtered_module_names.append(_SCREAMING_SNAKE_CASE				)

    return filtered_module_names












from math import pi, sqrt, tan





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if side_length < 0:
        raise ValueError('surface_area_cube() only accepts non-negative values'				)
    return 6 * side_length**2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if length < 0 or breadth < 0 or height < 0:
        raise ValueError('surface_area_cuboid() only accepts non-negative values'				)
    return 2 * ((length * breadth) + (breadth * height) + (length * height))





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius < 0:
        raise ValueError('surface_area_sphere() only accepts non-negative values'				)
    return 4 * pi * radius**2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius < 0:
        raise ValueError('surface_area_hemisphere() only accepts non-negative values'				)
    return 3 * pi * radius**2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius < 0 or height < 0:
        raise ValueError('surface_area_cone() only accepts non-negative values'				)
    return pi * radius * (radius + (height**2 + radius**2) ** 0.5)





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius_a < 0 or radius_a < 0 or height < 0:
        raise ValueError(
            'surface_area_conical_frustum() only accepts non-negative values'				)
    _A     =							(height**2 + (radius_a - radius_a) ** 2) ** 0.5
    return pi * ((slant_height * (radius_a + radius_a)) + radius_a**2 + radius_a**2)





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius < 0 or height < 0:
        raise ValueError('surface_area_cylinder() only accepts non-negative values'				)
    return 2 * pi * radius * (height + radius)





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if torus_radius < 0 or tube_radius < 0:
        raise ValueError('surface_area_torus() only accepts non-negative values'				)
    if torus_radius < tube_radius:
        raise ValueError(
            'surface_area_torus() does not support spindle or self intersecting tori'				)
    return 4 * pow(_SCREAMING_SNAKE_CASE							,     2				) * torus_radius * tube_radius





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if length < 0 or width < 0:
        raise ValueError('area_rectangle() only accepts non-negative values'				)
    return length * width





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if side_length < 0:
        raise ValueError('area_square() only accepts non-negative values'				)
    return side_length**2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if base < 0 or height < 0:
        raise ValueError('area_triangle() only accepts non-negative values'				)
    return (base * height) / 2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if sidea < 0 or sidea < 0 or sidea < 0:
        raise ValueError('area_triangle_three_sides() only accepts non-negative values'				)
    elif sidea + sidea < sidea or sidea + sidea < sidea or sidea + sidea < sidea:
        raise ValueError('Given three sides do not form a triangle'				)
    _A     =							(sidea + sidea + sidea) / 2
    _A     =							sqrt(
        semi_perimeter
        * (semi_perimeter - sidea)
        * (semi_perimeter - sidea)
        * (semi_perimeter - sidea)				)
    return area





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if base < 0 or height < 0:
        raise ValueError('area_parallelogram() only accepts non-negative values'				)
    return base * height





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if basea < 0 or basea < 0 or height < 0:
        raise ValueError('area_trapezium() only accepts non-negative values'				)
    return 1 / 2 * (basea + basea) * height





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius < 0:
        raise ValueError('area_circle() only accepts non-negative values'				)
    return pi * radius**2





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if radius_x < 0 or radius_y < 0:
        raise ValueError('area_ellipse() only accepts non-negative values'				)
    return pi * radius_x * radius_y





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if diagonal_a < 0 or diagonal_a < 0:
        raise ValueError('area_rhombus() only accepts non-negative values'				)
    return 1 / 2 * diagonal_a * diagonal_a





def 				__lowerCAmelCase(       _SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				)							-> float:




    """simple docstring"""




    if not isinstance(_SCREAMING_SNAKE_CASE							,     _SCREAMING_SNAKE_CASE				) or sides < 3:
        raise ValueError(
            'area_reg_polygon() only accepts integers greater than or \
equal to three as number of sides'				)
    elif length < 0:
        raise ValueError(
            'area_reg_polygon() only accepts non-negative values as \
length of a side'				)
    return (sides * length**2) / (4 * tan(pi / sides				))
    return (sides * length**2) / (4 * tan(pi / sides				))


if __name__ == "__main__":
 import doctest

 doctest.testmod(verbose=True)  # verbose so we can see methods missing tests

 print("[DEMO] Areas of various geometric shapes: \n")
 print(f"Rectangle: {area_rectangle(10, 20) = }")
 print(f"Square: {area_square(10) = }")
 print(f"Triangle: {area_triangle(10, 10) = }")
 print(f"Triangle: {area_triangle_three_sides(5, 12, 13) = }")
 print(f"Parallelogram: {area_parallelogram(10, 20) = }")
 print(f"Rhombus: {area_rhombus(10, 20) = }")
 print(f"Trapezium: {area_trapezium(10, 20, 30) = }")
 print(f"Circle: {area_circle(20) = }")
 print(f"Ellipse: {area_ellipse(10, 20) = }")
 print("\nSurface Areas of various geometric shapes: \n")
 print(f"Cube: {surface_area_cube(20) = }")
 print(f"Cuboid: {surface_area_cuboid(10, 20, 30) = }")
 print(f"Sphere: {surface_area_sphere(20) = }")
 print(f"Hemisphere: {surface_area_hemisphere(20) = }")
 print(f"Cone: {surface_area_cone(10, 20) = }")
 print(f"Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }")
 print(f"Cylinder: {surface_area_cylinder(10, 20) = }")
 print(f"Torus: {surface_area_torus(20, 10) = }")
 print(f"Equilateral Triangle: {area_reg_polygon(3, 10) = }")
 print(f"Square: {area_reg_polygon(4, 10) = }")
 print(f"Reqular Pentagon: {area_reg_polygon(5, 10) = }")





