// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build go1.18

package kernels

import (
	
	
	
)

type computeWordFN func(leftTrue, leftFalse, rightTrue, rightFalse uint64) (outValid, outData uint64)

func computeKleene( computeWordFN,  *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	var (
		 = [4]bitutil.Bitmap{
			{Data: .Buffers[0].Buf, Offset: .Offset, Len: .Len},
			{Data: .Buffers[1].Buf, Offset: .Offset, Len: .Len},
			{Data: .Buffers[1].Buf, Offset: .Offset, Len: .Len},
			{Data: .Buffers[0].Buf, Offset: .Offset, Len: .Len},
		}
		 = [2]bitutil.Bitmap{
			{Data: .Buffers[0].Buf, Offset: .Offset, Len: .Len},
			{Data: .Buffers[1].Buf, Offset: .Offset, Len: .Len},
		}
		 = func(,  uint64, ,  uint64) (,  uint64) {
			,  := &, &^
			,  := &, &^
			return (, , , )
		}
	)

	switch {
	case .UpdateNullCount() == 0:
		return bitutil.VisitWordsAndWrite([:3], [:],
			func(,  []uint64) {
				[0], [1] = ([0], [1], ^uint64(0), [2])
			})
	case .UpdateNullCount() == 0:
		return bitutil.VisitWordsAndWrite([1:], [:],
			func(,  []uint64) {
				[0], [1] = (^uint64(0), [0], [2], [1])
			})
	default:
		return bitutil.VisitWordsAndWrite([:], [:],
			func(,  []uint64) {
				[0], [1] = ([0], [1], [3], [2])
			})
	}
}

type AndOpKernel struct {
	commutativeBinaryKernel[AndOpKernel]
}

func (AndOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	bitutil.BitmapAnd(.Buffers[1].Buf, .Buffers[1].Buf,
		.Offset, .Offset, .Buffers[1].Buf, .Offset, .Len)
	return nil
}

func (AndOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	if !.IsValid() {
		return nil
	}

	 := .Buffers[1].Buf
	if .(*scalar.Boolean).Value {
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset),
			int(.Len), , int(.Offset))
	} else {
		bitutil.SetBitsTo(, .Offset, .Len, false)
	}
	return nil
}

type KleeneAndOpKernel struct {
	commutativeBinaryKernel[KleeneAndOpKernel]
}

func (KleeneAndOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	if .UpdateNullCount() == 0 && .UpdateNullCount() == 0 {
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		return (AndOpKernel{}).Call(, , , )
	}

	 := func(, , ,  uint64) (,  uint64) {
		return  |  | ( & ),  & 
	}
	return computeKleene(, , , , )
}

func (KleeneAndOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	var (
		  = .IsValid() && .(*scalar.Boolean).Value
		 = .IsValid() && !.(*scalar.Boolean).Value
	)

	switch {
	case :
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		bitutil.SetBitsTo(.Buffers[1].Buf, .Offset, .Len, false)
	case :
		if .UpdateNullCount() == 0 {
			bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
			.Nulls = 0
		} else {
			bitutil.CopyBitmap(.Buffers[0].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		}
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	default: // scalar was null: out[i] is valid iff right[i] was false
		if .UpdateNullCount() == 0 {
			bitutil.InvertBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		} else {
			bitutil.BitmapAndNot(.Buffers[0].Buf, .Buffers[1].Buf, .Offset,
				.Offset, .Buffers[0].Buf, .Offset, .Len)
		}
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	}
	return nil
}

type OrOpKernel struct {
	commutativeBinaryKernel[OrOpKernel]
}

func (OrOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	bitutil.BitmapOr(.Buffers[1].Buf, .Buffers[1].Buf,
		.Offset, .Offset, .Buffers[1].Buf, .Offset, .Len)
	return nil
}

func (OrOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	if !.IsValid() {
		return nil
	}

	 := .Buffers[1].Buf
	if .(*scalar.Boolean).Value {
		bitutil.SetBitsTo(, .Offset, .Len, true)
	} else {
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset),
			int(.Len), , int(.Offset))
	}
	return nil
}

type KleeneOrOpKernel struct {
	commutativeBinaryKernel[KleeneOrOpKernel]
}

func (KleeneOrOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	if .UpdateNullCount() == 0 && .UpdateNullCount() == 0 {
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		return (OrOpKernel{}).Call(, , , )
	}

	 := func(, , ,  uint64) (,  uint64) {
		return  |  | ( & ),  | 
	}
	return computeKleene(, , , , )
}

func (KleeneOrOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	var (
		  = .IsValid() && .(*scalar.Boolean).Value
		 = .IsValid() && !.(*scalar.Boolean).Value
	)

	switch {
	case :
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		bitutil.SetBitsTo(.Buffers[1].Buf, .Offset, .Len, true) // all true case
	case :
		if .UpdateNullCount() == 0 {
			bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
			.Nulls = 0
		} else {
			bitutil.CopyBitmap(.Buffers[0].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		}
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	default: // scalar was null: out[i] is valid iff right[i] was true
		if .UpdateNullCount() == 0 {
			bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		} else {
			bitutil.BitmapAnd(.Buffers[0].Buf, .Buffers[1].Buf, .Offset,
				.Offset, .Buffers[0].Buf, .Offset, .Len)
		}
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	}
	return nil
}

type XorOpKernel struct {
	commutativeBinaryKernel[XorOpKernel]
}

func (XorOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	bitutil.BitmapXor(.Buffers[1].Buf, .Buffers[1].Buf,
		.Offset, .Offset, .Buffers[1].Buf, .Offset, .Len)
	return nil
}

func (XorOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	if !.IsValid() {
		return nil
	}

	 := .Buffers[1].Buf
	if .(*scalar.Boolean).Value {
		bitutil.InvertBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			, int(.Offset))
	} else {
		bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			, int(.Offset))
	}
	return nil
}

func invertScalar( scalar.Scalar) *scalar.Boolean {
	if .IsValid() {
		return scalar.NewBooleanScalar(!.(*scalar.Boolean).Value)
	}
	return .(*scalar.Boolean)
}

type AndNotOpKernel struct{}

func (AndNotOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	bitutil.BitmapAndNot(.Buffers[1].Buf, .Buffers[1].Buf, .Offset, .Offset,
		.Buffers[1].Buf, .Offset, .Len)
	return nil
}

func (AndNotOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	if !.IsValid() {
		return nil
	}

	 := .Buffers[1].Buf
	if .(*scalar.Boolean).Value {
		bitutil.InvertBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			, int(.Offset))
	} else {
		bitutil.SetBitsTo(, .Offset, .Len, false)
	}
	return nil
}

func (AndNotOpKernel) ( *exec.KernelCtx,  *exec.ArraySpan,  scalar.Scalar,  *exec.ExecResult) error {
	return (AndOpKernel{}).CallScalarRight(, , invertScalar(), )
}

type KleeneAndNotOpKernel struct{}

func (KleeneAndNotOpKernel) ( *exec.KernelCtx, ,  *exec.ArraySpan,  *exec.ExecResult) error {
	if .UpdateNullCount() == 0 && .UpdateNullCount() == 0 {
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		return (AndNotOpKernel{}).Call(, , , )
	}

	 := func(, , ,  uint64) (,  uint64) {
		return  |  | ( & ),  & 
	}

	return computeKleene(, , , , )
}

func (KleeneAndNotOpKernel) ( *exec.KernelCtx,  scalar.Scalar,  *exec.ArraySpan,  *exec.ExecResult) error {
	var (
		  = .IsValid() && .(*scalar.Boolean).Value
		 = .IsValid() && !.(*scalar.Boolean).Value
	)

	switch {
	case :
		bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
		.Nulls = 0
		bitutil.SetBitsTo(.Buffers[1].Buf, .Offset, .Len, false)
	case :
		if .UpdateNullCount() == 0 {
			bitutil.SetBitsTo(.Buffers[0].Buf, .Offset, .Len, true)
			.Nulls = 0
		} else {
			bitutil.CopyBitmap(.Buffers[0].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		}
		bitutil.InvertBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	default: // scalar was null: out[i] is valid iff right[i] was true
		if .UpdateNullCount() == 0 {
			bitutil.CopyBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
				.Buffers[0].Buf, int(.Offset))
		} else {
			bitutil.BitmapAnd(.Buffers[0].Buf, .Buffers[1].Buf, .Offset, .Offset,
				.Buffers[0].Buf, .Offset, .Len)
		}
		bitutil.InvertBitmap(.Buffers[1].Buf, int(.Offset), int(.Len),
			.Buffers[1].Buf, int(.Offset))
	}
	return nil
}

func (KleeneAndNotOpKernel) ( *exec.KernelCtx,  *exec.ArraySpan,  scalar.Scalar,  *exec.ExecResult) error {
	return (KleeneAndOpKernel{}).CallScalarRight(, , invertScalar(), )
}

func ( *exec.KernelCtx,  *exec.ExecSpan,  *exec.ExecResult) error {
	bitutil.InvertBitmap(.Values[0].Array.Buffers[1].Buf, int(.Values[0].Array.Offset),
		int(.Values[0].Array.Len), .Buffers[1].Buf, int(.Offset))

	.Buffers[0] = .Values[0].Array.Buffers[0]
	if .Buffers[0].SelfAlloc {
		.Buffers[0].SelfAlloc = false
	}
	.Nulls = .Values[0].Array.Nulls

	return nil
}