2022-03-28 12:39:07 +00:00
|
|
|
type operation = GenericDist_Types.Operation.genericFunctionCall
|
2022-03-27 20:59:46 +00:00
|
|
|
type genericDist = GenericDist_Types.genericDist
|
|
|
|
type error = GenericDist_Types.error
|
|
|
|
|
|
|
|
// TODO: It could be great to use a cache for some calculations (basically, do memoization). Also, better analytics/tracking could go a long way.
|
2022-03-27 18:22:26 +00:00
|
|
|
|
|
|
|
type params = {
|
|
|
|
sampleCount: int,
|
|
|
|
xyPointLength: int,
|
|
|
|
}
|
|
|
|
|
|
|
|
type outputType = [
|
|
|
|
| #Dist(genericDist)
|
|
|
|
| #Error(error)
|
|
|
|
| #Float(float)
|
2022-03-28 01:07:41 +00:00
|
|
|
| #String(string)
|
2022-03-27 18:22:26 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
let fromResult = (r: result<outputType, error>): outputType =>
|
|
|
|
switch r {
|
|
|
|
| Ok(o) => o
|
|
|
|
| Error(e) => #Error(e)
|
|
|
|
}
|
|
|
|
|
2022-03-27 21:37:27 +00:00
|
|
|
let outputToDistResult = (b: outputType): result<genericDist, error> =>
|
|
|
|
switch b {
|
|
|
|
| #Dist(r) => Ok(r)
|
|
|
|
| #Error(r) => Error(r)
|
|
|
|
| _ => Error(ImpossiblePath)
|
|
|
|
}
|
|
|
|
|
2022-03-27 20:59:46 +00:00
|
|
|
let rec run = (extra, fnName: operation): outputType => {
|
|
|
|
let {sampleCount, xyPointLength} = extra
|
2022-03-27 21:37:27 +00:00
|
|
|
|
2022-03-27 20:59:46 +00:00
|
|
|
let reCall = (~extra=extra, ~fnName=fnName, ()) => {
|
|
|
|
run(extra, fnName)
|
2022-03-27 18:22:26 +00:00
|
|
|
}
|
2022-03-27 21:37:27 +00:00
|
|
|
|
2022-03-27 18:22:26 +00:00
|
|
|
let toPointSet = r => {
|
2022-03-27 20:59:46 +00:00
|
|
|
switch reCall(~fnName=#fromDist(#toDist(#toPointSet), r), ()) {
|
2022-03-27 18:22:26 +00:00
|
|
|
| #Dist(#PointSet(p)) => Ok(p)
|
|
|
|
| #Error(r) => Error(r)
|
|
|
|
| _ => Error(ImpossiblePath)
|
|
|
|
}
|
|
|
|
}
|
2022-03-27 21:37:27 +00:00
|
|
|
|
2022-03-27 18:22:26 +00:00
|
|
|
let toSampleSet = r => {
|
2022-03-27 20:59:46 +00:00
|
|
|
switch reCall(~fnName=#fromDist(#toDist(#toSampleSet(sampleCount)), r), ()) {
|
2022-03-27 18:22:26 +00:00
|
|
|
| #Dist(#SampleSet(p)) => Ok(p)
|
|
|
|
| #Error(r) => Error(r)
|
|
|
|
| _ => Error(ImpossiblePath)
|
|
|
|
}
|
|
|
|
}
|
2022-03-27 20:59:46 +00:00
|
|
|
|
2022-03-27 21:37:27 +00:00
|
|
|
let scaleMultiply = (r, weight) =>
|
|
|
|
reCall(
|
|
|
|
~fnName=#fromDist(#toDistCombination(#Pointwise, #Multiply, #Float(weight)), r),
|
|
|
|
(),
|
|
|
|
) |> outputToDistResult
|
|
|
|
|
|
|
|
let pointwiseAdd = (r1, r2) =>
|
|
|
|
reCall(
|
|
|
|
~fnName=#fromDist(#toDistCombination(#Pointwise, #Add, #Dist(r2)), r1),
|
|
|
|
(),
|
|
|
|
) |> outputToDistResult
|
|
|
|
|
2022-03-27 20:59:46 +00:00
|
|
|
let fromDistFn = (subFn: GenericDist_Types.Operation.fromDist, dist: genericDist) =>
|
|
|
|
switch subFn {
|
|
|
|
| #toFloat(fnName) =>
|
|
|
|
GenericDist.operationToFloat(toPointSet, fnName, dist)
|
|
|
|
|> E.R.fmap(r => #Float(r))
|
|
|
|
|> fromResult
|
2022-03-28 01:07:41 +00:00
|
|
|
| #toString => dist |> GenericDist.toString |> (r => #String(r))
|
2022-03-27 20:59:46 +00:00
|
|
|
| #toDist(#normalize) => dist |> GenericDist.normalize |> (r => #Dist(r))
|
|
|
|
| #toDist(#truncate(left, right)) =>
|
|
|
|
dist
|
2022-03-28 12:39:07 +00:00
|
|
|
|> GenericDist.truncate(toPointSet, left, right)
|
2022-03-27 20:59:46 +00:00
|
|
|
|> E.R.fmap(r => #Dist(r))
|
|
|
|
|> fromResult
|
|
|
|
| #toDist(#toPointSet) =>
|
|
|
|
dist
|
|
|
|
|> GenericDist.toPointSet(xyPointLength)
|
|
|
|
|> E.R.fmap(r => #Dist(#PointSet(r)))
|
|
|
|
|> fromResult
|
|
|
|
| #toDist(#toSampleSet(n)) =>
|
|
|
|
dist |> GenericDist.sampleN(n) |> E.R.fmap(r => #Dist(#SampleSet(r))) |> fromResult
|
|
|
|
| #toDistCombination(#Algebraic, _, #Float(_)) => #Error(NotYetImplemented)
|
|
|
|
| #toDistCombination(#Algebraic, operation, #Dist(dist2)) =>
|
|
|
|
dist
|
2022-03-28 12:39:07 +00:00
|
|
|
|> GenericDist.algebraicCombination(toPointSet, toSampleSet, operation, dist2)
|
2022-03-27 20:59:46 +00:00
|
|
|
|> E.R.fmap(r => #Dist(r))
|
|
|
|
|> fromResult
|
|
|
|
| #toDistCombination(#Pointwise, operation, #Dist(dist2)) =>
|
|
|
|
dist
|
|
|
|
|> GenericDist.pointwiseCombination(toPointSet, operation, dist2)
|
|
|
|
|> E.R.fmap(r => #Dist(r))
|
|
|
|
|> fromResult
|
|
|
|
| #toDistCombination(#Pointwise, operation, #Float(f)) =>
|
|
|
|
dist
|
|
|
|
|> GenericDist.pointwiseCombinationFloat(toPointSet, operation, f)
|
|
|
|
|> E.R.fmap(r => #Dist(r))
|
|
|
|
|> fromResult
|
|
|
|
}
|
|
|
|
|
2022-03-27 18:22:26 +00:00
|
|
|
switch fnName {
|
2022-03-27 20:59:46 +00:00
|
|
|
| #fromDist(subFn, dist) => fromDistFn(subFn, dist)
|
2022-03-27 21:37:27 +00:00
|
|
|
| #fromFloat(subFn, float) => reCall(~fnName=#fromDist(subFn, GenericDist.fromFloat(float)), ())
|
|
|
|
| #mixture(dists) =>
|
|
|
|
GenericDist.mixture(scaleMultiply, pointwiseAdd, dists) |> E.R.fmap(r => #Dist(r)) |> fromResult
|
2022-03-27 18:22:26 +00:00
|
|
|
}
|
|
|
|
}
|