class_docstr: Spliced Binned-Pareto univariate distribution.
  
  Arguments
  ----------
  bins_lower_bound: The lower bound of the bin edges
  bins_upper_bound: The upper bound of the bin edges
  nbins: The number of equidistance bins to allocate between `bins_lower_bound` and `bins_upper_bound`. Default value is 100.
  percentile_gen_pareto: The percentile of the distribution that is each tail. Default value is 0.05. NB: This symmetric percentile can still represent asymmetric upper and lower tails.
docstr: Arguments
  ----------
  xx: one datapoint
  for_training: boolean to indicate a return of the log-probability, or of the loss (which is an adjusted log-probability)
docstr_tok: ["Arguments","--","--","--","--","--","xx",":","one","datapoint","for_training",":","boolean","to","indicate","a","return","of","the","log-probability",",","or","of","the","loss","(","which","is","an","adjusted","log-probability",")"]
code: def log_p(self, xx, for_training=True):
      """
      Arguments
      ----------
      xx: one datapoint
      for_training: boolean to indicate a return of the log-probability, or of the loss (which is an adjusted log-probability)
      """
      assert xx.shape.numel() == 1, "log_p() expects univariate"
  
      # Compute upper and lower tail thresholds at current time from their percentiiles
      upper_percentile = self.icdf(1 - self.percentile_gen_pareto)
      lower_percentile = self.icdf(self.percentile_gen_pareto)
  
      # Log-prob given binned distribution
      logp_bins = self.log_binned_p(xx) + torch.log(
          1 - 2 * self.percentile_gen_pareto
      )
      logp = logp_bins
  
      # Log-prob given upper tail distribution
      if xx > upper_percentile:
          if self.upper_xi_batch is not None:
              # self.upper_gen_pareto.xi = torch.square(self.upper_xi_batch[self.idx])
              # self.upper_gen_pareto.beta = torch.square(self.upper_beta_batch[self.idx])
              self.upper_gen_pareto.xi = self.upper_xi_batch[self.idx]
              self.upper_gen_pareto.beta = self.upper_beta_batch[
                  self.idx
              ]
          logp_gen_pareto = self.upper_gen_pareto.log_prob(
              xx - upper_percentile
          ) + torch.log(self.percentile_gen_pareto)
          logp = logp_gen_pareto
          if for_training:
              logp += logp_bins
  
      # Log-prob given upper tail distribution
      elif xx < lower_percentile:
          if self.lower_xi_batch is not None:
              # self.lower_gen_pareto.xi = torch.square(self.lower_xi_batch[self.idx])
              # self.lower_gen_pareto.beta = torch.square(self.lower_beta_batch[self.idx])
              self.lower_gen_pareto.xi = self.lower_xi_batch[self.idx]
              self.lower_gen_pareto.beta = self.lower_beta_batch[
                  self.idx
              ]
          logp_gen_pareto = self.lower_gen_pareto.log_prob(
              lower_percentile - xx
          ) + torch.log(self.percentile_gen_pareto)
          logp = logp_gen_pareto
          if for_training:
              logp += logp_bins
  
      return logp
  
imports: from typing import Optional
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.optim
  from .genpareto import GenPareto
label_desc: Use image node_id 4 for calling the SplicedBinnedPareto obj's underlying member method code with example usage: obj.log_p(xx, for_training) and returns: logp