# Path: fedjax/core/dataclasses.py
# def dataclass(clz: type):
#   def replace(self, **updates):
#   def iterate_clz(x):
#   def clz_from_iterable(meta, data):
# 
# Path: fedjax/core/util.py
# def safe_div(a, b):
#   def __getattr__(self, _):
# def import_tf():
# class FakeTensorFlowModule:
# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py



import abc
import functools
import jax
import jax.numpy as jnp
from typing import Optional, Tuple
from fedjax.core import dataclasses
from fedjax.core import util
from fedjax.core.typing import BatchExample
from fedjax.core.typing import BatchPrediction
from fedjax.core.typing import SingleExample
from fedjax.core.typing import SinglePrediction
    """

  @abc.abstractmethod
  def merge(self, other: 'Stat') -> 'Stat':
    """Merges two Stat objects into a new Stat with merged statistics.

    Args:
      other: Another Stat object of the same type.

    Returns:
      A new Stat object of the same type with merged statistics.
    """

  @abc.abstractmethod
  def reduce(self, axis: Optional[int] = 0) -> 'Stat':
    """Reduces a higher rank statistic along a given ``axis``.

    See the class docstring for details.

    Args:
      axis: An integer axis index, or ``None``.

    Returns:
      A new Stat object of the same type.
    """

  def __str__(self) -> str:
    return f'{repr(self)} => {self.result()}'



# Path: fedjax/core/dataclasses.py
# def dataclass(clz: type):
#   def replace(self, **updates):
#   def iterate_clz(x):
#   def clz_from_iterable(meta, data):
# 
# Path: fedjax/core/util.py
# def safe_div(a, b):
#   def __getattr__(self, _):
# def import_tf():
# class FakeTensorFlowModule:
# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py

# 
# Path: fedjax/core/typing.py



# Path: fedjax/core/metrics.py
import abc
import functools
import jax
import jax.numpy as jnp
from typing import Optional, Tuple
from fedjax.core import dataclasses
from fedjax.core import util
from fedjax.core.typing import BatchExample
from fedjax.core.typing import BatchPrediction
from fedjax.core.typing import SingleExample
from fedjax.core.typing import SinglePrediction

    """

  @abc.abstractmethod
  def merge(self, other: 'Stat') -> 'Stat':
    """Merges two Stat objects into a new Stat with merged statistics.

    Args:
      other: Another Stat object of the same type.

    Returns:
      A new Stat object of the same type with merged statistics.
    """

  @abc.abstractmethod
  def reduce(self, axis: Optional[int] = 0) -> 'Stat':
    """Reduces a higher rank statistic along a given ``axis``.

    See the class docstring for details.

    Args:
      axis: An integer axis index, or ``None``.

    Returns:
      A new Stat object of the same type.
    """

  def __str__(self) -> str:
    return f'{repr(self)} => {self.result()}'



@dataclasses.dataclass