04b533ac4484b1376bed2b4eb36e96410520764c
[hive.git] / ql / src / gen / vectorization / ExpressionTemplates / ColumnDivideColumn.txt
1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package org.apache.hadoop.hive.ql.exec.vector.expressions.gen;
20
21 import org.apache.hadoop.hive.ql.exec.vector.expressions.VectorExpression;
22 import org.apache.hadoop.hive.ql.exec.vector.expressions.NullUtil;
23 import org.apache.hadoop.hive.ql.exec.vector.*;
24 import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
25 import org.apache.hadoop.hive.ql.exec.vector.VectorExpressionDescriptor;
26
27 /**
28  * Generated from template ColumnArithmeticColumn.txt, which covers binary arithmetic
29  * expressions between columns.
30  */
31 public class <ClassName> extends VectorExpression {
32
33   private static final long serialVersionUID = 1L;
34
35   private int colNum1;
36   private int colNum2;
37   private int outputColumn;
38
39   public <ClassName>(int colNum1, int colNum2, int outputColumn) {
40     this.colNum1 = colNum1;
41     this.colNum2 = colNum2;
42     this.outputColumn = outputColumn;
43   }
44
45   public <ClassName>() {
46   }
47
48   @Override
49   public void evaluate(VectorizedRowBatch batch) {
50
51     if (childExpressions != null) {
52       super.evaluateChildren(batch);
53     }
54
55     <InputColumnVectorType1> inputColVector1 = (<InputColumnVectorType1>) batch.cols[colNum1];
56     <InputColumnVectorType2> inputColVector2 = (<InputColumnVectorType2>) batch.cols[colNum2];
57     <OutputColumnVectorType> outputColVector = (<OutputColumnVectorType>) batch.cols[outputColumn];
58     int[] sel = batch.selected;
59     int n = batch.size;
60     <OperandType1>[] vector1 = inputColVector1.vector;
61     <OperandType2>[] vector2 = inputColVector2.vector;
62     <ReturnType>[] outputVector = outputColVector.vector;
63
64     // return immediately if batch is empty
65     if (n == 0) {
66       return;
67     }
68
69     outputColVector.isRepeating =
70          inputColVector1.isRepeating && inputColVector2.isRepeating
71       || inputColVector1.isRepeating && !inputColVector1.noNulls && inputColVector1.isNull[0]
72       || inputColVector2.isRepeating && !inputColVector2.noNulls && inputColVector2.isNull[0];
73
74     // Handle nulls first
75     NullUtil.propagateNullsColCol(
76       inputColVector1, inputColVector2, outputColVector, sel, n, batch.selectedInUse);
77
78     /* Disregard nulls for processing. In other words,
79      * the arithmetic operation is performed even if one or
80      * more inputs are null. This is to improve speed by avoiding
81      * conditional checks in the inner loop.
82      */
83     boolean hasDivBy0 = false;
84     if (inputColVector1.isRepeating && inputColVector2.isRepeating) {
85       <OperandType2> denom = vector2[0];
86       outputVector[0] = vector1[0] <OperatorSymbol> denom;
87       hasDivBy0 = hasDivBy0 || (denom == 0);
88     } else if (inputColVector1.isRepeating) {
89       final <OperandType1> vector1Value = vector1[0];
90       if (batch.selectedInUse) {
91         for(int j = 0; j != n; j++) {
92           int i = sel[j];
93           <OperandType2> denom = vector2[i];
94           outputVector[i] = vector1Value <OperatorSymbol> denom;
95           hasDivBy0 = hasDivBy0 || (denom == 0);
96         }
97       } else {
98         for(int i = 0; i != n; i++) {
99           outputVector[i] = vector1Value <OperatorSymbol> vector2[i];
100         }
101
102         for(int i = 0; i != n; i++) {
103           hasDivBy0 = hasDivBy0 || (vector2[i] == 0);
104         }
105       }
106     } else if (inputColVector2.isRepeating) {
107       final <OperandType2> vector2Value = vector2[0];
108       if (vector2Value == 0) {
109         // Denominator is zero, convert the batch to nulls
110         outputColVector.noNulls = false;
111         outputColVector.isRepeating = true;
112         outputColVector.isNull[0] = true;
113       } else if (batch.selectedInUse) {
114         for(int j = 0; j != n; j++) {
115           int i = sel[j];
116           outputVector[i] = vector1[i] <OperatorSymbol> vector2Value;
117         }
118       } else {
119         for(int i = 0; i != n; i++) {
120           outputVector[i] = vector1[i] <OperatorSymbol> vector2Value;
121         }
122       }
123     } else {
124       if (batch.selectedInUse) {
125         for(int j = 0; j != n; j++) {
126           int i = sel[j];
127           <OperandType2> denom = vector2[i];
128           outputVector[i] = vector1[i] <OperatorSymbol> denom;
129           hasDivBy0 = hasDivBy0 || (denom == 0);
130         }
131       } else {
132         for(int i = 0; i != n; i++) {
133           outputVector[i] = vector1[i] <OperatorSymbol> vector2[i];
134         }
135
136         for(int i = 0; i != n; i++) {
137           hasDivBy0 = hasDivBy0 || (vector2[i] == 0);
138         }
139       }
140     }
141
142     /* For the case when the output can have null values, follow
143      * the convention that the data values must be 1 for long and
144      * NaN for double. This is to prevent possible later zero-divide errors
145      * in complex arithmetic expressions like col2 <OperatorSymbol> (col1 - 1)
146      * in the case when some col1 entries are null.
147      */
148     if (!hasDivBy0) {
149       NullUtil.setNullDataEntries<CamelReturnType>(outputColVector, batch.selectedInUse, sel, n);
150     } else {
151       NullUtil.setNullAndDivBy0DataEntries<CamelReturnType>(
152           outputColVector, batch.selectedInUse, sel, n, inputColVector2);
153     }
154   }
155
156   @Override
157   public int getOutputColumn() {
158     return outputColumn;
159   }
160
161   @Override
162   public String getOutputType() {
163     return "<ReturnType>";
164   }
165
166   public int getColNum1() {
167     return colNum1;
168   }
169
170   public void setColNum1(int colNum1) {
171     this.colNum1 = colNum1;
172   }
173
174   public int getColNum2() {
175     return colNum2;
176   }
177
178   public void setColNum2(int colNum2) {
179     this.colNum2 = colNum2;
180   }
181
182   public void setOutputColumn(int outputColumn) {
183     this.outputColumn = outputColumn;
184   }
185
186   @Override
187   public String vectorExpressionParameters() {
188     return "col " + colNum1 + ", col " + + colNum2;
189   }
190
191   @Override
192   public VectorExpressionDescriptor.Descriptor getDescriptor() {
193     return (new VectorExpressionDescriptor.Builder())
194         .setMode(
195             VectorExpressionDescriptor.Mode.PROJECTION)
196         .setNumArguments(2)
197         .setArgumentTypes(
198             VectorExpressionDescriptor.ArgumentType.getType("<OperandType1>"),
199             VectorExpressionDescriptor.ArgumentType.getType("<OperandType2>"))
200         .setInputExpressionTypes(
201             VectorExpressionDescriptor.InputExpressionType.COLUMN,
202             VectorExpressionDescriptor.InputExpressionType.COLUMN).build();
203   }
204 }