github.com/apache/arrow/go/v16@v16.1.0/arrow/compute/internal/kernels/scalar_boolean.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 //go:build go1.18 18 19 package kernels 20 21 import ( 22 "github.com/apache/arrow/go/v16/arrow/bitutil" 23 "github.com/apache/arrow/go/v16/arrow/compute/exec" 24 "github.com/apache/arrow/go/v16/arrow/scalar" 25 ) 26 27 type computeWordFN func(leftTrue, leftFalse, rightTrue, rightFalse uint64) (outValid, outData uint64) 28 29 func computeKleene(computeWord computeWordFN, ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 30 var ( 31 inBMs = [4]bitutil.Bitmap{ 32 {Data: left.Buffers[0].Buf, Offset: left.Offset, Len: left.Len}, 33 {Data: left.Buffers[1].Buf, Offset: left.Offset, Len: left.Len}, 34 {Data: right.Buffers[1].Buf, Offset: right.Offset, Len: right.Len}, 35 {Data: right.Buffers[0].Buf, Offset: right.Offset, Len: right.Len}, 36 } 37 outBMs = [2]bitutil.Bitmap{ 38 {Data: out.Buffers[0].Buf, Offset: out.Offset, Len: out.Len}, 39 {Data: out.Buffers[1].Buf, Offset: out.Offset, Len: out.Len}, 40 } 41 apply = func(leftValid, leftData uint64, rightValid, rightData uint64) (outValidity, outData uint64) { 42 leftTrue, leftFalse := leftValid&leftData, leftValid&^leftData 43 rightTrue, rightFalse := rightValid&rightData, rightValid&^rightData 44 return computeWord(leftTrue, leftFalse, rightTrue, rightFalse) 45 } 46 ) 47 48 switch { 49 case right.UpdateNullCount() == 0: 50 return bitutil.VisitWordsAndWrite(inBMs[:3], outBMs[:], 51 func(in, out []uint64) { 52 out[0], out[1] = apply(in[0], in[1], ^uint64(0), in[2]) 53 }) 54 case left.UpdateNullCount() == 0: 55 return bitutil.VisitWordsAndWrite(inBMs[1:], outBMs[:], 56 func(in, out []uint64) { 57 out[0], out[1] = apply(^uint64(0), in[0], in[2], in[1]) 58 }) 59 default: 60 return bitutil.VisitWordsAndWrite(inBMs[:], outBMs[:], 61 func(in, out []uint64) { 62 out[0], out[1] = apply(in[0], in[1], in[3], in[2]) 63 }) 64 } 65 } 66 67 type AndOpKernel struct { 68 commutativeBinaryKernel[AndOpKernel] 69 } 70 71 func (AndOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 72 bitutil.BitmapAnd(left.Buffers[1].Buf, right.Buffers[1].Buf, 73 left.Offset, right.Offset, out.Buffers[1].Buf, out.Offset, left.Len) 74 return nil 75 } 76 77 func (AndOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 78 if !left.IsValid() { 79 return nil 80 } 81 82 outBM := out.Buffers[1].Buf 83 if left.(*scalar.Boolean).Value { 84 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), 85 int(right.Len), outBM, int(out.Offset)) 86 } else { 87 bitutil.SetBitsTo(outBM, out.Offset, out.Len, false) 88 } 89 return nil 90 } 91 92 type KleeneAndOpKernel struct { 93 commutativeBinaryKernel[KleeneAndOpKernel] 94 } 95 96 func (KleeneAndOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 97 if left.UpdateNullCount() == 0 && right.UpdateNullCount() == 0 { 98 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 99 out.Nulls = 0 100 return (AndOpKernel{}).Call(ctx, left, right, out) 101 } 102 103 computeWord := func(leftTrue, leftFalse, rightTrue, rightFalse uint64) (outValid, outData uint64) { 104 return leftFalse | rightFalse | (leftTrue & rightTrue), leftTrue & rightTrue 105 } 106 return computeKleene(computeWord, ctx, left, right, out) 107 } 108 109 func (KleeneAndOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 110 var ( 111 leftTrue = left.IsValid() && left.(*scalar.Boolean).Value 112 leftFalse = left.IsValid() && !left.(*scalar.Boolean).Value 113 ) 114 115 switch { 116 case leftFalse: 117 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 118 out.Nulls = 0 119 bitutil.SetBitsTo(out.Buffers[1].Buf, out.Offset, out.Len, false) 120 case leftTrue: 121 if right.UpdateNullCount() == 0 { 122 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 123 out.Nulls = 0 124 } else { 125 bitutil.CopyBitmap(right.Buffers[0].Buf, int(right.Offset), int(right.Len), 126 out.Buffers[0].Buf, int(out.Offset)) 127 } 128 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 129 out.Buffers[1].Buf, int(out.Offset)) 130 default: // scalar was null: out[i] is valid iff right[i] was false 131 if right.UpdateNullCount() == 0 { 132 bitutil.InvertBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 133 out.Buffers[0].Buf, int(out.Offset)) 134 } else { 135 bitutil.BitmapAndNot(right.Buffers[0].Buf, right.Buffers[1].Buf, right.Offset, 136 right.Offset, out.Buffers[0].Buf, out.Offset, right.Len) 137 } 138 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 139 out.Buffers[1].Buf, int(out.Offset)) 140 } 141 return nil 142 } 143 144 type OrOpKernel struct { 145 commutativeBinaryKernel[OrOpKernel] 146 } 147 148 func (OrOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 149 bitutil.BitmapOr(left.Buffers[1].Buf, right.Buffers[1].Buf, 150 left.Offset, right.Offset, out.Buffers[1].Buf, out.Offset, left.Len) 151 return nil 152 } 153 154 func (OrOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 155 if !left.IsValid() { 156 return nil 157 } 158 159 outBM := out.Buffers[1].Buf 160 if left.(*scalar.Boolean).Value { 161 bitutil.SetBitsTo(outBM, out.Offset, out.Len, true) 162 } else { 163 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), 164 int(right.Len), outBM, int(out.Offset)) 165 } 166 return nil 167 } 168 169 type KleeneOrOpKernel struct { 170 commutativeBinaryKernel[KleeneOrOpKernel] 171 } 172 173 func (KleeneOrOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 174 if left.UpdateNullCount() == 0 && right.UpdateNullCount() == 0 { 175 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 176 out.Nulls = 0 177 return (OrOpKernel{}).Call(ctx, left, right, out) 178 } 179 180 computeWord := func(leftTrue, leftFalse, rightTrue, rightFalse uint64) (outValid, outData uint64) { 181 return leftTrue | rightTrue | (leftFalse & rightFalse), leftTrue | rightTrue 182 } 183 return computeKleene(computeWord, ctx, left, right, out) 184 } 185 186 func (KleeneOrOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 187 var ( 188 leftTrue = left.IsValid() && left.(*scalar.Boolean).Value 189 leftFalse = left.IsValid() && !left.(*scalar.Boolean).Value 190 ) 191 192 switch { 193 case leftTrue: 194 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 195 out.Nulls = 0 196 bitutil.SetBitsTo(out.Buffers[1].Buf, out.Offset, out.Len, true) // all true case 197 case leftFalse: 198 if right.UpdateNullCount() == 0 { 199 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 200 out.Nulls = 0 201 } else { 202 bitutil.CopyBitmap(right.Buffers[0].Buf, int(right.Offset), int(right.Len), 203 out.Buffers[0].Buf, int(out.Offset)) 204 } 205 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 206 out.Buffers[1].Buf, int(out.Offset)) 207 default: // scalar was null: out[i] is valid iff right[i] was true 208 if right.UpdateNullCount() == 0 { 209 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 210 out.Buffers[0].Buf, int(out.Offset)) 211 } else { 212 bitutil.BitmapAnd(right.Buffers[0].Buf, right.Buffers[1].Buf, right.Offset, 213 right.Offset, out.Buffers[0].Buf, out.Offset, right.Len) 214 } 215 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 216 out.Buffers[1].Buf, int(out.Offset)) 217 } 218 return nil 219 } 220 221 type XorOpKernel struct { 222 commutativeBinaryKernel[XorOpKernel] 223 } 224 225 func (XorOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 226 bitutil.BitmapXor(left.Buffers[1].Buf, right.Buffers[1].Buf, 227 left.Offset, right.Offset, out.Buffers[1].Buf, out.Offset, out.Len) 228 return nil 229 } 230 231 func (XorOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 232 if !left.IsValid() { 233 return nil 234 } 235 236 outBM := out.Buffers[1].Buf 237 if left.(*scalar.Boolean).Value { 238 bitutil.InvertBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 239 outBM, int(out.Offset)) 240 } else { 241 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 242 outBM, int(out.Offset)) 243 } 244 return nil 245 } 246 247 func invertScalar(in scalar.Scalar) *scalar.Boolean { 248 if in.IsValid() { 249 return scalar.NewBooleanScalar(!in.(*scalar.Boolean).Value) 250 } 251 return in.(*scalar.Boolean) 252 } 253 254 type AndNotOpKernel struct{} 255 256 func (AndNotOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 257 bitutil.BitmapAndNot(left.Buffers[1].Buf, right.Buffers[1].Buf, left.Offset, right.Offset, 258 out.Buffers[1].Buf, out.Offset, right.Len) 259 return nil 260 } 261 262 func (AndNotOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 263 if !left.IsValid() { 264 return nil 265 } 266 267 outBM := out.Buffers[1].Buf 268 if left.(*scalar.Boolean).Value { 269 bitutil.InvertBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 270 outBM, int(out.Offset)) 271 } else { 272 bitutil.SetBitsTo(outBM, out.Offset, out.Len, false) 273 } 274 return nil 275 } 276 277 func (AndNotOpKernel) CallScalarRight(ctx *exec.KernelCtx, left *exec.ArraySpan, right scalar.Scalar, out *exec.ExecResult) error { 278 return (AndOpKernel{}).CallScalarRight(ctx, left, invertScalar(right), out) 279 } 280 281 type KleeneAndNotOpKernel struct{} 282 283 func (KleeneAndNotOpKernel) Call(ctx *exec.KernelCtx, left, right *exec.ArraySpan, out *exec.ExecResult) error { 284 if left.UpdateNullCount() == 0 && right.UpdateNullCount() == 0 { 285 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 286 out.Nulls = 0 287 return (AndNotOpKernel{}).Call(ctx, left, right, out) 288 } 289 290 computeWord := func(leftTrue, leftFalse, rightTrue, rightFalse uint64) (outValid, outData uint64) { 291 return leftFalse | rightTrue | (leftTrue & rightFalse), leftTrue & rightFalse 292 } 293 294 return computeKleene(computeWord, ctx, left, right, out) 295 } 296 297 func (KleeneAndNotOpKernel) CallScalarLeft(ctx *exec.KernelCtx, left scalar.Scalar, right *exec.ArraySpan, out *exec.ExecResult) error { 298 var ( 299 leftTrue = left.IsValid() && left.(*scalar.Boolean).Value 300 leftFalse = left.IsValid() && !left.(*scalar.Boolean).Value 301 ) 302 303 switch { 304 case leftFalse: 305 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 306 out.Nulls = 0 307 bitutil.SetBitsTo(out.Buffers[1].Buf, out.Offset, out.Len, false) 308 case leftTrue: 309 if right.UpdateNullCount() == 0 { 310 bitutil.SetBitsTo(out.Buffers[0].Buf, out.Offset, out.Len, true) 311 out.Nulls = 0 312 } else { 313 bitutil.CopyBitmap(right.Buffers[0].Buf, int(right.Offset), int(right.Len), 314 out.Buffers[0].Buf, int(out.Offset)) 315 } 316 bitutil.InvertBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 317 out.Buffers[1].Buf, int(out.Offset)) 318 default: // scalar was null: out[i] is valid iff right[i] was true 319 if right.UpdateNullCount() == 0 { 320 bitutil.CopyBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 321 out.Buffers[0].Buf, int(out.Offset)) 322 } else { 323 bitutil.BitmapAnd(right.Buffers[0].Buf, right.Buffers[1].Buf, right.Offset, right.Offset, 324 out.Buffers[0].Buf, out.Offset, right.Len) 325 } 326 bitutil.InvertBitmap(right.Buffers[1].Buf, int(right.Offset), int(right.Len), 327 out.Buffers[1].Buf, int(out.Offset)) 328 } 329 return nil 330 } 331 332 func (KleeneAndNotOpKernel) CallScalarRight(ctx *exec.KernelCtx, left *exec.ArraySpan, right scalar.Scalar, out *exec.ExecResult) error { 333 return (KleeneAndOpKernel{}).CallScalarRight(ctx, left, invertScalar(right), out) 334 }