package datascience

// LorenzState representa el estado del atractor de Lorenz en 3D.
type LorenzState struct {
	X, Y, Z float64
}

// LorenzParams define los parámetros del atractor de Lorenz.
type LorenzParams struct {
	Sigma float64 // Rate of rotation (default 10)
	Rho   float64 // Size of attractor (default 28)
	Beta  float64 // Damping (default 8/3)
}

// DefaultLorenzParams retorna los parámetros clásicos del atractor de Lorenz.
func DefaultLorenzParams() LorenzParams {
	return LorenzParams{Sigma: 10.0, Rho: 28.0, Beta: 8.0 / 3.0}
}

// LorenzStep calcula un paso del atractor de Lorenz usando integración de Euler.
// dx/dt = sigma*(y-x), dy/dt = x*(rho-z)-y, dz/dt = x*y - beta*z
func LorenzStep(s LorenzState, dt float64, p LorenzParams) LorenzState {
	dx := p.Sigma * (s.Y - s.X)
	dy := s.X*(p.Rho-s.Z) - s.Y
	dz := s.X*s.Y - p.Beta*s.Z

	return LorenzState{
		X: s.X + dx*dt,
		Y: s.Y + dy*dt,
		Z: s.Z + dz*dt,
	}
}

// LorenzSeries genera N pasos del atractor y retorna la serie completa.
func LorenzSeries(initial LorenzState, dt float64, p LorenzParams, steps int) []LorenzState {
	series := make([]LorenzState, steps)
	state := initial
	for i := 0; i < steps; i++ {
		state = LorenzStep(state, dt, p)
		series[i] = state
	}
	return series
}
