score:0

I'm not sure I understand your distinction between `A` and `B`. But since you have `f: A => B`, I assume they can somehow be converted into each other? Then looking at the code, my impression is that `A` is the main type, so why not convert all `B` type things into `A` instead of the other way around?

Then you can spare any conversions to `Double`, that seems not a good idea anyway.

``````/*
* 'f' is a "strictly increasing function" (derivative > 0).
* The sweep gives the value at which it gives 'goal' (within '+-bEps' margins).
*/
object NewtonianSweep {
def apply[A: Fractional, B: Fractional](
// f: A => B,
fDerivate: A => A,
goal: B,
bEps: B,
initialSeed: A,
aMin: A,
aMax: A
)(f: B => A) : A = {

assert( initialSeed >= aMin && initialSeed <= aMax )

// 'goal' is supposed to exist within the range (this also checks that
// the function is increasing - though doesn't (cannot) check "strict increasing",
// we'll just trust the caller.
//
val aGoal = f(goal)
val aEps  = f(bEps)

assert(aMin <= aGoal)
assert(aMax >= aGoal)

val aType = implicitly[Fractional[A]]

@tailrec
def sweep(_seed: A): A = {
val seed = _seed.max(aMin).min(aMax)   // keep 'seed' within range

seed                        // done (within margins)
} else {
val d = fDerivate(seed)      // slope at the particular position (dy/dx)
assert(d > aType.zero)
val prod = d * aDiff
sweep(seed + prod)
}
}

sweep(initialSeed)
}
}
``````