@@ -138,26 +138,48 @@ def pdf(self, x) -> np.ndarray | float:
138138 :param x: The value at which to evaluate the PDF.
139139 :return: The value of the PDF at ``x``.
140140 """
141- # handle the log transformation; see also:
142- # https://en.wikipedia.org/wiki/Probability_density_function#Scalar_to_scalar
143- chain_rule_factor = (
144- (1 / (x * np .log (self ._logbase ))) if self ._logbase else 1
145- )
146- return (
147- self ._pdf (self ._log (x ))
148- * chain_rule_factor
149- * self ._truncation_normalizer
141+ if self ._trunc is None :
142+ return self ._pdf_transformed_untruncated (x )
143+
144+ return np .where (
145+ (x >= self .trunc_low ) & (x <= self .trunc_high ),
146+ self ._pdf_transformed_untruncated (x ) * self ._truncation_normalizer ,
147+ 0 ,
150148 )
151149
152150 @abc .abstractmethod
153- def _pdf (self , x ) -> np .ndarray | float :
151+ def _pdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
154152 """Probability density function of the underlying distribution at x.
155153
156154 :param x: The value at which to evaluate the PDF.
157155 :return: The value of the PDF at ``x``.
158156 """
159157 ...
160158
159+ def _pdf_transformed_untruncated (self , x ) -> np .ndarray | float :
160+ """Probability density function of the transformed, but untruncated
161+ distribution at x.
162+
163+ :param x: The value at which to evaluate the PDF.
164+ :return: The value of the PDF at ``x``.
165+ """
166+ if self .logbase is False :
167+ return self ._pdf_untransformed_untruncated (x )
168+
169+ # handle the log transformation; see also:
170+ # https://en.wikipedia.org/wiki/Probability_density_function#Scalar_to_scalar
171+ chain_rule_factor = (
172+ (1 / (x * np .log (self ._logbase ))) if self ._logbase else 1
173+ )
174+
175+ with np .errstate (invalid = "ignore" ):
176+ return np .where (
177+ x > 0 ,
178+ self ._pdf_untransformed_untruncated (self ._log (x ))
179+ * chain_rule_factor ,
180+ 0 ,
181+ )
182+
161183 @property
162184 def logbase (self ) -> bool | float :
163185 """The base of the log transformation.
@@ -185,7 +207,13 @@ def _cdf_transformed_untruncated(self, x) -> np.ndarray | float:
185207 :param x: The value at which to evaluate the CDF.
186208 :return: The value of the CDF at ``x``.
187209 """
188- return self ._cdf_untransformed_untruncated (self ._log (x ))
210+ if not self .logbase :
211+ return self ._cdf_untransformed_untruncated (x )
212+
213+ with np .errstate (invalid = "ignore" ):
214+ return np .where (
215+ x < 0 , 0 , self ._cdf_untransformed_untruncated (self ._log (x ))
216+ )
189217
190218 def _cdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
191219 """Cumulative distribution function of the underlying
@@ -263,7 +291,7 @@ def __repr__(self):
263291 def _sample (self , shape = None ) -> np .ndarray | float :
264292 return np .random .normal (loc = self ._loc , scale = self ._scale , size = shape )
265293
266- def _pdf (self , x ) -> np .ndarray | float :
294+ def _pdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
267295 return norm .pdf (x , loc = self ._loc , scale = self ._scale )
268296
269297 def _cdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
@@ -314,7 +342,7 @@ def __repr__(self):
314342 def _sample (self , shape = None ) -> np .ndarray | float :
315343 return np .random .uniform (low = self ._low , high = self ._high , size = shape )
316344
317- def _pdf (self , x ) -> np .ndarray | float :
345+ def _pdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
318346 return uniform .pdf (x , loc = self ._low , scale = self ._high - self ._low )
319347
320348 def _cdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
@@ -360,7 +388,7 @@ def __repr__(self):
360388 def _sample (self , shape = None ) -> np .ndarray | float :
361389 return np .random .laplace (loc = self ._loc , scale = self ._scale , size = shape )
362390
363- def _pdf (self , x ) -> np .ndarray | float :
391+ def _pdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
364392 return laplace .pdf (x , loc = self ._loc , scale = self ._scale )
365393
366394 def _cdf_untransformed_untruncated (self , x ) -> np .ndarray | float :
0 commit comments