Skip to content

Commit

Permalink
Merge pull request #957 from finos/computed-comparators
Browse files Browse the repository at this point in the history
Add ==, !=, >, <, and string equality computed columns
  • Loading branch information
texodus authored Mar 6, 2020
2 parents bfbaade + 558b192 commit e23988b
Show file tree
Hide file tree
Showing 9 changed files with 663 additions and 5 deletions.
30 changes: 30 additions & 0 deletions cpp/perspective/src/cpp/computed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ t_computed_column::get_computed_function_1(t_computation computation) {
case MULTIPLY: return computed_function::multiply<DTYPE>; \
case DIVIDE: return computed_function::divide<DTYPE>; \
case PERCENT_A_OF_B: return computed_function::percent_of<DTYPE>; \
case EQUALS: return computed_function::equals<DTYPE>; \
case NOT_EQUALS: return computed_function::not_equals<DTYPE>; \
case GREATER_THAN: return computed_function::greater_than<DTYPE>; \
case LESS_THAN: return computed_function::less_than<DTYPE>; \
default: break; \
}

Expand Down Expand Up @@ -152,6 +156,12 @@ t_computed_column::get_computed_function_2(t_computation computation) {
case DTYPE_FLOAT64: {
GET_COMPUTED_FUNCTION_2(DTYPE_FLOAT64);
} break;
case DTYPE_STR: {
switch (computation.m_name) {
case IS: return computed_function::is;
default: break;
}
}
default: break;
}

Expand Down Expand Up @@ -305,6 +315,7 @@ void t_computed_column::make_computations() {
std::vector<t_dtype> dtypes = {DTYPE_FLOAT64, DTYPE_FLOAT32, DTYPE_INT64, DTYPE_INT32, DTYPE_INT16, DTYPE_INT8, DTYPE_UINT64, DTYPE_UINT32, DTYPE_UINT16, DTYPE_UINT8};
std::vector<t_computed_function_name> numeric_function_1 = {INVERT, POW, SQRT, ABS, BUCKET_10, BUCKET_100, BUCKET_1000, BUCKET_0_1, BUCKET_0_0_1, BUCKET_0_0_0_1};
std::vector<t_computed_function_name> numeric_function_2 = {ADD, SUBTRACT, MULTIPLY, DIVIDE, PERCENT_A_OF_B};
std::vector<t_computed_function_name> numeric_comparison_2 = {EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN};

for (const auto f : numeric_function_1) {
for (auto i = 0; i < dtypes.size(); ++i) {
Expand Down Expand Up @@ -332,6 +343,20 @@ void t_computed_column::make_computations() {
}
}

for (const auto f : numeric_comparison_2) {
for (auto i = 0; i < dtypes.size(); ++i) {
for (auto j = 0; j < dtypes.size(); ++j) {
t_computed_column::computations.push_back(
t_computation{
f,
std::vector<t_dtype>{dtypes[i], dtypes[j]},
DTYPE_BOOL
}
);
}
}
}

// Generate string functions
std::vector<t_computed_function_name> string_function_1 = {UPPERCASE, LOWERCASE};
std::vector<t_computed_function_name> string_function_2 = {CONCAT_SPACE, CONCAT_COMMA};
Expand Down Expand Up @@ -361,6 +386,11 @@ void t_computed_column::make_computations() {
t_computation{LENGTH, std::vector<t_dtype>{DTYPE_STR}, DTYPE_INT64}
);

// IS takes 2 strings and returns a bool
t_computed_column::computations.push_back(
t_computation{IS, std::vector<t_dtype>{DTYPE_STR, DTYPE_STR}, DTYPE_BOOL}
);

// Generate date/datetime functions
std::vector<t_dtype> date_dtypes = {DTYPE_DATE, DTYPE_TIME};

Expand Down
69 changes: 69 additions & 0 deletions cpp/perspective/src/cpp/computed_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,62 @@ NUMERIC_FUNCTION_1(BUCKET_0_0_0_1);
return rval; \
}

#define EQUALS(T1, T2) \
t_tscalar equals_##T1##_##T2(t_tscalar x, t_tscalar y) { \
t_tscalar rval; \
rval.set(false); \
if ((x.is_none() || !x.is_valid()) \
&& (y.is_none() || !y.is_valid())) { \
rval.set(true); \
return rval; \
} else if ((x.is_none() || !x.is_valid()) \
|| (y.is_none() || !y.is_valid())) { \
rval.set(false); \
return rval; \
} \
rval.set(static_cast<bool>(x.get<T1>() == y.get<T2>())); \
return rval; \
}

#define NOT_EQUALS(T1, T2) \
t_tscalar not_equals_##T1##_##T2(t_tscalar x, t_tscalar y) { \
t_tscalar rval; \
rval.set(false); \
if ((x.is_none() || !x.is_valid()) \
|| (y.is_none() || !y.is_valid())) return rval; \
rval.set(static_cast<bool>(x.get<T1>() != y.get<T2>())); \
return rval; \
}

#define GREATER_THAN(T1, T2) \
t_tscalar greater_than_##T1##_##T2(t_tscalar x, t_tscalar y) { \
t_tscalar rval; \
rval.set(false); \
if ((x.is_none() || !x.is_valid()) \
|| (y.is_none() || !y.is_valid())) return rval; \
rval.set(static_cast<bool>(x.get<T1>() > y.get<T2>())); \
return rval; \
}

#define LESS_THAN(T1, T2) \
t_tscalar less_than_##T1##_##T2(t_tscalar x, t_tscalar y) { \
t_tscalar rval; \
rval.set(false); \
if ((x.is_none() || !x.is_valid()) \
|| (y.is_none() || !y.is_valid())) return rval; \
rval.set(static_cast<bool>(x.get<T1>() < y.get<T2>())); \
return rval; \
}

NUMERIC_FUNCTION_2(ADD);
NUMERIC_FUNCTION_2(SUBTRACT);
NUMERIC_FUNCTION_2(MULTIPLY);
NUMERIC_FUNCTION_2(DIVIDE);
NUMERIC_FUNCTION_2(PERCENT_OF);
NUMERIC_FUNCTION_2(EQUALS);
NUMERIC_FUNCTION_2(NOT_EQUALS);
NUMERIC_FUNCTION_2(GREATER_THAN);
NUMERIC_FUNCTION_2(LESS_THAN);

/**
* @brief Generate dispatch functions that call the correct computation method
Expand Down Expand Up @@ -351,6 +402,10 @@ NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(subtract);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(multiply);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(divide);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(percent_of);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(equals);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(not_equals);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(greater_than);
NUMERIC_FUNCTION_2_DISPATCH_ALL_TYPES(less_than);

// String functions
t_tscalar length(t_tscalar x) {
Expand All @@ -365,6 +420,20 @@ t_tscalar length(t_tscalar x) {
return rval;
}

t_tscalar is(t_tscalar x, t_tscalar y) {
t_tscalar rval;
rval.set(false);

if ((x.is_none() || !x.is_valid() || x.get_dtype() != DTYPE_STR)
|| (y.is_none() || !y.is_valid() || y.get_dtype() != DTYPE_STR)) {
return rval;
}

bool eq = strcmp(x.get_char_ptr(), y.get_char_ptr()) == 0;
rval.set(eq);
return rval;
}

void uppercase(t_tscalar x, std::int32_t idx, std::shared_ptr<t_column> output_column) {
if (x.is_none() || !x.is_valid() || x.get_dtype() != DTYPE_STR) {
output_column->set_scalar(idx, mknone());
Expand Down
5 changes: 5 additions & 0 deletions cpp/perspective/src/cpp/emscripten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2000,9 +2000,14 @@ EMSCRIPTEN_BINDINGS(perspective) {
.value("SQRT", SQRT)
.value("ABS", ABS)
.value("PERCENT_A_OF_B", PERCENT_A_OF_B)
.value("EQUALS", EQUALS)
.value("NOT_EQUALS", NOT_EQUALS)
.value("GREATER_THAN", GREATER_THAN)
.value("LESS_THAN", LESS_THAN)
.value("UPPERCASE", UPPERCASE)
.value("LOWERCASE", LOWERCASE)
.value("LENGTH", LENGTH)
.value("IS", IS)
.value("CONCAT_SPACE", CONCAT_SPACE)
.value("CONCAT_COMMA", CONCAT_COMMA)
.value("BUCKET_10", BUCKET_10)
Expand Down
14 changes: 10 additions & 4 deletions cpp/perspective/src/include/perspective/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,19 @@ std::is_pod<X>::value && std::is_standard_layout<X>::value , \
#else
#define PSP_VERBOSE_ASSERT1(COND, MSG) \
{ \
if (!(COND)) \
psp_abort("Assertion failed!"); \
if (!(COND)) { \
std::stringstream ss; \
ss << MSG; \
psp_abort(ss.str()); \
} \
}
#define PSP_VERBOSE_ASSERT2(EXPR, COND, MSG) \
{ \
if (!(EXPR COND)) \
psp_abort("Assertion failed!"); \
if (!(EXPR COND)) { \
std::stringstream ss; \
ss << MSG; \
psp_abort(ss.str()); \
} \
}
#define PSP_COMPLAIN_AND_ABORT(X) psp_abort(X);
#define PSP_ASSERT_SIMPLE_TYPE(X)
Expand Down
5 changes: 5 additions & 0 deletions cpp/perspective/src/include/perspective/computed.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ enum t_computed_function_name {
SQRT,
ABS,
PERCENT_A_OF_B,
EQUALS,
NOT_EQUALS,
GREATER_THAN,
LESS_THAN,
UPPERCASE,
LOWERCASE,
LENGTH,
IS,
CONCAT_SPACE,
CONCAT_COMMA,
BUCKET_10,
Expand Down
18 changes: 17 additions & 1 deletion cpp/perspective/src/include/perspective/computed_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ t_tscalar divide(t_tscalar x, t_tscalar y);
template <t_dtype T>
t_tscalar percent_of(t_tscalar x, t_tscalar y);

template <t_dtype T>
t_tscalar equals(t_tscalar x, t_tscalar y);

template <t_dtype T>
t_tscalar not_equals(t_tscalar x, t_tscalar y);

template <t_dtype T>
t_tscalar greater_than(t_tscalar x, t_tscalar y);

template <t_dtype T>
t_tscalar less_than(t_tscalar x, t_tscalar y);

#define NUMERIC_FUNCTION_2_HEADER(NAME) \
template <> t_tscalar NAME<DTYPE_UINT8>(t_tscalar x, t_tscalar y); \
template <> t_tscalar NAME<DTYPE_UINT16>(t_tscalar x, t_tscalar y); \
Expand All @@ -89,10 +101,14 @@ NUMERIC_FUNCTION_2_HEADER(add);
NUMERIC_FUNCTION_2_HEADER(subtract);
NUMERIC_FUNCTION_2_HEADER(multiply);
NUMERIC_FUNCTION_2_HEADER(divide);
NUMERIC_FUNCTION_2_HEADER(percent_of);
NUMERIC_FUNCTION_2_HEADER(equals);
NUMERIC_FUNCTION_2_HEADER(not_equals);
NUMERIC_FUNCTION_2_HEADER(greater_than);
NUMERIC_FUNCTION_2_HEADER(less_than);

// String functions
t_tscalar length(t_tscalar x);
t_tscalar is(t_tscalar x, t_tscalar y);

// Functions that return a string/write into a string column should not return,
// and instead write directly into the output column. This prevents pointers to
Expand Down
45 changes: 45 additions & 0 deletions packages/perspective-viewer/src/js/computed_column.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,42 @@ export const COMPUTATIONS = {
["Math"],
2
),
equals: new Computation(
"==",
(x, y) => `(${x} == ${y})`,
"float",
"float",
(a, b) => a === b,
["Math"],
2
),
not_equals: new Computation(
"!=",
(x, y) => `(${x} != ${y})`,
"float",
"boolean",
(a, b) => a !== b,
["Math"],
2
),
greater_than: new Computation(
">",
(x, y) => `(${x} > ${y})`,
"float",
"boolean",
(a, b) => a > b,
["Math"],
2
),
less_than: new Computation(
"<",
(x, y) => `(${x} < ${y})`,
"float",
"boolean",
(a, b) => a < b,
["Math"],
2
),
uppercase: new Computation(
"Uppercase",
x => `uppercase(${x})`,
Expand All @@ -253,6 +289,15 @@ export const COMPUTATIONS = {
x => x.length,
["Text"]
),
is: new Computation(
"is",
(x, y) => `(${x} is ${y})`,
"string",
"boolean",
(x, y) => x === y,
["Text"],
2
),
concat_space: new Computation(
"concat_space",
x => `concat_space(${x})`,
Expand Down
10 changes: 10 additions & 0 deletions packages/perspective/src/js/perspective.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,22 @@ export default function(Module) {
return __MODULE__.t_computed_function_name.ABS;
case "%":
return __MODULE__.t_computed_function_name.PERCENT_A_OF_B;
case "==":
return __MODULE__.t_computed_function_name.EQUALS;
case "!=":
return __MODULE__.t_computed_function_name.NOT_EQUALS;
case ">":
return __MODULE__.t_computed_function_name.GREATER_THAN;
case "<":
return __MODULE__.t_computed_function_name.LESS_THAN;
case "Uppercase":
return __MODULE__.t_computed_function_name.UPPERCASE;
case "Lowercase":
return __MODULE__.t_computed_function_name.LOWERCASE;
case "length":
return __MODULE__.t_computed_function_name.LENGTH;
case "is":
return __MODULE__.t_computed_function_name.IS;
case "concat_space":
return __MODULE__.t_computed_function_name.CONCAT_SPACE;
case "concat_comma":
Expand Down
Loading

0 comments on commit e23988b

Please sign in to comment.