// Code generated by genlib2. DO NOT EDIT.

package execution

import (
	"reflect"

	"github.com/pkg/errors"
	"github.com/pdevine/tensor/internal/storage"
)

func (e E) MaxBetween(t reflect.Type, a *storage.Header, b *storage.Header) (err error) {
	as := isScalar(a, t)
	bs := isScalar(b, t)

	switch t {
	case Int:
		at := a.Ints()
		bt := b.Ints()
		switch {
		case as && bs:
			VecMaxI(at, bt)
		case as && !bs:
			MaxSVI(at[0], bt)
		case !as && bs:
			MaxVSI(at, bt[0])
		default:
			VecMaxI(at, bt)
		}
		return
	case Int8:
		at := a.Int8s()
		bt := b.Int8s()
		switch {
		case as && bs:
			VecMaxI8(at, bt)
		case as && !bs:
			MaxSVI8(at[0], bt)
		case !as && bs:
			MaxVSI8(at, bt[0])
		default:
			VecMaxI8(at, bt)
		}
		return
	case Int16:
		at := a.Int16s()
		bt := b.Int16s()
		switch {
		case as && bs:
			VecMaxI16(at, bt)
		case as && !bs:
			MaxSVI16(at[0], bt)
		case !as && bs:
			MaxVSI16(at, bt[0])
		default:
			VecMaxI16(at, bt)
		}
		return
	case Int32:
		at := a.Int32s()
		bt := b.Int32s()
		switch {
		case as && bs:
			VecMaxI32(at, bt)
		case as && !bs:
			MaxSVI32(at[0], bt)
		case !as && bs:
			MaxVSI32(at, bt[0])
		default:
			VecMaxI32(at, bt)
		}
		return
	case Int64:
		at := a.Int64s()
		bt := b.Int64s()
		switch {
		case as && bs:
			VecMaxI64(at, bt)
		case as && !bs:
			MaxSVI64(at[0], bt)
		case !as && bs:
			MaxVSI64(at, bt[0])
		default:
			VecMaxI64(at, bt)
		}
		return
	case Uint:
		at := a.Uints()
		bt := b.Uints()
		switch {
		case as && bs:
			VecMaxU(at, bt)
		case as && !bs:
			MaxSVU(at[0], bt)
		case !as && bs:
			MaxVSU(at, bt[0])
		default:
			VecMaxU(at, bt)
		}
		return
	case Uint8:
		at := a.Uint8s()
		bt := b.Uint8s()
		switch {
		case as && bs:
			VecMaxU8(at, bt)
		case as && !bs:
			MaxSVU8(at[0], bt)
		case !as && bs:
			MaxVSU8(at, bt[0])
		default:
			VecMaxU8(at, bt)
		}
		return
	case Uint16:
		at := a.Uint16s()
		bt := b.Uint16s()
		switch {
		case as && bs:
			VecMaxU16(at, bt)
		case as && !bs:
			MaxSVU16(at[0], bt)
		case !as && bs:
			MaxVSU16(at, bt[0])
		default:
			VecMaxU16(at, bt)
		}
		return
	case Uint32:
		at := a.Uint32s()
		bt := b.Uint32s()
		switch {
		case as && bs:
			VecMaxU32(at, bt)
		case as && !bs:
			MaxSVU32(at[0], bt)
		case !as && bs:
			MaxVSU32(at, bt[0])
		default:
			VecMaxU32(at, bt)
		}
		return
	case Uint64:
		at := a.Uint64s()
		bt := b.Uint64s()
		switch {
		case as && bs:
			VecMaxU64(at, bt)
		case as && !bs:
			MaxSVU64(at[0], bt)
		case !as && bs:
			MaxVSU64(at, bt[0])
		default:
			VecMaxU64(at, bt)
		}
		return
	case Float32:
		at := a.Float32s()
		bt := b.Float32s()
		switch {
		case as && bs:
			VecMaxF32(at, bt)
		case as && !bs:
			MaxSVF32(at[0], bt)
		case !as && bs:
			MaxVSF32(at, bt[0])
		default:
			VecMaxF32(at, bt)
		}
		return
	case Float64:
		at := a.Float64s()
		bt := b.Float64s()
		switch {
		case as && bs:
			VecMaxF64(at, bt)
		case as && !bs:
			MaxSVF64(at[0], bt)
		case !as && bs:
			MaxVSF64(at, bt[0])
		default:
			VecMaxF64(at, bt)
		}
		return
	case String:
		at := a.Strings()
		bt := b.Strings()
		switch {
		case as && bs:
			VecMaxStr(at, bt)
		case as && !bs:
			MaxSVStr(at[0], bt)
		case !as && bs:
			MaxVSStr(at, bt[0])
		default:
			VecMaxStr(at, bt)
		}
		return
	default:
		return errors.Errorf("Unsupported type %v for Max", t)
	}
}

func (e E) MinBetween(t reflect.Type, a *storage.Header, b *storage.Header) (err error) {
	as := isScalar(a, t)
	bs := isScalar(b, t)

	switch t {
	case Int:
		at := a.Ints()
		bt := b.Ints()
		switch {
		case as && bs:
			VecMinI(at, bt)
		case as && !bs:
			MinSVI(at[0], bt)
		case !as && bs:
			MinVSI(at, bt[0])
		default:
			VecMinI(at, bt)
		}
		return
	case Int8:
		at := a.Int8s()
		bt := b.Int8s()
		switch {
		case as && bs:
			VecMinI8(at, bt)
		case as && !bs:
			MinSVI8(at[0], bt)
		case !as && bs:
			MinVSI8(at, bt[0])
		default:
			VecMinI8(at, bt)
		}
		return
	case Int16:
		at := a.Int16s()
		bt := b.Int16s()
		switch {
		case as && bs:
			VecMinI16(at, bt)
		case as && !bs:
			MinSVI16(at[0], bt)
		case !as && bs:
			MinVSI16(at, bt[0])
		default:
			VecMinI16(at, bt)
		}
		return
	case Int32:
		at := a.Int32s()
		bt := b.Int32s()
		switch {
		case as && bs:
			VecMinI32(at, bt)
		case as && !bs:
			MinSVI32(at[0], bt)
		case !as && bs:
			MinVSI32(at, bt[0])
		default:
			VecMinI32(at, bt)
		}
		return
	case Int64:
		at := a.Int64s()
		bt := b.Int64s()
		switch {
		case as && bs:
			VecMinI64(at, bt)
		case as && !bs:
			MinSVI64(at[0], bt)
		case !as && bs:
			MinVSI64(at, bt[0])
		default:
			VecMinI64(at, bt)
		}
		return
	case Uint:
		at := a.Uints()
		bt := b.Uints()
		switch {
		case as && bs:
			VecMinU(at, bt)
		case as && !bs:
			MinSVU(at[0], bt)
		case !as && bs:
			MinVSU(at, bt[0])
		default:
			VecMinU(at, bt)
		}
		return
	case Uint8:
		at := a.Uint8s()
		bt := b.Uint8s()
		switch {
		case as && bs:
			VecMinU8(at, bt)
		case as && !bs:
			MinSVU8(at[0], bt)
		case !as && bs:
			MinVSU8(at, bt[0])
		default:
			VecMinU8(at, bt)
		}
		return
	case Uint16:
		at := a.Uint16s()
		bt := b.Uint16s()
		switch {
		case as && bs:
			VecMinU16(at, bt)
		case as && !bs:
			MinSVU16(at[0], bt)
		case !as && bs:
			MinVSU16(at, bt[0])
		default:
			VecMinU16(at, bt)
		}
		return
	case Uint32:
		at := a.Uint32s()
		bt := b.Uint32s()
		switch {
		case as && bs:
			VecMinU32(at, bt)
		case as && !bs:
			MinSVU32(at[0], bt)
		case !as && bs:
			MinVSU32(at, bt[0])
		default:
			VecMinU32(at, bt)
		}
		return
	case Uint64:
		at := a.Uint64s()
		bt := b.Uint64s()
		switch {
		case as && bs:
			VecMinU64(at, bt)
		case as && !bs:
			MinSVU64(at[0], bt)
		case !as && bs:
			MinVSU64(at, bt[0])
		default:
			VecMinU64(at, bt)
		}
		return
	case Float32:
		at := a.Float32s()
		bt := b.Float32s()
		switch {
		case as && bs:
			VecMinF32(at, bt)
		case as && !bs:
			MinSVF32(at[0], bt)
		case !as && bs:
			MinVSF32(at, bt[0])
		default:
			VecMinF32(at, bt)
		}
		return
	case Float64:
		at := a.Float64s()
		bt := b.Float64s()
		switch {
		case as && bs:
			VecMinF64(at, bt)
		case as && !bs:
			MinSVF64(at[0], bt)
		case !as && bs:
			MinVSF64(at, bt[0])
		default:
			VecMinF64(at, bt)
		}
		return
	case String:
		at := a.Strings()
		bt := b.Strings()
		switch {
		case as && bs:
			VecMinStr(at, bt)
		case as && !bs:
			MinSVStr(at[0], bt)
		case !as && bs:
			MinVSStr(at, bt[0])
		default:
			VecMinStr(at, bt)
		}
		return
	default:
		return errors.Errorf("Unsupported type %v for Min", t)
	}
}

func (e E) MaxBetweenIter(t reflect.Type, a *storage.Header, b *storage.Header, ait Iterator, bit Iterator) (err error) {
	as := isScalar(a, t)
	bs := isScalar(b, t)

	switch t {
	case Int:
		at := a.Ints()
		bt := b.Ints()
		switch {
		case as && bs:
			VecMaxI(at, bt)
		case as && !bs:
			MaxIterSVI(at[0], bt, bit)
		case !as && bs:
			MaxIterVSI(at, bt[0], ait)
		default:
			VecMaxIterI(at, bt, ait, bit)
		}
		return
	case Int8:
		at := a.Int8s()
		bt := b.Int8s()
		switch {
		case as && bs:
			VecMaxI8(at, bt)
		case as && !bs:
			MaxIterSVI8(at[0], bt, bit)
		case !as && bs:
			MaxIterVSI8(at, bt[0], ait)
		default:
			VecMaxIterI8(at, bt, ait, bit)
		}
		return
	case Int16:
		at := a.Int16s()
		bt := b.Int16s()
		switch {
		case as && bs:
			VecMaxI16(at, bt)
		case as && !bs:
			MaxIterSVI16(at[0], bt, bit)
		case !as && bs:
			MaxIterVSI16(at, bt[0], ait)
		default:
			VecMaxIterI16(at, bt, ait, bit)
		}
		return
	case Int32:
		at := a.Int32s()
		bt := b.Int32s()
		switch {
		case as && bs:
			VecMaxI32(at, bt)
		case as && !bs:
			MaxIterSVI32(at[0], bt, bit)
		case !as && bs:
			MaxIterVSI32(at, bt[0], ait)
		default:
			VecMaxIterI32(at, bt, ait, bit)
		}
		return
	case Int64:
		at := a.Int64s()
		bt := b.Int64s()
		switch {
		case as && bs:
			VecMaxI64(at, bt)
		case as && !bs:
			MaxIterSVI64(at[0], bt, bit)
		case !as && bs:
			MaxIterVSI64(at, bt[0], ait)
		default:
			VecMaxIterI64(at, bt, ait, bit)
		}
		return
	case Uint:
		at := a.Uints()
		bt := b.Uints()
		switch {
		case as && bs:
			VecMaxU(at, bt)
		case as && !bs:
			MaxIterSVU(at[0], bt, bit)
		case !as && bs:
			MaxIterVSU(at, bt[0], ait)
		default:
			VecMaxIterU(at, bt, ait, bit)
		}
		return
	case Uint8:
		at := a.Uint8s()
		bt := b.Uint8s()
		switch {
		case as && bs:
			VecMaxU8(at, bt)
		case as && !bs:
			MaxIterSVU8(at[0], bt, bit)
		case !as && bs:
			MaxIterVSU8(at, bt[0], ait)
		default:
			VecMaxIterU8(at, bt, ait, bit)
		}
		return
	case Uint16:
		at := a.Uint16s()
		bt := b.Uint16s()
		switch {
		case as && bs:
			VecMaxU16(at, bt)
		case as && !bs:
			MaxIterSVU16(at[0], bt, bit)
		case !as && bs:
			MaxIterVSU16(at, bt[0], ait)
		default:
			VecMaxIterU16(at, bt, ait, bit)
		}
		return
	case Uint32:
		at := a.Uint32s()
		bt := b.Uint32s()
		switch {
		case as && bs:
			VecMaxU32(at, bt)
		case as && !bs:
			MaxIterSVU32(at[0], bt, bit)
		case !as && bs:
			MaxIterVSU32(at, bt[0], ait)
		default:
			VecMaxIterU32(at, bt, ait, bit)
		}
		return
	case Uint64:
		at := a.Uint64s()
		bt := b.Uint64s()
		switch {
		case as && bs:
			VecMaxU64(at, bt)
		case as && !bs:
			MaxIterSVU64(at[0], bt, bit)
		case !as && bs:
			MaxIterVSU64(at, bt[0], ait)
		default:
			VecMaxIterU64(at, bt, ait, bit)
		}
		return
	case Float32:
		at := a.Float32s()
		bt := b.Float32s()
		switch {
		case as && bs:
			VecMaxF32(at, bt)
		case as && !bs:
			MaxIterSVF32(at[0], bt, bit)
		case !as && bs:
			MaxIterVSF32(at, bt[0], ait)
		default:
			VecMaxIterF32(at, bt, ait, bit)
		}
		return
	case Float64:
		at := a.Float64s()
		bt := b.Float64s()
		switch {
		case as && bs:
			VecMaxF64(at, bt)
		case as && !bs:
			MaxIterSVF64(at[0], bt, bit)
		case !as && bs:
			MaxIterVSF64(at, bt[0], ait)
		default:
			VecMaxIterF64(at, bt, ait, bit)
		}
		return
	case String:
		at := a.Strings()
		bt := b.Strings()
		switch {
		case as && bs:
			VecMaxStr(at, bt)
		case as && !bs:
			MaxIterSVStr(at[0], bt, bit)
		case !as && bs:
			MaxIterVSStr(at, bt[0], ait)
		default:
			VecMaxIterStr(at, bt, ait, bit)
		}
		return
	default:
		return errors.Errorf("Unsupported type %v for Max", t)
	}
}

func (e E) MinBetweenIter(t reflect.Type, a *storage.Header, b *storage.Header, ait Iterator, bit Iterator) (err error) {
	as := isScalar(a, t)
	bs := isScalar(b, t)

	switch t {
	case Int:
		at := a.Ints()
		bt := b.Ints()
		switch {
		case as && bs:
			VecMinI(at, bt)
		case as && !bs:
			MinIterSVI(at[0], bt, bit)
		case !as && bs:
			MinIterVSI(at, bt[0], ait)
		default:
			VecMinIterI(at, bt, ait, bit)
		}
		return
	case Int8:
		at := a.Int8s()
		bt := b.Int8s()
		switch {
		case as && bs:
			VecMinI8(at, bt)
		case as && !bs:
			MinIterSVI8(at[0], bt, bit)
		case !as && bs:
			MinIterVSI8(at, bt[0], ait)
		default:
			VecMinIterI8(at, bt, ait, bit)
		}
		return
	case Int16:
		at := a.Int16s()
		bt := b.Int16s()
		switch {
		case as && bs:
			VecMinI16(at, bt)
		case as && !bs:
			MinIterSVI16(at[0], bt, bit)
		case !as && bs:
			MinIterVSI16(at, bt[0], ait)
		default:
			VecMinIterI16(at, bt, ait, bit)
		}
		return
	case Int32:
		at := a.Int32s()
		bt := b.Int32s()
		switch {
		case as && bs:
			VecMinI32(at, bt)
		case as && !bs:
			MinIterSVI32(at[0], bt, bit)
		case !as && bs:
			MinIterVSI32(at, bt[0], ait)
		default:
			VecMinIterI32(at, bt, ait, bit)
		}
		return
	case Int64:
		at := a.Int64s()
		bt := b.Int64s()
		switch {
		case as && bs:
			VecMinI64(at, bt)
		case as && !bs:
			MinIterSVI64(at[0], bt, bit)
		case !as && bs:
			MinIterVSI64(at, bt[0], ait)
		default:
			VecMinIterI64(at, bt, ait, bit)
		}
		return
	case Uint:
		at := a.Uints()
		bt := b.Uints()
		switch {
		case as && bs:
			VecMinU(at, bt)
		case as && !bs:
			MinIterSVU(at[0], bt, bit)
		case !as && bs:
			MinIterVSU(at, bt[0], ait)
		default:
			VecMinIterU(at, bt, ait, bit)
		}
		return
	case Uint8:
		at := a.Uint8s()
		bt := b.Uint8s()
		switch {
		case as && bs:
			VecMinU8(at, bt)
		case as && !bs:
			MinIterSVU8(at[0], bt, bit)
		case !as && bs:
			MinIterVSU8(at, bt[0], ait)
		default:
			VecMinIterU8(at, bt, ait, bit)
		}
		return
	case Uint16:
		at := a.Uint16s()
		bt := b.Uint16s()
		switch {
		case as && bs:
			VecMinU16(at, bt)
		case as && !bs:
			MinIterSVU16(at[0], bt, bit)
		case !as && bs:
			MinIterVSU16(at, bt[0], ait)
		default:
			VecMinIterU16(at, bt, ait, bit)
		}
		return
	case Uint32:
		at := a.Uint32s()
		bt := b.Uint32s()
		switch {
		case as && bs:
			VecMinU32(at, bt)
		case as && !bs:
			MinIterSVU32(at[0], bt, bit)
		case !as && bs:
			MinIterVSU32(at, bt[0], ait)
		default:
			VecMinIterU32(at, bt, ait, bit)
		}
		return
	case Uint64:
		at := a.Uint64s()
		bt := b.Uint64s()
		switch {
		case as && bs:
			VecMinU64(at, bt)
		case as && !bs:
			MinIterSVU64(at[0], bt, bit)
		case !as && bs:
			MinIterVSU64(at, bt[0], ait)
		default:
			VecMinIterU64(at, bt, ait, bit)
		}
		return
	case Float32:
		at := a.Float32s()
		bt := b.Float32s()
		switch {
		case as && bs:
			VecMinF32(at, bt)
		case as && !bs:
			MinIterSVF32(at[0], bt, bit)
		case !as && bs:
			MinIterVSF32(at, bt[0], ait)
		default:
			VecMinIterF32(at, bt, ait, bit)
		}
		return
	case Float64:
		at := a.Float64s()
		bt := b.Float64s()
		switch {
		case as && bs:
			VecMinF64(at, bt)
		case as && !bs:
			MinIterSVF64(at[0], bt, bit)
		case !as && bs:
			MinIterVSF64(at, bt[0], ait)
		default:
			VecMinIterF64(at, bt, ait, bit)
		}
		return
	case String:
		at := a.Strings()
		bt := b.Strings()
		switch {
		case as && bs:
			VecMinStr(at, bt)
		case as && !bs:
			MinIterSVStr(at[0], bt, bit)
		case !as && bs:
			MinIterVSStr(at, bt[0], ait)
		default:
			VecMinIterStr(at, bt, ait, bit)
		}
		return
	default:
		return errors.Errorf("Unsupported type %v for Min", t)
	}
}
