// Copyright 2023 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: GPL-3.0-or-later

package bench

import "log"

type funcParams struct {
	min float64
	max float64
}

const (
	// Neighbourhood is the number of neighbouring values that are to be
	// generated as part of e.g. Stochastic Hill Climbing algo.
	Neighbourhood = 10
	// MaxNeighbourVariancePercent covers an arbitrary task requirement: pick
	// neighbours from max n percent of search space.
	MaxNeighbourVariancePercent = 10
	// MaxFES is the maximum number of allowed function evaluations.
	MaxFES = 10000
)

var (
	// Dimensions to compute for (spatial complexity..?).
	Dimensions = []int{5, 10, 20}

	// DimensionsGA are used with Genetic Algorithms (such as DE, see algo/de).
	DimensionsGA = []int{10, 30}

	// SchwefelParams is a struct holding the min, max allowed value of inputs
	// passed to the Schwefel function.
	SchwefelParams = funcParams{min: -500.0, max: 500.0}
	// DeJong1Params is a struct holding the min, max allowed value of inputs
	// passed to the De Jong 1st function.
	DeJong1Params = funcParams{min: -5.0, max: 5.0}
	// DeJong2Params is a struct holding the min, max allowed value of inputs
	// passed to the De Jong 2nd function.
	DeJong2Params = funcParams{min: -5.0, max: 5.0}
	// RastriginParams is a struct holding the min, max allowed value of inputs
	// passed to the Rastrigin function.
	RastriginParams = funcParams{min: -5.12, max: 5.12}
)

// Min returns the non-exported "min" field of a funcParams struct.
func (f *funcParams) Min() float64 {
	return f.min
}

// Max returns the non-exported 'max' field of a funcParams struct.
func (f *funcParams) Max() float64 {
	return f.max
}

// NewfuncParams returns a pointer to a fresh instance of funcParams.
// nolint: revive
func NewfuncParams(min, max float64) *funcParams {
	return &funcParams{min: min, max: max}
}

// GetGAMaxFES calculates the value of MaxFES for Genetic Algorithms. This is
// an arbitrary specification where MaxFES is 5000xD.
func GetGAMaxFES(dim int) int {
	if dim <= 0 {
		log.Fatalln("dim has to be greater than 0, got:", dim)
	}

	return dim * 5000
}
