func RangeReduceString(
	low, high, n int,
	reduce func(low, high int) string,
	join func(x, y string) string,
) string {
	var recur func(int, int, int) string
	recur = func(low, high, n int) string {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return join(left, right)
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
RangeReduceString receives a range, a batch count n, a range reducer
function, and a join function, divides the range into batches, and invokes
the range reducer for each of these batches sequentially, covering the
half-open interval from low to high, including low but excluding high. The
results of the range reducer invocations are then combined by repeated
invocations of join.

The range is specified by a low and high integer, with low <= high. The
batches are determined by dividing up the size of the range (high - low) by
n. If n is 0, a reasonable default is used that takes runtime.GOMAXPROCS(0)
into account.

StringRangeReduce panics if high < low, or if n < 0.
package sequential
import (
	"fmt"
	"github.com/exascience/pargo/internal"
)
func Reduce(
	join func(x, y interface{}) interface{},
	firstFunction func() interface{},
	moreFunctions ...func() interface{},
) interface{} {
	result := firstFunction()
	for _, f := range moreFunctions {
		result = join(result, f())
	}
	return result
}
func ReduceFloat64(
	join func(x, y float64) float64,
	firstFunction func() float64,
	moreFunctions ...func() float64,
) float64 {
	result := firstFunction()
	for _, f := range moreFunctions {
		result = join(result, f())
	}
	return result
}
func ReduceFloat64Sum(functions ...func() float64) float64 {
	result := float64(0)
	for _, f := range functions {
		result += f()
	}
	return result
}
func ReduceFloat64Product(functions ...func() float64) float64 {
	result := float64(1)
	for _, f := range functions {
		result *= f()
	}
	return result
}
func ReduceInt(
	join func(x, y int) int,
	firstFunction func() int,
	moreFunctions ...func() int,
) int {
	result := firstFunction()
	for _, f := range moreFunctions {
		result = join(result, f())
	}
	return result
}
func ReduceIntSum(functions ...func() int) int {
	result := 0
	for _, f := range functions {
		result += f()
	}
	return result
}
func ReduceIntProduct(functions ...func() int) int {
	result := 1
	for _, f := range functions {
		result *= f()
	}
	return result
}
func ReduceString(
	join func(x, y string) string,
	firstFunction func() string,
	moreFunctions ...func() string,
) string {
	result := firstFunction()
	for _, f := range moreFunctions {
		result = join(result, f())
	}
	return result
}
func ReduceStringSum(functions ...func() string) string {
	result := ""
	for _, f := range functions {
		result += f()
	}
	return result
}
func Do(thunks ...func()) {
	for _, thunk := range thunks {
		thunk()
	}
}
func And(predicates ...func() bool) bool {
	result := true
	for _, predicate := range predicates {
		result = result && predicate()
	}
	return result
}
func Or(predicates ...func() bool) bool {
	result := false
	for _, predicate := range predicates {
		result = result || predicate()
	}
	return result
}
func Range(
	low, high, n int,
	f func(low, high int),
) {
	var recur func(int, int, int)
	recur = func(low, high, n int) {
		switch {
		case n == 1:
			f(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				f(low, high)
				return
			}
			recur(low, mid, half)
			recur(mid, high, n-half)
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeAnd(
	low, high, n int,
	f func(low, high int) bool,
) bool {
	var recur func(int, int, int) bool
	recur = func(low, high, n int) bool {
		switch {
		case n == 1:
			return f(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return f(low, high)
			}
			b0 := recur(low, mid, half)
			b1 := recur(mid, high, n-half)
			return b0 && b1
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeOr(
	low, high, n int,
	f func(low, high int) bool,
) bool {
	var recur func(int, int, int) bool
	recur = func(low, high, n int) bool {
		switch {
		case n == 1:
			return f(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return f(low, high)
			}
			b0 := recur(low, mid, half)
			b1 := recur(mid, high, n-half)
			return b0 || b1
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduce(
	low, high, n int,
	reduce func(low, high int) interface{},
	join func(x, y interface{}) interface{},
) interface{} {
	var recur func(int, int, int) interface{}
	recur = func(low, high, n int) interface{} {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return join(left, right)
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceInt(
	low, high, n int,
	reduce func(low, high int) int,
	join func(x, y int) int,
) int {
	var recur func(int, int, int) int
	recur = func(low, high, n int) int {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return join(left, right)
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceIntSum(
	low, high, n int,
	reduce func(low, high int) int,
) int {
	var recur func(int, int, int) int
	recur = func(low, high, n int) int {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return left + right
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceIntProduct(
	low, high, n int,
	reduce func(low, high int) int,
) int {
	var recur func(int, int, int) int
	recur = func(low, high, n int) int {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return left * right
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceFloat64(
	low, high, n int,
	reduce func(low, high int) float64,
	join func(x, y float64) float64,
) float64 {
	var recur func(int, int, int) float64
	recur = func(low, high, n int) float64 {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return join(left, right)
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceFloat64Sum(
	low, high, n int,
	reduce func(low, high int) float64,
) float64 {
	var recur func(int, int, int) float64
	recur = func(low, high, n int) float64 {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return left + right
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}
func RangeReduceFloat64Product(
	low, high, n int,
	reduce func(low, high int) float64,
) float64 {
	var recur func(int, int, int) float64
	recur = func(low, high, n int) float64 {
		switch {
		case n == 1:
			return reduce(low, high)
		case n > 1:
			batchSize := ((high - low - 1) / n) + 1
			half := n / 2
			mid := low + batchSize*half
			if mid >= high {
				return reduce(low, high)
			}
			left := recur(low, mid, half)
			right := recur(mid, high, n-half)
			return left * right
		default:
			panic(fmt.Sprintf("invalid number of batches: %v", n))
		}
	}
	return recur(low, high, internal.ComputeNofBatches(low, high, n))
}