



# DISCLAIMER: This file is strongly influenced by https://github.com/ermongroup/ddim

from dataclasses import dataclass
from typing import Optional, Tuple, Union

import flax
import jax
import jax.numpy as jnp

from ..configuration_utils import ConfigMixin, register_to_config
from .scheduling_utils_flax import (
    CommonSchedulerState,
    FlaxKarrasDiffusionSchedulers,
    FlaxSchedulerMixin,
    FlaxSchedulerOutput,
    add_noise_common,
    get_velocity_common,
)

@flax.struct.dataclass
class 	lowerCamelCase_    :






						'''simple docstring'''
						a__   =  42

						# setable values
						a__   =  42
						a__   =  42
						a__   =  None







						@classmethod
						def 			SCREAMING_SNAKE_CASE__		(	cls      :			Optional[int]	,	__lowerCamelCase      :			CommonSchedulerState	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			jnp.ndarray )      ->				Optional[int]:
									return cls(common=__lowerCamelCase	,	init_noise_sigma=__lowerCamelCase	,	timesteps=__lowerCamelCase )







@dataclass
class 	lowerCamelCase_    ( _A						):






						'''simple docstring'''
						a__   =  42







class 	lowerCamelCase_    ( _A						,_A						):






						'''simple docstring'''
						a__   =  [e.name for e in FlaxKarrasDiffusionSchedulers]

						a__   =  42







						@property
						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[Any] )      ->				str:
									return True







						@register_to_config
						def __init__(	self      :			Tuple	,	__lowerCamelCase      :			int = 10_00	,	__lowerCamelCase      :			float = 0.0001	,	__lowerCamelCase      :			float = 0.02	,	__lowerCamelCase      :			str = "linear"	,	__lowerCamelCase      :			Optional[jnp.ndarray] = None	,	__lowerCamelCase      :			str = "fixed_small"	,	__lowerCamelCase      :			bool = True	,	__lowerCamelCase      :			str = "epsilon"	,	__lowerCamelCase      :			jnp.dtype = jnp.floataa	,	)      ->				List[str]:
									A							:					str              =						dtype







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Tuple	,	__lowerCamelCase      :			Optional[CommonSchedulerState] = None )      ->				DDPMSchedulerState:
									if common is None:
												A							:					int              =						CommonSchedulerState.create(self )

									# standard deviation of the initial noise distribution
									A							:					Tuple              =						jnp.array(1.0	,	dtype=self.dtype )

									A							:					Union[str, Any]              =						jnp.arange(0	,	self.config.num_train_timesteps ).round()[::-1]

									return DDPMSchedulerState.create(
									    common=__lowerCamelCase	,	init_noise_sigma=__lowerCamelCase	,	timesteps=__lowerCamelCase	,	)







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Tuple	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			Optional[int] = None )      ->				jnp.ndarray:
									return sample







						def 			SCREAMING_SNAKE_CASE__		(	self      :			str	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			int	,	__lowerCamelCase      :			Tuple = () )      ->				DDPMSchedulerState:
									A							:					List[str]              =						self.config.num_train_timesteps // num_inference_steps
									# creates integer timesteps by multiplying by ratio
									# rounding to avoid issues when num_inference_step is power of 3
									A							:					int              =						(jnp.arange(0	,	__lowerCamelCase ) * step_ratio).round()[::-1]

									return state.replace(
									    num_inference_steps=__lowerCamelCase	,	timesteps=__lowerCamelCase	,	)







						def 			SCREAMING_SNAKE_CASE__		(	self      :			int	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			Any	,	__lowerCamelCase      :			List[str]=None	,	__lowerCamelCase      :			int=None )      ->				Any:
									A							:					str              =						state.common.alphas_cumprod[t]
									A							:					Union[str, Any]              =						jnp.where(t > 0	,	state.common.alphas_cumprod[t - 1]	,	jnp.array(1.0	,	dtype=self.dtype ) )

									# For t > 0, compute predicted variance βt (see formula (6) and (7) from https://arxiv.org/pdf/2006.11239.pdf)
									# and sample from it to get previous sample
									# x_{t-1} ~ N(pred_prev_sample, variance) == add variance to pred_sample
									A							:					str              =						(1 - alpha_prod_t_prev) / (1 - alpha_prod_t) * state.common.betas[t]

									if variance_type is None:
												A							:					Tuple              =						self.config.variance_type

									# hacks - were probably added for training stability
									if variance_type == "fixed_small":
												A							:					str              =						jnp.clip(__lowerCamelCase	,	a_min=1e-20 )
									# for rl-diffuser https://arxiv.org/abs/2205.09991
									elif variance_type == "fixed_small_log":
												A							:					str              =						jnp.log(jnp.clip(__lowerCamelCase	,	a_min=1e-20 ) )
									elif variance_type == "fixed_large":
												A							:					Union[str, Any]              =						state.common.betas[t]
									elif variance_type == "fixed_large_log":
												# Glide max_log
												A							:					str              =						jnp.log(state.common.betas[t] )
									elif variance_type == "learned":
												return predicted_variance
									elif variance_type == "learned_range":
												A							:					Optional[Any]              =						variance
												A							:					str              =						state.common.betas[t]
												A							:					Optional[int]              =						(predicted_variance + 1) / 2
												A							:					int              =						frac * max_log + (1 - frac) * min_log

									return variance







						def 			SCREAMING_SNAKE_CASE__		(	self      :			int	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			int	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			Optional[jax.random.KeyArray] = None	,	__lowerCamelCase      :			bool = True	,	)      ->				Union[FlaxDDPMSchedulerOutput, Tuple]:
									A							:					Union[str, Any]              =						timestep

									if key is None:
												A							:					Any              =						jax.random.PRNGKey(0 )

									if model_output.shape[1] == sample.shape[1] * 2 and self.config.variance_type in ["learned", "learned_range"]:
												A       , A							:					Any              =						jnp.split(__lowerCamelCase	,	sample.shape[1]	,	axis=1 )
									else:
												A							:					Tuple              =						None

									# 1. compute alphas, betas
									A							:					Dict              =						state.common.alphas_cumprod[t]
									A							:					Tuple              =						jnp.where(t > 0	,	state.common.alphas_cumprod[t - 1]	,	jnp.array(1.0	,	dtype=self.dtype ) )
									A							:					Any              =						1 - alpha_prod_t
									A							:					str              =						1 - alpha_prod_t_prev

									# 2. compute predicted original sample from predicted noise also called
									# "predicted x_0" of formula (15) from https://arxiv.org/pdf/2006.11239.pdf
									if self.config.prediction_type == "epsilon":
												A							:					Optional[int]              =						(sample - beta_prod_t ** 0.5 * model_output) / alpha_prod_t ** 0.5
									elif self.config.prediction_type == "sample":
												A							:					Union[str, Any]              =						model_output
									elif self.config.prediction_type == "v_prediction":
												A							:					Dict              =						(alpha_prod_t**0.5) * sample - (beta_prod_t**0.5) * model_output
									else:
												raise ValueError(
												    F"""prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample` """
												    " for the FlaxDDPMScheduler." )

									# 3. Clip "predicted x_0"
									if self.config.clip_sample:
												A							:					Dict              =						jnp.clip(__lowerCamelCase	,	-1	,	1 )

									# 4. Compute coefficients for pred_original_sample x_0 and current sample x_t
									# See formula (7) from https://arxiv.org/pdf/2006.11239.pdf
									A							:					Optional[int]              =						(alpha_prod_t_prev ** 0.5 * state.common.betas[t]) / beta_prod_t
									A							:					Dict              =						state.common.alphas[t] ** 0.5 * beta_prod_t_prev / beta_prod_t

									# 5. Compute predicted previous sample µ_t
									# See formula (7) from https://arxiv.org/pdf/2006.11239.pdf
									A							:					List[str]              =						pred_original_sample_coeff * pred_original_sample + current_sample_coeff * sample

									# 6. Add noise
									def random_variance():
												A							:					str              =						jax.random.split(__lowerCamelCase	,	num=1 )
												A							:					Any              =						jax.random.normal(__lowerCamelCase	,	shape=model_output.shape	,	dtype=self.dtype )
												return (self._get_variance(__lowerCamelCase	,	__lowerCamelCase	,	predicted_variance=__lowerCamelCase ) ** 0.5) * noise

									A							:					List[Any]              =						jnp.where(t > 0	,	random_variance()	,	jnp.zeros(model_output.shape	,	dtype=self.dtype ) )

									A							:					List[Any]              =						pred_prev_sample + variance

									if not return_dict:
												return (pred_prev_sample, state)

									return FlaxDDPMSchedulerOutput(prev_sample=__lowerCamelCase	,	state=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Dict	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			jnp.ndarray	,	)      ->				jnp.ndarray:
									return add_noise_common(state.common	,	__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[str]	,	__lowerCamelCase      :			DDPMSchedulerState	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			jnp.ndarray	,	__lowerCamelCase      :			jnp.ndarray	,	)      ->				jnp.ndarray:
									return get_velocity_common(state.common	,	__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase )







						def __len__(	self      :			str )      ->				str:
									return self.config.num_train_timesteps




import tempfile

import torch

from diffusers import PNDMScheduler

from .test_schedulers import SchedulerCommonTest

class 	lowerCamelCase_    ( _A						):






						'''simple docstring'''
						a__   =  (PNDMScheduler,)
						a__   =  (("num_inference_steps", 50),)







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Union[str, Any]	,	**__lowerCamelCase      :			str )      ->				Optional[Any]:
									A							:					Union[str, Any]              =						{
									    "num_train_timesteps": 10_00,
									    "beta_start": 0.0001,
									    "beta_end": 0.02,
									    "beta_schedule": "linear",
									}

									config.update(**__lowerCamelCase )
									return config







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Union[str, Any]	,	__lowerCamelCase      :			List[str]=0	,	**__lowerCamelCase      :			Any )      ->				Tuple:
									A							:					Dict              =						dict(self.forward_default_kwargs )
									A							:					Dict              =						kwargs.pop("num_inference_steps"	,	__lowerCamelCase )
									A							:					Union[str, Any]              =						self.dummy_sample
									A							:					List[Any]              =						0.1 * sample
									A							:					List[Any]              =						[residual + 0.2, residual + 0.15, residual + 0.1, residual + 0.05]

									for scheduler_class in self.scheduler_classes:
												A							:					Any              =						self.get_scheduler_config(**__lowerCamelCase )
												A							:					int              =						scheduler_class(**__lowerCamelCase )
												scheduler.set_timesteps(__lowerCamelCase )
												# copy over dummy past residuals
												A							:					Tuple              =						dummy_past_residuals[:]

												with tempfile.TemporaryDirectory() as tmpdirname:
															scheduler.save_config(__lowerCamelCase )
															A							:					Dict              =						scheduler_class.from_pretrained(__lowerCamelCase )
															new_scheduler.set_timesteps(__lowerCamelCase )
															# copy over dummy past residuals
															A							:					Tuple              =						dummy_past_residuals[:]

												A							:					Dict              =						scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					str              =						new_scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												assert torch.sum(torch.abs(output - new_output ) ) < 1e-5, "Scheduler outputs are not identical"

												A							:					int              =						scheduler.step_plms(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					List[str]              =						new_scheduler.step_plms(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												assert torch.sum(torch.abs(output - new_output ) ) < 1e-5, "Scheduler outputs are not identical"







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[Any] )      ->				Union[str, Any]:
									pass







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[str]	,	__lowerCamelCase      :			Optional[Any]=0	,	**__lowerCamelCase      :			Tuple )      ->				str:
									A							:					List[str]              =						dict(self.forward_default_kwargs )
									A							:					Optional[int]              =						kwargs.pop("num_inference_steps"	,	__lowerCamelCase )
									A							:					List[str]              =						self.dummy_sample
									A							:					Any              =						0.1 * sample
									A							:					Any              =						[residual + 0.2, residual + 0.15, residual + 0.1, residual + 0.05]

									for scheduler_class in self.scheduler_classes:
												A							:					Tuple              =						self.get_scheduler_config()
												A							:					Optional[int]              =						scheduler_class(**__lowerCamelCase )
												scheduler.set_timesteps(__lowerCamelCase )

												# copy over dummy past residuals (must be after setting timesteps)
												A							:					Optional[int]              =						dummy_past_residuals[:]

												with tempfile.TemporaryDirectory() as tmpdirname:
															scheduler.save_config(__lowerCamelCase )
															A							:					str              =						scheduler_class.from_pretrained(__lowerCamelCase )
															# copy over dummy past residuals
															new_scheduler.set_timesteps(__lowerCamelCase )

															# copy over dummy past residual (must be after setting timesteps)
															A							:					Optional[Any]              =						dummy_past_residuals[:]

												A							:					Union[str, Any]              =						scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					Dict              =						new_scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												assert torch.sum(torch.abs(output - new_output ) ) < 1e-5, "Scheduler outputs are not identical"

												A							:					Union[str, Any]              =						scheduler.step_plms(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					List[Any]              =						new_scheduler.step_plms(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												assert torch.sum(torch.abs(output - new_output ) ) < 1e-5, "Scheduler outputs are not identical"







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Tuple	,	**__lowerCamelCase      :			Any )      ->				Union[str, Any]:
									A							:					Optional[Any]              =						self.scheduler_classes[0]
									A							:					List[Any]              =						self.get_scheduler_config(**__lowerCamelCase )
									A							:					str              =						scheduler_class(**__lowerCamelCase )

									A							:					List[str]              =						10
									A							:					Union[str, Any]              =						self.dummy_model()
									A							:					int              =						self.dummy_sample_deter
									scheduler.set_timesteps(__lowerCamelCase )

									for i, t in enumerate(scheduler.prk_timesteps ):
												A							:					Optional[int]              =						model(__lowerCamelCase	,	__lowerCamelCase )
												A							:					Optional[int]              =						scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase ).prev_sample

									for i, t in enumerate(scheduler.plms_timesteps ):
												A							:					Tuple              =						model(__lowerCamelCase	,	__lowerCamelCase )
												A							:					Tuple              =						scheduler.step_plms(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase ).prev_sample

									return sample







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Optional[Any] )      ->				Any:
									A							:					Union[str, Any]              =						dict(self.forward_default_kwargs )

									A							:					Union[str, Any]              =						kwargs.pop("num_inference_steps"	,	__lowerCamelCase )

									for scheduler_class in self.scheduler_classes:
												A							:					Dict              =						self.get_scheduler_config()
												A							:					List[str]              =						scheduler_class(**__lowerCamelCase )

												A							:					List[Any]              =						self.dummy_sample
												A							:					List[Any]              =						0.1 * sample

												if num_inference_steps is not None and hasattr(__lowerCamelCase	,	"set_timesteps" ):
															scheduler.set_timesteps(__lowerCamelCase )
												elif num_inference_steps is not None and not hasattr(__lowerCamelCase	,	"set_timesteps" ):
															A							:					List[str]              =						num_inference_steps

												# copy over dummy past residuals (must be done after set_timesteps)
												A							:					List[Any]              =						[residual + 0.2, residual + 0.15, residual + 0.1, residual + 0.05]
												A							:					Tuple              =						dummy_past_residuals[:]

												A							:					Dict              =						scheduler.step_prk(__lowerCamelCase	,	0	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					List[Any]              =						scheduler.step_prk(__lowerCamelCase	,	1	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												self.assertEqual(output_a.shape	,	sample.shape )
												self.assertEqual(output_a.shape	,	output_a.shape )

												A							:					Any              =						scheduler.step_plms(__lowerCamelCase	,	0	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample
												A							:					str              =						scheduler.step_plms(__lowerCamelCase	,	1	,	__lowerCamelCase	,	**__lowerCamelCase ).prev_sample

												self.assertEqual(output_a.shape	,	sample.shape )
												self.assertEqual(output_a.shape	,	output_a.shape )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			str )      ->				Tuple:
									for timesteps in [1_00, 10_00]:
												self.check_over_configs(num_train_timesteps=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Tuple )      ->				List[str]:
									for steps_offset in [0, 1]:
												self.check_over_configs(steps_offset=__lowerCamelCase )

									A							:					Dict              =						self.scheduler_classes[0]
									A							:					Union[str, Any]              =						self.get_scheduler_config(steps_offset=1 )
									A							:					Optional[int]              =						scheduler_class(**__lowerCamelCase )
									scheduler.set_timesteps(10 )
									assert torch.equal(
									    scheduler.timesteps	,	torch.LongTensor(
									        [9_01, 8_51, 8_51, 8_01, 8_01, 7_51, 7_51, 7_01, 7_01, 6_51, 6_51, 6_01, 6_01, 5_01, 4_01, 3_01, 2_01, 1_01, 1] )	,	)







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Union[str, Any] )      ->				Dict:
									for beta_start, beta_end in zip([0.0001, 0.001]	,	[0.002, 0.02] ):
												self.check_over_configs(beta_start=__lowerCamelCase	,	beta_end=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Optional[int] )      ->				Union[str, Any]:
									for schedule in ["linear", "squaredcos_cap_v2"]:
												self.check_over_configs(beta_schedule=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Any )      ->				str:
									for prediction_type in ["epsilon", "v_prediction"]:
												self.check_over_configs(prediction_type=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[str] )      ->				List[Any]:
									for t in [1, 5, 10]:
												self.check_over_forward(time_step=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Tuple )      ->				int:
									for t, num_inference_steps in zip([1, 5, 10]	,	[10, 50, 1_00] ):
												self.check_over_forward(num_inference_steps=__lowerCamelCase )







						def 			SCREAMING_SNAKE_CASE__		(	self      :			Optional[int] )      ->				Any:
									# earlier version of set_timesteps() caused an error indexing alpha's with inference steps as power of 3
									A							:					str              =						27

									for scheduler_class in self.scheduler_classes:
												A							:					Tuple              =						self.dummy_sample
												A							:					List[Any]              =						0.1 * sample

												A							:					List[Any]              =						self.get_scheduler_config()
												A							:					List[str]              =						scheduler_class(**__lowerCamelCase )

												scheduler.set_timesteps(__lowerCamelCase )

												# before power of 3 fix, would error on first step, so we only need to do two
												for i, t in enumerate(scheduler.prk_timesteps[:2] ):
															A							:					Dict              =						scheduler.step_prk(__lowerCamelCase	,	__lowerCamelCase	,	__lowerCamelCase ).prev_sample







						def 			SCREAMING_SNAKE_CASE__		(	self      :			str )      ->				int:
									with self.assertRaises(__lowerCamelCase ):
												A							:					Union[str, Any]              =						self.scheduler_classes[0]
												A							:					Union[str, Any]              =						self.get_scheduler_config()
												A							:					List[str]              =						scheduler_class(**__lowerCamelCase )

												scheduler.step_plms(self.dummy_sample	,	1	,	self.dummy_sample ).prev_sample







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[str] )      ->				Dict:
									A							:					Optional[Any]              =						self.full_loop()
									A							:					Tuple              =						torch.sum(torch.abs(__lowerCamelCase ) )
									A							:					Optional[int]              =						torch.mean(torch.abs(__lowerCamelCase ) )

									assert abs(result_sum.item() - 198.1318 ) < 1e-2
									assert abs(result_mean.item() - 0.2580 ) < 1e-3







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[str] )      ->				Any:
									A							:					Any              =						self.full_loop(prediction_type="v_prediction" )
									A							:					Union[str, Any]              =						torch.sum(torch.abs(__lowerCamelCase ) )
									A							:					List[str]              =						torch.mean(torch.abs(__lowerCamelCase ) )

									assert abs(result_sum.item() - 67.3986 ) < 1e-2
									assert abs(result_mean.item() - 0.0878 ) < 1e-3







						def 			SCREAMING_SNAKE_CASE__		(	self      :			List[Any] )      ->				List[str]:
									# We specify different beta, so that the first alpha is 0.99
									A							:					Any              =						self.full_loop(set_alpha_to_one=__lowerCamelCase	,	beta_start=0.01 )
									A							:					Dict              =						torch.sum(torch.abs(__lowerCamelCase ) )
									A							:					Any              =						torch.mean(torch.abs(__lowerCamelCase ) )

									assert abs(result_sum.item() - 230.0399 ) < 1e-2
									assert abs(result_mean.item() - 0.2995 ) < 1e-3







						def 			SCREAMING_SNAKE_CASE__		(	self      :			int )      ->				Any:
									# We specify different beta, so that the first alpha is 0.99
									A							:					Any              =						self.full_loop(set_alpha_to_one=__lowerCamelCase	,	beta_start=0.01 )
									A							:					List[Any]              =						torch.sum(torch.abs(__lowerCamelCase ) )
									A							:					Optional[Any]              =						torch.mean(torch.abs(__lowerCamelCase ) )

									assert abs(result_sum.item() - 186.9482 ) < 1e-2
									assert abs(result_mean.item() - 0.2434 ) < 1e-3