This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new ed1d60d  ARROW-3544: [Gandiva] [C++] Create function registry in 
multiple compilation units to reduce build times
ed1d60d is described below

commit ed1d60d0e459108b23ce4ff9bc9129a005058ece
Author: Siddharth Dave <[email protected]>
AuthorDate: Mon Jan 7 10:42:50 2019 -0600

    ARROW-3544: [Gandiva] [C++] Create function registry in multiple 
compilation units to reduce build times
    
    Refactored function_registry into separate files. The function signatures 
are now split across
    3 different files viz. function_registry.cc, function_registry_binaryfn.cc 
& function_registry_unaryfn.cc.
    This approach reduces the build times on my setup with little refactoring.
    
    I looked into tensorflow as well, as Wes had suggested, however tensorflow 
heavily utilizes tempalate based
    approach, which is quite different from this & may require quite a bit of 
refactoring in gandiva.
    
    Author: Siddharth Dave <[email protected]>
    
    Closes #3051 from siddharthdave/master and squashes the following commits:
    
    1d75ac7f6 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 removed individual clasess for 
each registry. removed unused header files. cleaned up code.
    ab93602f3 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 fixed lint errors with make 
format
    8161eddb5 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 added a note in 
function_registry_common.h that its for internal use.
    60954a038 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 > Replaced STRINGIFY with 
ARROW_STRINGIFY
    241b6340c <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 > Yet another refactor of 
macros > removed redundant comments
    faeffeef4 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 1. incorporated review comments 
suggested by ravindra 2. refactored code a bit & removed unused includes etc.
    508b7835e <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 Fixed make check-format errors.
    b8176dd40 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 Incorported review comments: 1. 
removed duplicate code/macros & moved it into a new header file 
function_registry_common.h 2. added separate classes for holding different 
function types 3. during initialization, the map is populated by individualy 
populating from these classes into 1 common map.
    1788fb32e <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 Fixing whitespace issue 
reported during 'make lint'
    2cdb6df58 <Siddharth Dave> ARROW-3544:   Extremely long compile time for 
function_registry.cc in release mode on clang 6 Refactored function_registry 
into separate files. The function signatures are now split across 3 different 
files viz. function_registry.cc, function_registry_binaryfn.cc & 
function_registry_unaryfn.cc. This approach reduces the build times on my setup 
with little refactoring.
---
 cpp/src/arrow/test-util.h                          |  48 ++-
 cpp/src/arrow/util/macros.h                        |   2 +
 cpp/src/gandiva/CMakeLists.txt                     |   6 +
 cpp/src/gandiva/function_registry.cc               | 440 ++-------------------
 cpp/src/gandiva/function_registry.h                |  25 +-
 cpp/src/gandiva/function_registry_arithmetic.cc    |  78 ++++
 cpp/src/gandiva/function_registry_arithmetic.h     |  30 ++
 cpp/src/gandiva/function_registry_common.h         | 218 ++++++++++
 cpp/src/gandiva/function_registry_datetime.cc      |  65 +++
 cpp/src/gandiva/function_registry_datetime.h       |  30 ++
 cpp/src/gandiva/function_registry_hash.cc          |  53 +++
 cpp/src/gandiva/function_registry_hash.h           |  30 ++
 cpp/src/gandiva/function_registry_math_ops.cc      |  67 ++++
 cpp/src/gandiva/function_registry_math_ops.h       |  30 ++
 cpp/src/gandiva/function_registry_string.cc        |  50 +++
 cpp/src/gandiva/function_registry_string.h         |  30 ++
 .../function_registry_timestamp_arithmetic.cc      |  81 ++++
 .../function_registry_timestamp_arithmetic.h       |  30 ++
 cpp/src/gandiva/native_function.h                  |   4 +-
 19 files changed, 862 insertions(+), 455 deletions(-)

diff --git a/cpp/src/arrow/test-util.h b/cpp/src/arrow/test-util.h
index 3332163..aa7c73e 100644
--- a/cpp/src/arrow/test-util.h
+++ b/cpp/src/arrow/test-util.h
@@ -46,35 +46,33 @@
 #include "arrow/util/macros.h"
 #include "arrow/util/visibility.h"
 
-#define STRINGIFY(x) #x
-
-#define ASSERT_RAISES(ENUM, expr)                                         \
-  do {                                                                    \
-    ::arrow::Status s = (expr);                                           \
-    if (!s.Is##ENUM()) {                                                  \
-      FAIL() << "Expected '" STRINGIFY(expr) "' to fail with " STRINGIFY( \
-                    ENUM) ", but got "                                    \
-             << s.ToString();                                             \
-    }                                                                     \
+#define ASSERT_RAISES(ENUM, expr)                                              
       \
+  do {                                                                         
       \
+    ::arrow::Status s = (expr);                                                
       \
+    if (!s.Is##ENUM()) {                                                       
       \
+      FAIL() << "Expected '" ARROW_STRINGIFY(expr) "' to fail with " 
ARROW_STRINGIFY( \
+                    ENUM) ", but got "                                         
       \
+             << s.ToString();                                                  
       \
+    }                                                                          
       \
   } while (false)
 
-#define ASSERT_RAISES_WITH_MESSAGE(ENUM, message, expr)                   \
-  do {                                                                    \
-    ::arrow::Status s = (expr);                                           \
-    if (!s.Is##ENUM()) {                                                  \
-      FAIL() << "Expected '" STRINGIFY(expr) "' to fail with " STRINGIFY( \
-                    ENUM) ", but got "                                    \
-             << s.ToString();                                             \
-    }                                                                     \
-    ASSERT_EQ((message), s.ToString());                                   \
+#define ASSERT_RAISES_WITH_MESSAGE(ENUM, message, expr)                        
       \
+  do {                                                                         
       \
+    ::arrow::Status s = (expr);                                                
       \
+    if (!s.Is##ENUM()) {                                                       
       \
+      FAIL() << "Expected '" ARROW_STRINGIFY(expr) "' to fail with " 
ARROW_STRINGIFY( \
+                    ENUM) ", but got "                                         
       \
+             << s.ToString();                                                  
       \
+    }                                                                          
       \
+    ASSERT_EQ((message), s.ToString());                                        
       \
   } while (false)
 
-#define ASSERT_OK(expr)                                                \
-  do {                                                                 \
-    ::arrow::Status _s = (expr);                                       \
-    if (!_s.ok()) {                                                    \
-      FAIL() << "'" STRINGIFY(expr) "' failed with " << _s.ToString(); \
-    }                                                                  \
+#define ASSERT_OK(expr)                                                      \
+  do {                                                                       \
+    ::arrow::Status _s = (expr);                                             \
+    if (!_s.ok()) {                                                          \
+      FAIL() << "'" ARROW_STRINGIFY(expr) "' failed with " << _s.ToString(); \
+    }                                                                        \
   } while (false)
 
 #define ASSERT_OK_NO_THROW(expr) ASSERT_NO_THROW(ASSERT_OK(expr))
diff --git a/cpp/src/arrow/util/macros.h b/cpp/src/arrow/util/macros.h
index 1d18882..f4c58f4 100644
--- a/cpp/src/arrow/util/macros.h
+++ b/cpp/src/arrow/util/macros.h
@@ -18,6 +18,8 @@
 #ifndef ARROW_UTIL_MACROS_H
 #define ARROW_UTIL_MACROS_H
 
+#define ARROW_STRINGIFY(x) #x
+
 // From Google gutil
 #ifndef ARROW_DISALLOW_COPY_AND_ASSIGN
 #define ARROW_DISALLOW_COPY_AND_ASSIGN(TypeName) \
diff --git a/cpp/src/gandiva/CMakeLists.txt b/cpp/src/gandiva/CMakeLists.txt
index 6b67c86..90fe7cf 100644
--- a/cpp/src/gandiva/CMakeLists.txt
+++ b/cpp/src/gandiva/CMakeLists.txt
@@ -55,6 +55,12 @@ set(SRC_FILES annotator.cc
       exported_funcs_registry.cc
       filter.cc
       function_registry.cc
+      function_registry_arithmetic.cc
+      function_registry_datetime.cc
+      function_registry_hash.cc
+      function_registry_math_ops.cc
+      function_registry_string.cc
+      function_registry_timestamp_arithmetic.cc
       function_signature.cc
       gdv_function_stubs.cc
       llvm_generator.cc
diff --git a/cpp/src/gandiva/function_registry.cc 
b/cpp/src/gandiva/function_registry.cc
index 3928fbe..83d80b4 100644
--- a/cpp/src/gandiva/function_registry.cc
+++ b/cpp/src/gandiva/function_registry.cc
@@ -16,7 +16,15 @@
 // under the License.
 
 #include "gandiva/function_registry.h"
-
+#include "gandiva/function_registry_arithmetic.h"
+#include "gandiva/function_registry_datetime.h"
+#include "gandiva/function_registry_hash.h"
+#include "gandiva/function_registry_math_ops.h"
+#include "gandiva/function_registry_string.h"
+#include "gandiva/function_registry_timestamp_arithmetic.h"
+
+#include <iterator>
+#include <utility>
 #include <vector>
 
 namespace gandiva {
@@ -35,424 +43,46 @@ using arrow::uint32;
 using arrow::uint64;
 using arrow::uint8;
 using arrow::utf8;
+using std::iterator;
 using std::vector;
 
-#define STRINGIFY(a) #a
-
-// Binary functions that :
-// - have the same input type for both params
-// - output type is same as the input type
-// - NULL handling is of type NULL_IF_NULL
-//
-// The pre-compiled fn name includes the base name & input type names. eg. 
add_int32_int32
-#define BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(NAME, TYPE)                         
    \
-  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, TYPE(), 
kResultNullIfNull, \
-                 STRINGIFY(NAME##_##TYPE##_##TYPE))
-
-// Binary functions that :
-// - have the same input type for both params
-// - NULL handling is of type NULL_IINTERNAL
-// - can return error.
-//
-// The pre-compiled fn name includes the base name & input type names. eg. 
add_int32_int32
-#define BINARY_UNSAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                  \
-  NativeFunction(#NAME, DataTypeVector{IN_TYPE(), IN_TYPE()}, OUT_TYPE(),    \
-                 kResultNullIfNull, STRINGIFY(NAME##_##IN_TYPE##_##IN_TYPE), \
-                 NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors)
-
-#define BINARY_SYMMETRIC_UNSAFE_NULL_IF_NULL(NAME, TYPE) \
-  BINARY_UNSAFE_NULL_IF_NULL(NAME, TYPE, TYPE)
-
-// Binary functions that :
-// - have different input types, or output type
-// - NULL handling is of type NULL_IF_NULL
-//
-// The pre-compiled fn name includes the base name & input type names. eg. 
mod_int64_int32
-#define BINARY_GENERIC_SAFE_NULL_IF_NULL(NAME, IN_TYPE1, IN_TYPE2, OUT_TYPE) \
-  NativeFunction(#NAME, DataTypeVector{IN_TYPE1(), IN_TYPE2()}, OUT_TYPE(),  \
-                 kResultNullIfNull, STRINGIFY(NAME##_##IN_TYPE1##_##IN_TYPE2))
-
-// Binary functions that :
-// - have the same input type
-// - output type is boolean
-// - NULL handling is of type NULL_IF_NULL
-//
-// The pre-compiled fn name includes the base name & input type names.
-// eg. equal_int32_int32
-#define BINARY_RELATIONAL_SAFE_NULL_IF_NULL(NAME, TYPE)                        
       \
-  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, boolean(), 
kResultNullIfNull, \
-                 STRINGIFY(NAME##_##TYPE##_##TYPE))
-
-// Unary functions that :
-// - NULL handling is of type NULL_IF_NULL
-//
-// The pre-compiled fn name includes the base name & input type name. eg. 
castFloat_int32
-#define UNARY_SAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                       
   \
-  NativeFunction(#NAME, DataTypeVector{IN_TYPE()}, OUT_TYPE(), 
kResultNullIfNull, \
-                 STRINGIFY(NAME##_##IN_TYPE))
-
-// Unary functions that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type name. eg. 
isnull_int32
-#define UNARY_SAFE_NULL_NEVER_BOOL(NAME, TYPE)                               \
-  NativeFunction(#NAME, DataTypeVector{TYPE()}, boolean(), kResultNullNever, \
-                 STRINGIFY(NAME##_##TYPE))
-
-// Unary functions that :
-// - NULL handling is of type NULL_INTERNAL
-//
-// The pre-compiled fn name includes the base name & input type name. eg. 
castFloat_int32
-#define UNARY_UNSAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                     
   \
-  NativeFunction(#NAME, DataTypeVector{IN_TYPE()}, OUT_TYPE(), 
kResultNullIfNull, \
-                 STRINGIFY(NAME##_##IN_TYPE),                                  
   \
-                 NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors)
-
-// Binary functions that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type names,
-// eg. is_distinct_from_int32_int32
-#define BINARY_SAFE_NULL_NEVER_BOOL(NAME, TYPE)                                
      \
-  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, boolean(), 
kResultNullNever, \
-                 STRINGIFY(NAME##_##TYPE##_##TYPE))
-
-// Extract functions (used with data/time types) that :
-// - NULL handling is of type NULL_IF_NULL
-//
-// The pre-compiled fn name includes the base name & input type name. eg. 
extractYear_date
-#define EXTRACT_SAFE_NULL_IF_NULL(NAME, TYPE)                               \
-  NativeFunction(#NAME, DataTypeVector{TYPE()}, int64(), kResultNullIfNull, \
-                 STRINGIFY(NAME##_##TYPE))
-
-// Hash32 functions that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type name. 
hash32_int8
-#define HASH32_SAFE_NULL_NEVER(NAME, TYPE)                                 \
-  NativeFunction(#NAME, DataTypeVector{TYPE()}, int32(), kResultNullNever, \
-                 STRINGIFY(NAME##_##TYPE))
-
-// Hash32 functions that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type name. 
hash32_int8
-#define HASH64_SAFE_NULL_NEVER(NAME, TYPE)                                 \
-  NativeFunction(#NAME, DataTypeVector{TYPE()}, int64(), kResultNullNever, \
-                 STRINGIFY(NAME##_##TYPE))
-
-// Hash32 functions with seed that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type name. 
hash32WithSeed_int8
-#define HASH32_SEED_SAFE_NULL_NEVER(NAME, TYPE)                                
     \
-  NativeFunction(#NAME, DataTypeVector{TYPE(), int32()}, int32(), 
kResultNullNever, \
-                 STRINGIFY(NAME##WithSeed_##TYPE))
-
-// Hash64 functions with seed that :
-// - NULL handling is of type NULL_NEVER
-//
-// The pre-compiled fn name includes the base name & input type name. 
hash32WithSeed_int8
-#define HASH64_SEED_SAFE_NULL_NEVER(NAME, TYPE)                                
     \
-  NativeFunction(#NAME, DataTypeVector{TYPE(), int64()}, int64(), 
kResultNullNever, \
-                 STRINGIFY(NAME##WithSeed_##TYPE))
-
-// Iterate the inner macro over all numeric types
-#define NUMERIC_TYPES(INNER, NAME)                                             
          \
-  INNER(NAME, int8), INNER(NAME, int16), INNER(NAME, int32), INNER(NAME, 
int64),         \
-      INNER(NAME, uint8), INNER(NAME, uint16), INNER(NAME, uint32), 
INNER(NAME, uint64), \
-      INNER(NAME, float32), INNER(NAME, float64)
-
-// Iterate the inner macro over numeric and date/time types
-#define NUMERIC_DATE_TYPES(INNER, NAME) \
-  NUMERIC_TYPES(INNER, NAME), DATE_TYPES(INNER, NAME), TIME_TYPES(INNER, NAME)
-
-// Iterate the inner macro over all date types
-#define DATE_TYPES(INNER, NAME) INNER(NAME, date64), INNER(NAME, timestamp)
-
-// Iterate the inner macro over all time types
-#define TIME_TYPES(INNER, NAME) INNER(NAME, time32)
-
-// Iterate the inner macro over all data types
-#define VAR_LEN_TYPES(INNER, NAME) INNER(NAME, utf8), INNER(NAME, binary)
-
-// Iterate the inner macro over all numeric types, date types and bool type
-#define NUMERIC_BOOL_DATE_TYPES(INNER, NAME) \
-  NUMERIC_DATE_TYPES(INNER, NAME), INNER(NAME, boolean)
-
-// Iterate the inner macro over all numeric types, date types, bool and varlen 
types
-#define NUMERIC_BOOL_DATE_VAR_LEN_TYPES(INNER, NAME) \
-  NUMERIC_BOOL_DATE_TYPES(INNER, NAME), VAR_LEN_TYPES(INNER, NAME)
-
-// list of registered native functions.
-NativeFunction FunctionRegistry::pc_registry_[] = {
-    // Arithmetic operations
-    NUMERIC_TYPES(BINARY_SYMMETRIC_SAFE_NULL_IF_NULL, add),
-    NUMERIC_TYPES(BINARY_SYMMETRIC_SAFE_NULL_IF_NULL, subtract),
-    NUMERIC_TYPES(BINARY_SYMMETRIC_SAFE_NULL_IF_NULL, multiply),
-    NUMERIC_TYPES(BINARY_SYMMETRIC_UNSAFE_NULL_IF_NULL, divide),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(mod, int64, int32, int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(mod, int64, int64, int64),
-    NUMERIC_BOOL_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, equal),
-    NUMERIC_BOOL_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, not_equal),
-    NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, less_than),
-    NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, 
less_than_or_equal_to),
-    NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, greater_than),
-    NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, 
greater_than_or_equal_to),
-    UNARY_SAFE_NULL_IF_NULL(not, boolean, boolean),
-
-    // cast operations
-    UNARY_SAFE_NULL_IF_NULL(castBIGINT, int32, int64),
-    UNARY_SAFE_NULL_IF_NULL(castFLOAT4, int32, float32),
-    UNARY_SAFE_NULL_IF_NULL(castFLOAT4, int64, float32),
-    UNARY_SAFE_NULL_IF_NULL(castFLOAT8, int32, float64),
-    UNARY_SAFE_NULL_IF_NULL(castFLOAT8, int64, float64),
-    UNARY_SAFE_NULL_IF_NULL(castFLOAT8, float32, float64),
-    UNARY_SAFE_NULL_IF_NULL(castDATE, int64, date64),
-
-    // extended math ops
-    UNARY_SAFE_NULL_IF_NULL(cbrt, int32, float64),
-    UNARY_SAFE_NULL_IF_NULL(cbrt, int64, float64),
-    UNARY_SAFE_NULL_IF_NULL(cbrt, uint32, float64),
-    UNARY_SAFE_NULL_IF_NULL(cbrt, uint64, float64),
-    UNARY_SAFE_NULL_IF_NULL(cbrt, float32, float64),
-    UNARY_SAFE_NULL_IF_NULL(cbrt, float64, float64),
-
-    UNARY_SAFE_NULL_IF_NULL(exp, int32, float64),
-    UNARY_SAFE_NULL_IF_NULL(exp, int64, float64),
-    UNARY_SAFE_NULL_IF_NULL(exp, uint32, float64),
-    UNARY_SAFE_NULL_IF_NULL(exp, uint64, float64),
-    UNARY_SAFE_NULL_IF_NULL(exp, float32, float64),
-    UNARY_SAFE_NULL_IF_NULL(exp, float64, float64),
-
-    UNARY_SAFE_NULL_IF_NULL(log, int32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log, int64, float64),
-    UNARY_SAFE_NULL_IF_NULL(log, uint32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log, uint64, float64),
-    UNARY_SAFE_NULL_IF_NULL(log, float32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log, float64, float64),
-
-    UNARY_SAFE_NULL_IF_NULL(log10, int32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log10, int64, float64),
-    UNARY_SAFE_NULL_IF_NULL(log10, uint32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log10, uint64, float64),
-    UNARY_SAFE_NULL_IF_NULL(log10, float32, float64),
-    UNARY_SAFE_NULL_IF_NULL(log10, float64, float64),
-
-    BINARY_UNSAFE_NULL_IF_NULL(log, int32, float64),
-    BINARY_UNSAFE_NULL_IF_NULL(log, int64, float64),
-    BINARY_UNSAFE_NULL_IF_NULL(log, uint32, float64),
-    BINARY_UNSAFE_NULL_IF_NULL(log, uint64, float64),
-    BINARY_UNSAFE_NULL_IF_NULL(log, float32, float64),
-    BINARY_UNSAFE_NULL_IF_NULL(log, float64, float64),
-
-    BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(power, float64),
-
-    // nullable never operations
-    NUMERIC_BOOL_DATE_TYPES(UNARY_SAFE_NULL_NEVER_BOOL, isnull),
-    NUMERIC_BOOL_DATE_TYPES(UNARY_SAFE_NULL_NEVER_BOOL, isnotnull),
-    NUMERIC_TYPES(UNARY_SAFE_NULL_NEVER_BOOL, isnumeric),
-
-    // nullable never binary operations
-    NUMERIC_BOOL_DATE_TYPES(BINARY_SAFE_NULL_NEVER_BOOL, is_distinct_from),
-    NUMERIC_BOOL_DATE_TYPES(BINARY_SAFE_NULL_NEVER_BOOL, is_not_distinct_from),
-
-    // date/timestamp operations
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractMillennium),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractCentury),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDecade),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractYear),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDoy),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractQuarter),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractMonth),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractWeek),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDow),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDay),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractHour),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractMinute),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractSecond),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractEpoch),
-
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(months_between, date64, date64, float64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(months_between, timestamp, timestamp, 
float64),
-
-    // date_trunc operations on date/timestamp
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Millennium),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Century),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Decade),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Year),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Quarter),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Month),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Week),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Day),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Hour),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Minute),
-    DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, date_trunc_Second),
-
-    // time operations
-    TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractHour),
-    TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractMinute),
-    TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractSecond),
-
-    // timestamp diff operations
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffSecond, timestamp, 
timestamp, int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffMinute, timestamp, 
timestamp, int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffHour, timestamp, timestamp, 
int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffDay, timestamp, timestamp, 
int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffWeek, timestamp, timestamp, 
int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffMonth, timestamp, timestamp, 
int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffQuarter, timestamp, 
timestamp, int32),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampdiffYear, timestamp, timestamp, 
int32),
-
-    // timestamp add int32 operations
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddSecond, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMinute, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddHour, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddDay, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddWeek, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMonth, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddQuarter, timestamp, int32, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddYear, timestamp, int32, 
timestamp),
-    // date add int32 operations
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddSecond, date64, int32, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMinute, date64, int32, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddHour, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddDay, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddWeek, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMonth, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddQuarter, date64, int32, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddYear, date64, int32, date64),
-
-    // timestamp add int64 operations
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddSecond, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMinute, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddHour, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddDay, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddWeek, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMonth, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddQuarter, timestamp, int64, 
timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddYear, timestamp, int64, 
timestamp),
-    // date add int64 operations
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddSecond, date64, int64, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMinute, date64, int64, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddHour, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddDay, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddWeek, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddMonth, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddQuarter, date64, int64, 
date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(timestampaddYear, date64, int64, date64),
-
-    // date_add(date64, int32), date_add(timestamp, int32)
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, timestamp, int32, timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, timestamp, int32, timestamp),
-
-    // date_add(date64, int64), date_add(timestamp, int64)
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, timestamp, int64, timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, timestamp, int64, timestamp),
-
-    // date_add(int32, date64), date_add(int32, timestamp)
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, int32, date64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, int32, date64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, int32, timestamp, timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, int32, timestamp, timestamp),
-
-    // date_add(int64, date64), date_add(int64, timestamp)
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, int64, date64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, int64, date64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_add, int64, timestamp, timestamp),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(add, int64, timestamp, timestamp),
-
-    // date_sub(date64, int32), subtract and date_diff
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_sub, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(subtract, date64, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_diff, date64, int32, date64),
-    // date_sub(timestamp, int32), subtract and date_diff
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_sub, timestamp, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(subtract, timestamp, int32, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_diff, timestamp, int32, date64),
-
-    // date_sub(date64, int64), subtract and date_diff
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_sub, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(subtract, date64, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_diff, date64, int64, date64),
-    // date_sub(timestamp, int64), subtract and date_diff
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_sub, timestamp, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(subtract, timestamp, int64, date64),
-    BINARY_GENERIC_SAFE_NULL_IF_NULL(date_diff, timestamp, int64, date64),
-
-    // hash functions
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SAFE_NULL_NEVER, hash),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SAFE_NULL_NEVER, hash32),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SAFE_NULL_NEVER, hash32AsDouble),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SEED_SAFE_NULL_NEVER, hash32),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SEED_SAFE_NULL_NEVER, 
hash32AsDouble),
-
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SAFE_NULL_NEVER, hash64),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SAFE_NULL_NEVER, hash64AsDouble),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SEED_SAFE_NULL_NEVER, hash64),
-    NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SEED_SAFE_NULL_NEVER, 
hash64AsDouble),
-
-    // utf8/binary operations
-    UNARY_SAFE_NULL_IF_NULL(octet_length, utf8, int32),
-    UNARY_SAFE_NULL_IF_NULL(octet_length, binary, int32),
-    UNARY_SAFE_NULL_IF_NULL(bit_length, utf8, int32),
-    UNARY_SAFE_NULL_IF_NULL(bit_length, binary, int32),
-    UNARY_UNSAFE_NULL_IF_NULL(char_length, utf8, int32),
-    UNARY_UNSAFE_NULL_IF_NULL(length, utf8, int32),
-    UNARY_UNSAFE_NULL_IF_NULL(lengthUtf8, binary, int32),
-
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, equal),
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, not_equal),
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, less_than),
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, less_than_or_equal_to),
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, greater_than),
-    VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, 
greater_than_or_equal_to),
+FunctionRegistry::iterator FunctionRegistry::begin() const {
+  return &(*pc_registry_.begin());
+}
 
-    BINARY_RELATIONAL_SAFE_NULL_IF_NULL(starts_with, utf8),
-    BINARY_RELATIONAL_SAFE_NULL_IF_NULL(ends_with, utf8),
+FunctionRegistry::iterator FunctionRegistry::end() const {
+  return &(*pc_registry_.end());
+}
 
-    NativeFunction("upper", DataTypeVector{utf8()}, utf8(), kResultNullIfNull,
-                   "upper_utf8", NativeFunction::kNeedsContext),
+std::vector<NativeFunction> FunctionRegistry::pc_registry_;
 
-    NativeFunction("like", DataTypeVector{utf8(), utf8()}, boolean(), 
kResultNullIfNull,
-                   "gdv_fn_like_utf8_utf8", 
NativeFunction::kNeedsFunctionHolder),
+SignatureMap FunctionRegistry::pc_registry_map_ = InitPCMap();
 
-    NativeFunction("castDATE", DataTypeVector{utf8()}, date64(), 
kResultNullIfNull,
-                   "castDATE_utf8",
-                   NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors),
+SignatureMap FunctionRegistry::InitPCMap() {
+  SignatureMap map;
 
-    NativeFunction("to_date", DataTypeVector{utf8(), utf8(), int32()}, 
date64(),
-                   kResultNullInternal, "gdv_fn_to_date_utf8_utf8_int32",
-                   NativeFunction::kNeedsContext | 
NativeFunction::kNeedsFunctionHolder |
-                       NativeFunction::kCanReturnErrors),
-};  // namespace gandiva
+  auto v1 = GetArithmeticFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v1.begin(), v1.end());
 
-FunctionRegistry::iterator FunctionRegistry::begin() const {
-  return std::begin(pc_registry_);
-}
+  auto v2 = GetDateTimeFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v2.begin(), v2.end());
 
-FunctionRegistry::iterator FunctionRegistry::end() const {
-  return std::end(pc_registry_);
-}
+  auto v3 = GetHashFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v3.begin(), v3.end());
 
-FunctionRegistry::SignatureMap FunctionRegistry::pc_registry_map_ = 
InitPCMap();
+  auto v4 = GetMathOpsFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v4.begin(), v4.end());
 
-FunctionRegistry::SignatureMap FunctionRegistry::InitPCMap() {
-  SignatureMap map;
+  auto v5 = GetStringFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v5.begin(), v5.end());
 
-  int num_entries = static_cast<int>(sizeof(pc_registry_) / 
sizeof(NativeFunction));
-  for (int i = 0; i < num_entries; i++) {
-    const NativeFunction* entry = &pc_registry_[i];
+  auto v6 = GetDateTimeArithmeticFunctionRegistry();
+  pc_registry_.insert(std::end(pc_registry_), v6.begin(), v6.end());
 
-    DCHECK(map.find(&entry->signature()) == map.end());
-    map[&entry->signature()] = entry;
-    // printf("%s -> %s\n", entry->signature().ToString().c_str(),
-    //      entry->pc_name().c_str());
+  for (auto& elem : pc_registry_) {
+    map.insert(std::make_pair(&(elem.signature()), &elem));
   }
+
   return map;
 }
 
diff --git a/cpp/src/gandiva/function_registry.h 
b/cpp/src/gandiva/function_registry.h
index 0f74089..810bf2d 100644
--- a/cpp/src/gandiva/function_registry.h
+++ b/cpp/src/gandiva/function_registry.h
@@ -18,8 +18,8 @@
 #ifndef GANDIVA_FUNCTION_REGISTRY_H
 #define GANDIVA_FUNCTION_REGISTRY_H
 
-#include <unordered_map>
-
+#include <vector>
+#include "gandiva/function_registry_common.h"
 #include "gandiva/gandiva_aliases.h"
 #include "gandiva/native_function.h"
 
@@ -37,28 +37,9 @@ class FunctionRegistry {
   iterator end() const;
 
  private:
-  struct KeyHash {
-    std::size_t operator()(const FunctionSignature* k) const { return 
k->Hash(); }
-  };
-
-  struct KeyEquals {
-    bool operator()(const FunctionSignature* s1, const FunctionSignature* s2) 
const {
-      return *s1 == *s2;
-    }
-  };
-
-  static DataTypePtr time32() { return arrow::time32(arrow::TimeUnit::MILLI); }
-
-  static DataTypePtr time64() { return arrow::time64(arrow::TimeUnit::MICRO); }
-
-  static DataTypePtr timestamp() { return 
arrow::timestamp(arrow::TimeUnit::MILLI); }
-
-  typedef std::unordered_map<const FunctionSignature*, const NativeFunction*, 
KeyHash,
-                             KeyEquals>
-      SignatureMap;
   static SignatureMap InitPCMap();
 
-  static NativeFunction pc_registry_[];
+  static std::vector<NativeFunction> pc_registry_;
   static SignatureMap pc_registry_map_;
 };
 
diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc 
b/cpp/src/gandiva/function_registry_arithmetic.cc
new file mode 100644
index 0000000..800bc49
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_arithmetic.cc
@@ -0,0 +1,78 @@
+// 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.
+
+#include "gandiva/function_registry_arithmetic.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define BINARY_SYMMETRIC_FN(name) 
NUMERIC_TYPES(BINARY_SYMMETRIC_SAFE_NULL_IF_NULL, name)
+
+#define BINARY_RELATIONAL_BOOL_FN(name) \
+  NUMERIC_BOOL_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, name)
+
+#define BINARY_RELATIONAL_BOOL_DATE_FN(name) \
+  NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, name)
+
+#define UNARY_OCTET_LEN_FN(name) \
+  UNARY_SAFE_NULL_IF_NULL(name, utf8, int32), UNARY_SAFE_NULL_IF_NULL(name, 
binary, int32)
+
+#define UNARY_CAST_TO_FLOAT64(name) UNARY_SAFE_NULL_IF_NULL(castFLOAT8, name, 
float64)
+
+#define UNARY_CAST_TO_FLOAT32(name) UNARY_SAFE_NULL_IF_NULL(castFLOAT4, name, 
float32)
+
+std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
+  static std::vector<NativeFunction> arithmetic_fn_registry_ = {
+      UNARY_SAFE_NULL_IF_NULL(not, boolean, boolean),
+      UNARY_SAFE_NULL_IF_NULL(castBIGINT, int32, int64),
+
+      UNARY_CAST_TO_FLOAT32(int32),
+      UNARY_CAST_TO_FLOAT32(int64),
+
+      UNARY_CAST_TO_FLOAT64(int32),
+      UNARY_CAST_TO_FLOAT64(int64),
+      UNARY_CAST_TO_FLOAT64(float32),
+
+      UNARY_SAFE_NULL_IF_NULL(castDATE, int64, date64),
+
+      BINARY_SYMMETRIC_FN(add),
+      BINARY_SYMMETRIC_FN(subtract),
+      BINARY_SYMMETRIC_FN(multiply),
+
+      NUMERIC_TYPES(BINARY_SYMMETRIC_UNSAFE_NULL_IF_NULL, divide),
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(mod, int64, int32, int32),
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(mod, int64, int64, int64),
+
+      BINARY_RELATIONAL_BOOL_FN(equal),
+      BINARY_RELATIONAL_BOOL_FN(not_equal),
+
+      BINARY_RELATIONAL_BOOL_DATE_FN(less_than),
+      BINARY_RELATIONAL_BOOL_DATE_FN(less_than_or_equal_to),
+      BINARY_RELATIONAL_BOOL_DATE_FN(greater_than),
+      BINARY_RELATIONAL_BOOL_DATE_FN(greater_than_or_equal_to),
+
+      UNARY_OCTET_LEN_FN(octet_length),
+      UNARY_OCTET_LEN_FN(bit_length),
+
+      UNARY_UNSAFE_NULL_IF_NULL(char_length, utf8, int32),
+      UNARY_UNSAFE_NULL_IF_NULL(length, utf8, int32),
+      UNARY_UNSAFE_NULL_IF_NULL(lengthUtf8, binary, int32)};
+
+  return arithmetic_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_arithmetic.h 
b/cpp/src/gandiva/function_registry_arithmetic.h
new file mode 100644
index 0000000..e98a4e7
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_arithmetic.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_ARITHMETIC_H
+#define GANDIVA_FUNCTION_REGISTRY_ARITHMETIC_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetArithmeticFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_ARITHMETIC_H
diff --git a/cpp/src/gandiva/function_registry_common.h 
b/cpp/src/gandiva/function_registry_common.h
new file mode 100644
index 0000000..78babce
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_common.h
@@ -0,0 +1,218 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_COMMON_H
+#define GANDIVA_FUNCTION_REGISTRY_COMMON_H
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "gandiva/arrow.h"
+#include "gandiva/function_signature.h"
+#include "gandiva/gandiva_aliases.h"
+#include "gandiva/native_function.h"
+
+/* This is a private file, intended for internal use by gandiva & must not be 
included
+ * directly.
+ */
+namespace gandiva {
+
+using arrow::binary;
+using arrow::boolean;
+using arrow::date64;
+using arrow::float32;
+using arrow::float64;
+using arrow::int16;
+using arrow::int32;
+using arrow::int64;
+using arrow::int8;
+using arrow::uint16;
+using arrow::uint32;
+using arrow::uint64;
+using arrow::uint8;
+using arrow::utf8;
+using std::vector;
+
+inline DataTypePtr time32() { return arrow::time32(arrow::TimeUnit::MILLI); }
+
+inline DataTypePtr time64() { return arrow::time64(arrow::TimeUnit::MICRO); }
+
+inline DataTypePtr timestamp() { return 
arrow::timestamp(arrow::TimeUnit::MILLI); }
+
+struct KeyHash {
+  std::size_t operator()(const FunctionSignature* k) const { return k->Hash(); 
}
+};
+
+struct KeyEquals {
+  bool operator()(const FunctionSignature* s1, const FunctionSignature* s2) 
const {
+    return *s1 == *s2;
+  }
+};
+
+typedef std::unordered_map<const FunctionSignature*, const NativeFunction*, 
KeyHash,
+                           KeyEquals>
+    SignatureMap;
+
+// Binary functions that :
+// - have the same input type for both params
+// - output type is same as the input type
+// - NULL handling is of type NULL_IF_NULL
+//
+// The pre-compiled fn name includes the base name & input type names. eg. 
add_int32_int32
+#define BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(NAME, TYPE)                         
    \
+  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, TYPE(), 
kResultNullIfNull, \
+                 ARROW_STRINGIFY(NAME##_##TYPE##_##TYPE))
+
+// Binary functions that :
+// - have the same input type for both params
+// - NULL handling is of type NULL_IINTERNAL
+// - can return error.
+//
+// The pre-compiled fn name includes the base name & input type names. eg. 
add_int32_int32
+#define BINARY_UNSAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                    
    \
+  NativeFunction(#NAME, DataTypeVector{IN_TYPE(), IN_TYPE()}, OUT_TYPE(),      
    \
+                 kResultNullIfNull, 
ARROW_STRINGIFY(NAME##_##IN_TYPE##_##IN_TYPE), \
+                 NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors)
+
+#define BINARY_SYMMETRIC_UNSAFE_NULL_IF_NULL(NAME, TYPE) \
+  BINARY_UNSAFE_NULL_IF_NULL(NAME, TYPE, TYPE)
+
+// Binary functions that :
+// - have different input types, or output type
+// - NULL handling is of type NULL_IF_NULL
+//
+// The pre-compiled fn name includes the base name & input type names. eg. 
mod_int64_int32
+#define BINARY_GENERIC_SAFE_NULL_IF_NULL(NAME, IN_TYPE1, IN_TYPE2, OUT_TYPE) \
+  NativeFunction(#NAME, DataTypeVector{IN_TYPE1(), IN_TYPE2()}, OUT_TYPE(),  \
+                 kResultNullIfNull, 
ARROW_STRINGIFY(NAME##_##IN_TYPE1##_##IN_TYPE2))
+
+// Binary functions that :
+// - have the same input type
+// - output type is boolean
+// - NULL handling is of type NULL_IF_NULL
+//
+// The pre-compiled fn name includes the base name & input type names.
+// eg. equal_int32_int32
+#define BINARY_RELATIONAL_SAFE_NULL_IF_NULL(NAME, TYPE)                        
       \
+  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, boolean(), 
kResultNullIfNull, \
+                 ARROW_STRINGIFY(NAME##_##TYPE##_##TYPE))
+
+// Unary functions that :
+// - NULL handling is of type NULL_IF_NULL
+//
+// The pre-compiled fn name includes the base name & input type name. eg. 
castFloat_int32
+#define UNARY_SAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                       
   \
+  NativeFunction(#NAME, DataTypeVector{IN_TYPE()}, OUT_TYPE(), 
kResultNullIfNull, \
+                 ARROW_STRINGIFY(NAME##_##IN_TYPE))
+
+// Unary functions that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type name. eg. 
isnull_int32
+#define UNARY_SAFE_NULL_NEVER_BOOL(NAME, TYPE)                               \
+  NativeFunction(#NAME, DataTypeVector{TYPE()}, boolean(), kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##_##TYPE))
+
+// Unary functions that :
+// - NULL handling is of type NULL_INTERNAL
+//
+// The pre-compiled fn name includes the base name & input type name. eg. 
castFloat_int32
+#define UNARY_UNSAFE_NULL_IF_NULL(NAME, IN_TYPE, OUT_TYPE)                     
   \
+  NativeFunction(#NAME, DataTypeVector{IN_TYPE()}, OUT_TYPE(), 
kResultNullIfNull, \
+                 ARROW_STRINGIFY(NAME##_##IN_TYPE),                            
   \
+                 NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors)
+
+// Binary functions that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type names,
+// eg. is_distinct_from_int32_int32
+#define BINARY_SAFE_NULL_NEVER_BOOL(NAME, TYPE)                                
      \
+  NativeFunction(#NAME, DataTypeVector{TYPE(), TYPE()}, boolean(), 
kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##_##TYPE##_##TYPE))
+
+// Extract functions (used with data/time types) that :
+// - NULL handling is of type NULL_IF_NULL
+//
+// The pre-compiled fn name includes the base name & input type name. eg. 
extractYear_date
+#define EXTRACT_SAFE_NULL_IF_NULL(NAME, TYPE)                               \
+  NativeFunction(#NAME, DataTypeVector{TYPE()}, int64(), kResultNullIfNull, \
+                 ARROW_STRINGIFY(NAME##_##TYPE))
+
+// Hash32 functions that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type name. 
hash32_int8
+#define HASH32_SAFE_NULL_NEVER(NAME, TYPE)                                 \
+  NativeFunction(#NAME, DataTypeVector{TYPE()}, int32(), kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##_##TYPE))
+
+// Hash32 functions that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type name. 
hash32_int8
+#define HASH64_SAFE_NULL_NEVER(NAME, TYPE)                                 \
+  NativeFunction(#NAME, DataTypeVector{TYPE()}, int64(), kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##_##TYPE))
+
+// Hash32 functions with seed that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type name. 
hash32WithSeed_int8
+#define HASH32_SEED_SAFE_NULL_NEVER(NAME, TYPE)                                
     \
+  NativeFunction(#NAME, DataTypeVector{TYPE(), int32()}, int32(), 
kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##WithSeed_##TYPE))
+
+// Hash64 functions with seed that :
+// - NULL handling is of type NULL_NEVER
+//
+// The pre-compiled fn name includes the base name & input type name. 
hash32WithSeed_int8
+#define HASH64_SEED_SAFE_NULL_NEVER(NAME, TYPE)                                
     \
+  NativeFunction(#NAME, DataTypeVector{TYPE(), int64()}, int64(), 
kResultNullNever, \
+                 ARROW_STRINGIFY(NAME##WithSeed_##TYPE))
+
+// Iterate the inner macro over all numeric types
+#define NUMERIC_TYPES(INNER, NAME)                                             
          \
+  INNER(NAME, int8), INNER(NAME, int16), INNER(NAME, int32), INNER(NAME, 
int64),         \
+      INNER(NAME, uint8), INNER(NAME, uint16), INNER(NAME, uint32), 
INNER(NAME, uint64), \
+      INNER(NAME, float32), INNER(NAME, float64)
+
+// Iterate the inner macro over numeric and date/time types
+#define NUMERIC_DATE_TYPES(INNER, NAME) \
+  NUMERIC_TYPES(INNER, NAME), DATE_TYPES(INNER, NAME), TIME_TYPES(INNER, NAME)
+
+// Iterate the inner macro over all date types
+#define DATE_TYPES(INNER, NAME) INNER(NAME, date64), INNER(NAME, timestamp)
+
+// Iterate the inner macro over all time types
+#define TIME_TYPES(INNER, NAME) INNER(NAME, time32)
+
+// Iterate the inner macro over all data types
+#define VAR_LEN_TYPES(INNER, NAME) INNER(NAME, utf8), INNER(NAME, binary)
+
+// Iterate the inner macro over all numeric types, date types and bool type
+#define NUMERIC_BOOL_DATE_TYPES(INNER, NAME) \
+  NUMERIC_DATE_TYPES(INNER, NAME), INNER(NAME, boolean)
+
+// Iterate the inner macro over all numeric types, date types, bool and varlen 
types
+#define NUMERIC_BOOL_DATE_VAR_LEN_TYPES(INNER, NAME) \
+  NUMERIC_BOOL_DATE_TYPES(INNER, NAME), VAR_LEN_TYPES(INNER, NAME)
+
+}  // namespace gandiva
+
+#endif
diff --git a/cpp/src/gandiva/function_registry_datetime.cc 
b/cpp/src/gandiva/function_registry_datetime.cc
new file mode 100644
index 0000000..145b7d3
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_datetime.cc
@@ -0,0 +1,65 @@
+// 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.
+
+#include "gandiva/function_registry_datetime.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define DATE_EXTRACTION_FNS(name)                           \
+  DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Millennium),  \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Century), \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Decade),  \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Year),    \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Quarter), \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Month),   \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Week),    \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Day),     \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Hour),    \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Minute),  \
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Second)
+
+#define TIME_EXTRACTION_FNS(name)                          \
+  TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Hour),       \
+      TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Minute), \
+      TIME_TYPES(EXTRACT_SAFE_NULL_IF_NULL, name##Second)
+
+std::vector<NativeFunction> GetDateTimeFunctionRegistry() {
+  static std::vector<NativeFunction> date_time_fn_registry_ = {
+      DATE_EXTRACTION_FNS(extract),
+      DATE_EXTRACTION_FNS(date_trunc_),
+
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDoy),
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractDow),
+      DATE_TYPES(EXTRACT_SAFE_NULL_IF_NULL, extractEpoch),
+
+      TIME_EXTRACTION_FNS(extract),
+
+      NativeFunction("castDATE", DataTypeVector{utf8()}, date64(), 
kResultNullIfNull,
+                     "castDATE_utf8",
+                     NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors),
+
+      NativeFunction("to_date", DataTypeVector{utf8(), utf8(), int32()}, 
date64(),
+                     kResultNullInternal, "gdv_fn_to_date_utf8_utf8_int32",
+                     NativeFunction::kNeedsContext |
+                         NativeFunction::kNeedsFunctionHolder |
+                         NativeFunction::kCanReturnErrors)};
+
+  return date_time_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_datetime.h 
b/cpp/src/gandiva/function_registry_datetime.h
new file mode 100644
index 0000000..c9b8894
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_datetime.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_DATE_TIME_H
+#define GANDIVA_FUNCTION_REGISTRY_DATE_TIME_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetDateTimeFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_DATE_TIME_H
diff --git a/cpp/src/gandiva/function_registry_hash.cc 
b/cpp/src/gandiva/function_registry_hash.cc
new file mode 100644
index 0000000..a163a23
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_hash.cc
@@ -0,0 +1,53 @@
+// 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.
+
+#include "gandiva/function_registry_hash.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define HASH32_SAFE_NULL_NEVER_FN(name) \
+  NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SAFE_NULL_NEVER, name)
+
+#define HASH32_SEED_SAFE_NULL_NEVER_FN(name) \
+  NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH32_SEED_SAFE_NULL_NEVER, name)
+
+#define HASH64_SAFE_NULL_NEVER_FN(name) \
+  NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SAFE_NULL_NEVER, name)
+
+#define HASH64_SEED_SAFE_NULL_NEVER_FN(name) \
+  NUMERIC_BOOL_DATE_VAR_LEN_TYPES(HASH64_SEED_SAFE_NULL_NEVER, name)
+
+std::vector<NativeFunction> GetHashFunctionRegistry() {
+  static std::vector<NativeFunction> hash_fn_registry_ = {
+      HASH32_SAFE_NULL_NEVER_FN(hash),
+      HASH32_SAFE_NULL_NEVER_FN(hash32),
+      HASH32_SAFE_NULL_NEVER_FN(hash32AsDouble),
+
+      HASH32_SEED_SAFE_NULL_NEVER_FN(hash32),
+      HASH32_SEED_SAFE_NULL_NEVER_FN(hash32AsDouble),
+
+      HASH64_SAFE_NULL_NEVER_FN(hash64),
+      HASH64_SAFE_NULL_NEVER_FN(hash64AsDouble),
+
+      HASH64_SEED_SAFE_NULL_NEVER_FN(hash64),
+      HASH64_SEED_SAFE_NULL_NEVER_FN(hash64AsDouble)};
+
+  return hash_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_hash.h 
b/cpp/src/gandiva/function_registry_hash.h
new file mode 100644
index 0000000..dc02cb2
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_hash.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_HASH_H
+#define GANDIVA_FUNCTION_REGISTRY_HASH_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetHashFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_HASH_H
diff --git a/cpp/src/gandiva/function_registry_math_ops.cc 
b/cpp/src/gandiva/function_registry_math_ops.cc
new file mode 100644
index 0000000..31b4b13
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_math_ops.cc
@@ -0,0 +1,67 @@
+// 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.
+
+#include "gandiva/function_registry_math_ops.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define MATH_UNARY_OPS(name)                           \
+  UNARY_SAFE_NULL_IF_NULL(name, int32, float64),       \
+      UNARY_SAFE_NULL_IF_NULL(name, int64, float64),   \
+      UNARY_SAFE_NULL_IF_NULL(name, uint32, float64),  \
+      UNARY_SAFE_NULL_IF_NULL(name, uint64, float64),  \
+      UNARY_SAFE_NULL_IF_NULL(name, float32, float64), \
+      UNARY_SAFE_NULL_IF_NULL(name, float64, float64)
+
+#define MATH_BINARY_UNSAFE(name)                          \
+  BINARY_UNSAFE_NULL_IF_NULL(name, int32, float64),       \
+      BINARY_UNSAFE_NULL_IF_NULL(name, int64, float64),   \
+      BINARY_UNSAFE_NULL_IF_NULL(name, uint32, float64),  \
+      BINARY_UNSAFE_NULL_IF_NULL(name, uint64, float64),  \
+      BINARY_UNSAFE_NULL_IF_NULL(name, float32, float64), \
+      BINARY_UNSAFE_NULL_IF_NULL(name, float64, float64)
+
+#define UNARY_SAFE_NULL_NEVER_BOOL_FN(name) \
+  NUMERIC_BOOL_DATE_TYPES(UNARY_SAFE_NULL_NEVER_BOOL, name)
+
+#define BINARY_SAFE_NULL_NEVER_BOOL_FN(name) \
+  NUMERIC_BOOL_DATE_TYPES(BINARY_SAFE_NULL_NEVER_BOOL, name)
+
+std::vector<NativeFunction> GetMathOpsFunctionRegistry() {
+  static std::vector<NativeFunction> math_fn_registry_ = {
+      MATH_UNARY_OPS(cbrt),
+      MATH_UNARY_OPS(exp),
+      MATH_UNARY_OPS(log),
+      MATH_UNARY_OPS(log10),
+
+      MATH_BINARY_UNSAFE(log),
+
+      BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(power, float64),
+
+      UNARY_SAFE_NULL_NEVER_BOOL_FN(isnull),
+      UNARY_SAFE_NULL_NEVER_BOOL_FN(isnotnull),
+
+      NUMERIC_TYPES(UNARY_SAFE_NULL_NEVER_BOOL, isnumeric),
+
+      BINARY_SAFE_NULL_NEVER_BOOL_FN(is_distinct_from),
+      BINARY_SAFE_NULL_NEVER_BOOL_FN(is_not_distinct_from)};
+
+  return math_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_math_ops.h 
b/cpp/src/gandiva/function_registry_math_ops.h
new file mode 100644
index 0000000..0204ffc
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_math_ops.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_MATHOPS_H
+#define GANDIVA_FUNCTION_REGISTRY_MATHOPS_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetMathOpsFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_MATHOPS_H
diff --git a/cpp/src/gandiva/function_registry_string.cc 
b/cpp/src/gandiva/function_registry_string.cc
new file mode 100644
index 0000000..c97925a
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_string.cc
@@ -0,0 +1,50 @@
+// 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.
+
+#include "gandiva/function_registry_string.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(name) \
+  VAR_LEN_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, name)
+
+#define BINARY_RELATIONAL_SAFE_NULL_IF_NULL_UTF8_FN(name) \
+  BINARY_RELATIONAL_SAFE_NULL_IF_NULL(name, utf8)
+
+std::vector<NativeFunction> GetStringFunctionRegistry() {
+  static std::vector<NativeFunction> string_fn_registry_ = {
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(equal),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(not_equal),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(less_than),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(less_than_or_equal_to),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(greater_than),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_FN(greater_than_or_equal_to),
+
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_UTF8_FN(starts_with),
+      BINARY_RELATIONAL_SAFE_NULL_IF_NULL_UTF8_FN(ends_with),
+
+      NativeFunction("upper", DataTypeVector{utf8()}, utf8(), 
kResultNullIfNull,
+                     "upper_utf8", NativeFunction::kNeedsContext),
+
+      NativeFunction("like", DataTypeVector{utf8(), utf8()}, boolean(), 
kResultNullIfNull,
+                     "gdv_fn_like_utf8_utf8", 
NativeFunction::kNeedsFunctionHolder)};
+
+  return string_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_string.h 
b/cpp/src/gandiva/function_registry_string.h
new file mode 100644
index 0000000..c921789
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_string.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_STRING_H
+#define GANDIVA_FUNCTION_REGISTRY_STRING_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetStringFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_STRING_H
diff --git a/cpp/src/gandiva/function_registry_timestamp_arithmetic.cc 
b/cpp/src/gandiva/function_registry_timestamp_arithmetic.cc
new file mode 100644
index 0000000..7af7690
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_timestamp_arithmetic.cc
@@ -0,0 +1,81 @@
+// 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.
+
+#include "gandiva/function_registry_timestamp_arithmetic.h"
+#include "gandiva/function_registry_common.h"
+
+namespace gandiva {
+
+#define TIMESTAMP_ADD_FNS(name)                                            \
+  BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int32, timestamp),     \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int32, date64),       \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int64, timestamp), \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int64, date64)
+
+#define TIMESTAMP_DIFF_FN(name) \
+  BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, timestamp, int32)
+
+#define DATE_ADD_FNS(name)                                                 \
+  BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int32, date64),           \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int32, timestamp), \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int64, date64),       \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int64, timestamp), \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, int32, date64, date64),       \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, int32, timestamp, timestamp), \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, int64, date64, date64),       \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, int64, timestamp, timestamp)
+
+#define DATE_DIFF_FNS(name)                                             \
+  BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int32, date64),        \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int32, date64), \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, date64, int64, date64),    \
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(name, timestamp, int64, date64)
+
+std::vector<NativeFunction> GetDateTimeArithmeticFunctionRegistry() {
+  static std::vector<NativeFunction> datetime_fn_registry_ = {
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(months_between, date64, date64, 
float64),
+      BINARY_GENERIC_SAFE_NULL_IF_NULL(months_between, timestamp, timestamp, 
float64),
+
+      TIMESTAMP_DIFF_FN(timestampdiffSecond),
+      TIMESTAMP_DIFF_FN(timestampdiffMinute),
+      TIMESTAMP_DIFF_FN(timestampdiffHour),
+      TIMESTAMP_DIFF_FN(timestampdiffDay),
+      TIMESTAMP_DIFF_FN(timestampdiffWeek),
+      TIMESTAMP_DIFF_FN(timestampdiffMonth),
+      TIMESTAMP_DIFF_FN(timestampdiffQuarter),
+      TIMESTAMP_DIFF_FN(timestampdiffYear),
+
+      TIMESTAMP_ADD_FNS(timestampaddSecond),
+      TIMESTAMP_ADD_FNS(timestampaddMinute),
+      TIMESTAMP_ADD_FNS(timestampaddHour),
+      TIMESTAMP_ADD_FNS(timestampaddDay),
+      TIMESTAMP_ADD_FNS(timestampaddWeek),
+      TIMESTAMP_ADD_FNS(timestampaddMonth),
+      TIMESTAMP_ADD_FNS(timestampaddQuarter),
+      TIMESTAMP_ADD_FNS(timestampaddYear),
+
+      DATE_ADD_FNS(date_add),
+      DATE_ADD_FNS(add),
+
+      DATE_DIFF_FNS(date_sub),
+      DATE_DIFF_FNS(subtract),
+      DATE_DIFF_FNS(date_diff)};
+
+  return datetime_fn_registry_;
+}
+
+}  // namespace gandiva
diff --git a/cpp/src/gandiva/function_registry_timestamp_arithmetic.h 
b/cpp/src/gandiva/function_registry_timestamp_arithmetic.h
new file mode 100644
index 0000000..f1b9709
--- /dev/null
+++ b/cpp/src/gandiva/function_registry_timestamp_arithmetic.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef GANDIVA_FUNCTION_REGISTRY_TIMESTAMP_ARITHMETIC_H
+#define GANDIVA_FUNCTION_REGISTRY_TIMESTAMP_ARITHMETIC_H
+
+#include <vector>
+#include "gandiva/native_function.h"
+
+namespace gandiva {
+
+std::vector<NativeFunction> GetDateTimeArithmeticFunctionRegistry();
+
+}  // namespace gandiva
+
+#endif  // GANDIVA_FUNCTION_REGISTRY_TIMESTAMP_ARITHMETIC_H
diff --git a/cpp/src/gandiva/native_function.h 
b/cpp/src/gandiva/native_function.h
index 7a250e0..5b130a9 100644
--- a/cpp/src/gandiva/native_function.h
+++ b/cpp/src/gandiva/native_function.h
@@ -52,7 +52,6 @@ class NativeFunction {
   bool NeedsFunctionHolder() const { return (flags_ & kNeedsFunctionHolder) != 
0; }
   bool CanReturnErrors() const { return (flags_ & kCanReturnErrors) != 0; }
 
- private:
   NativeFunction(const std::string& base_name, const DataTypeVector& 
param_types,
                  DataTypePtr ret_type, const ResultNullableType& 
result_nullable_type,
                  const std::string& pc_name, int32_t flags = 0)
@@ -61,6 +60,7 @@ class NativeFunction {
         result_nullable_type_(result_nullable_type),
         pc_name_(pc_name) {}
 
+ private:
   FunctionSignature signature_;
 
   /// attributes
@@ -69,8 +69,6 @@ class NativeFunction {
 
   /// pre-compiled function name.
   std::string pc_name_;
-
-  friend class FunctionRegistry;
 };
 
 }  // end namespace gandiva

Reply via email to