You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2024/09/12 19:31:02 UTC

(datasketches-bigquery) 01/01: tuple sketch int64

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

alsay pushed a commit to branch tuple_sketch_int64
in repository https://gitbox.apache.org/repos/asf/datasketches-bigquery.git

commit 5206084eceb6b93e616d93fd3544f91e4ce21904
Author: AlexanderSaydakov <Al...@users.noreply.github.com>
AuthorDate: Thu Sep 12 12:30:35 2024 -0700

    tuple sketch int64
---
 tuple/Makefile                                     |  69 +++++++
 tuple/sqlx/tuple_sketch_int64_a_not_b_seed.sqlx    |  40 ++++
 tuple/sqlx/tuple_sketch_int64_agg_string.sqlx      |  36 ++++
 ...le_sketch_int64_agg_string_lgk_seed_p_mode.sqlx | 138 ++++++++++++++
 tuple/sqlx/tuple_sketch_int64_agg_union.sqlx       |  26 +++
 ...tuple_sketch_int64_agg_union_lgk_seed_mode.sqlx | 104 ++++++++++
 .../tuple_sketch_int64_filter_low_high_seed.sqlx   |  35 ++++
 .../tuple_sketch_int64_from_theta_sketch_seed.sqlx |  35 ++++
 tuple/sqlx/tuple_sketch_int64_get_estimate.sqlx    |  26 +++
 .../sqlx/tuple_sketch_int64_get_estimate_seed.sqlx |  39 ++++
 .../tuple_sketch_int64_intersection_seed_mode.sqlx |  42 +++++
 tuple/sqlx/tuple_sketch_int64_to_string.sqlx       |  26 +++
 tuple/sqlx/tuple_sketch_int64_to_string_seed.sqlx  |  39 ++++
 tuple/sqlx/tuple_sketch_int64_union.sqlx           |  26 +++
 .../tuple_sketch_int64_union_lgk_seed_mode.sqlx    |  43 +++++
 tuple/test/tuple_sketch_int_test.sql               |  89 +++++++++
 tuple/tuple_sketch_int64.cpp                       | 210 +++++++++++++++++++++
 17 files changed, 1023 insertions(+)

diff --git a/tuple/Makefile b/tuple/Makefile
new file mode 100644
index 0000000..fcb9dee
--- /dev/null
+++ b/tuple/Makefile
@@ -0,0 +1,69 @@
+# 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.
+
+EMCC=emcc
+EMCFLAGS=-I../datasketches-cpp/common/include \
+	-I../datasketches-cpp/theta/include \
+	-I../datasketches-cpp/tuple/include \
+	--no-entry \
+	-sWASM_BIGINT=1 \
+	-sEXPORTED_FUNCTIONS=[_malloc,_free] \
+	-sENVIRONMENT=shell \
+	-sTOTAL_MEMORY=1024MB \
+	-O3 \
+	--bind
+
+ARTIFACTS=tuple_sketch_int64.mjs tuple_sketch_int64.js tuple_sketch_int64.wasm
+
+all: $(ARTIFACTS)
+
+%.mjs: %.cpp
+	$(EMCC) $< $(EMCFLAGS) -sSINGLE_FILE=1 -o $@
+
+# this rule creates a non-es6 loadable library
+%.js: %.cpp
+	$(EMCC) $< $(EMCFLAGS) -sSINGLE_FILE=1 -o $@
+
+%.wasm: %.cpp
+	$(EMCC) $< $(EMCFLAGS) -sSTANDALONE_WASM=1 -o $@
+
+clean:
+	$(RM) $(ARTIFACTS)
+
+upload: all
+	@for file in $(ARTIFACTS); do \
+	  gcloud storage cp $$file gs://$(GCS_BUCKET)/ ; \
+	done
+
+# some functions (with shorter name) can call other functions (with suffix)
+# so reversing the order should create full-signature functions first
+reverse = $(if $(wordlist 2,2,$(1)),$(call reverse,$(wordlist 2,$(words $(1)),$(1))) $(firstword $(1)),$(1))
+
+create:
+	@for file in $(call reverse,$(wildcard sqlx/*.sqlx)); do \
+	  echo creating $$file; \
+	  ../substitute_and_run.sh $$file ; \
+	done
+
+install: upload create
+
+test:
+	@for file in $(wildcard test/*sql); do \
+	  ../substitute_and_run.sh $$file ; \
+	done
+
+.PHONY: all clean install upload create test
diff --git a/tuple/sqlx/tuple_sketch_int64_a_not_b_seed.sqlx b/tuple/sqlx/tuple_sketch_int64_a_not_b_seed.sqlx
new file mode 100644
index 0000000..f0e2fe9
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_a_not_b_seed.sqlx
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketchA BYTES, sketchB BYTES, seed INT64)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+const default_seed = BigInt(Module.DEFAULT_SEED);
+try {
+  var a_not_b = null;
+  try {
+    a_not_b = new Module.tuple_a_not_b_int64(seed ? BigInt(seed) : default_seed);
+    return a_not_b.computeWithB64ReturnB64(sketchA, sketchB, seed ? BigInt(seed) : default_seed);
+  } finally {
+    if (a_not_b != null) a_not_b.delete();
+  }
+} catch (e) {
+  throw new Error(Module.getExceptionMessage(e));
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_agg_string.sqlx b/tuple/sqlx/tuple_sketch_int64_agg_string.sqlx
new file mode 100644
index 0000000..091cdaa
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_agg_string.sqlx
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE AGGREGATE FUNCTION ${self()}(key STRING, value INT64)
+RETURNS BYTES 
+OPTIONS (
+  description = '''Creates a sketch that represents the cardinality of the given STRING column
+with an additional INT64 value associated with each key.
+Multiple values for the same key are aggregated using one of the selectable
+operations: SUM, MIN, MAX. 
+Param key: the STRING column of identifiers.
+Param value: the INT64 value associated with the key.
+Returns: a Compact Tuple Sketch, as bytes, which can be queried for results
+or used in other sketch operations.
+For more details: https://datasketches.apache.org/docs/Tuple/TupleOverview.html'''
+) AS (
+  $BQ_DATASET.tuple_sketch_int64_agg_string_lgk_seed_p_mode(key, value, STRUCT<BYTEINT, INT64, FLOAT64, STRING>(NULL, NULL, NULL, NULL))
+);
diff --git a/tuple/sqlx/tuple_sketch_int64_agg_string_lgk_seed_p_mode.sqlx b/tuple/sqlx/tuple_sketch_int64_agg_string_lgk_seed_p_mode.sqlx
new file mode 100644
index 0000000..554f5e9
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_agg_string_lgk_seed_p_mode.sqlx
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE AGGREGATE FUNCTION ${self()}(key STRING, value INT64, params STRUCT<lg_k BYTEINT, seed INT64, p FLOAT64, mode STRING> NOT AGGREGATE)
+RETURNS BYTES 
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.mjs"],
+  description = '''Creates a sketch that represents the cardinality of the given STRING column
+with an additional INT64 value associated with each key.
+Multiple values for the same key are aggregated using one of the selectable
+operations: SUM, MIN, MAX, ONE. 
+Param key: the STRING column of identifiers.
+Param value: the INT64 value associated with the key.
+Param lg_k: the sketch accuracy/size parameter as an integer in the range [4, 26].
+Param seed: the seed to be used by the underlying hash function.
+Param p: sampling probability (initial theta). The default is 1, so the sketch retains
+all entries until it reaches the limit, at which point it goes into the estimation mode
+and reduces the effective sampling probability (theta) as necessary.
+Param mode: aggregate values using SUM, MIN, MAX, ONE (constant 1).
+Returns: a Compact Tuple Sketch, as bytes, which can be queried for results
+or used in other sketch operations.
+For more details: https://datasketches.apache.org/docs/Tuple/TupleOverview.html'''
+) AS R"""
+import ModuleFactory from "gs://$GCS_BUCKET/tuple_sketch_int64.mjs";
+var Module = await ModuleFactory();
+const default_lg_k = Number(Module.DEFAULT_LG_K);
+const default_seed = BigInt(Module.DEFAULT_SEED);
+const default_p = 1.0;
+
+function destroyState(state) {
+  if (state.sketch) {
+    state.sketch.delete();
+    state.sketch = null;
+  }
+  if (state.union) {
+    state.union.delete();
+    state.union = null;
+  }
+  state.serialized = null;
+}
+
+// UDAF interface
+export function initialState(params) {
+  var state = {
+    lg_k: params.lg_k == null ? default_lg_k : Number(params.lg_k),
+    seed: params.seed == null ? default_seed : BigInt(params.seed),
+    p: params.p == null ? default_p : params.p,
+    mode: params.mode == null ? "" : params.mode
+  };
+  state.sketch = new Module.update_tuple_sketch_int64(state.lg_k, state.seed, state.p, state.mode);
+  return state;
+}
+
+export function aggregate(state, key, value) {
+  if (state.sketch == null) {
+    state.sketch = new Module.update_tuple_sketch_int64(state.lg_k, state.seed, state.p, state.mode);
+  }
+  state.sketch.updateString(key, value);
+}
+
+export function serialize(state) {
+  if (state.sketch == null) return state; // for transition deserialize-serialize
+  try {
+    // for prior transition deserialize-aggregate
+    // merge aggregated and serialized state
+    if (state.sketch != null && state.serialized != null) {
+      var u = null;
+      try {
+        u = new Module.tuple_union_int64(state.lg_k, state.seed, state.mode);
+        u.updateWithUpdateSketch(state.sketch);
+        u.updateWithBytes(state.serialized, state.seed);
+        state.serialized = u.getResultAsUint8Array();
+      } finally {
+        if (u != null) u.delete();
+      }
+    } else if (state.sketch != null) {
+      state.serialized = state.sketch.serializeAsUint8Array();
+    } else if (state.union != null) {
+      state.serialized = state.union.getResultAsUint8Array();
+    }
+    return {
+      lg_k: state.lg_k,
+      seed: state.seed,
+      mode: state.mode,
+      serialized: state.serialized
+    };
+  } catch (e) {
+    throw new Error(Module.getExceptionMessage(e));
+  } finally {
+    destroyState(state);
+  }
+}
+
+export function deserialize(state) {
+  return state;
+}
+
+export function merge(state, other_state) {
+  try {
+    if (!state.union) {
+      state.union = new Module.tuple_union_int64(state.lg_k, state.seed, state.mode);
+    }
+    if (state.serialized) {
+      state.union.updateWithBytes(state.serialized, state.seed);
+      state.serialized = null;
+    }
+    if (other_state.serialized) {
+      state.union.updateWithBytes(other_state.serialized, state.seed);
+      other_state.serialized = null;
+    }
+  } catch (e) {
+    throw new Error(Module.getExceptionMessage(e));
+  }
+}
+
+export function finalize(state) {
+  return serialize(state).serialized
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_agg_union.sqlx b/tuple/sqlx/tuple_sketch_int64_agg_union.sqlx
new file mode 100644
index 0000000..8235394
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_agg_union.sqlx
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE AGGREGATE FUNCTION ${self()}(sketch BYTES)
+RETURNS BYTES
+AS (
+  $BQ_DATASET.tuple_sketch_int64_agg_union_lgk_seed_mode(sketch, STRUCT<lg_k BYTEINT, seed INT64, mode STRING>(NULL, NULL, NULL))
+);
diff --git a/tuple/sqlx/tuple_sketch_int64_agg_union_lgk_seed_mode.sqlx b/tuple/sqlx/tuple_sketch_int64_agg_union_lgk_seed_mode.sqlx
new file mode 100644
index 0000000..f323bc0
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_agg_union_lgk_seed_mode.sqlx
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE AGGREGATE FUNCTION ${self()}(sketch BYTES, params STRUCT<lg_k BYTEINT, seed INT64, mode STRING> NOT AGGREGATE)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.mjs"]
+) AS R"""
+import ModuleFactory from "gs://$GCS_BUCKET/tuple_sketch_int64.mjs";
+var Module = await ModuleFactory();
+
+function ensureUnion(state) {
+  try {
+    if (state.union == null) {
+      state.union = new Module.tuple_union_int64(state.lg_k, state.seed, state.mode);
+    }
+    if (state.serialized != null) {
+      state.union.updateWithBytes(state.serialized, state.seed);
+      state.serialized = null;
+    }
+  } catch (e) {
+    throw new Error(Module.getExceptionMessage(e));
+  }
+}
+
+export function initialState(params) {
+  return {
+    lg_k: params.lg_k == null ? Number(Module.DEFAULT_LG_K) : Number(params.lg_k),
+    seed: params.seed == null ? BigInt(Module.DEFAULT_SEED) : BigInt(params.seed),
+    mode: params.mode == null ? "" : params.mode
+  };
+}
+
+export function aggregate(state, sketch) {
+  if (sketch != null) {
+    ensureUnion(state);
+    try {
+      state.union.updateWithBytes(sketch, state.seed);
+    } catch (e) {
+      throw new Error(Module.getExceptionMessage(e));
+    }
+  }
+}
+
+export function serialize(state) {
+  if (state.union == null) return state; // for transition deserialize-serialize
+  try {
+    if (state.serialized != null) {
+      state.union.updateWithBytes(state.serialized, state.seed);
+      state.serialized = null;
+    }
+    return {
+      lg_k: state.lg_k,
+      seed: state.seed,
+      mode: state.mode,
+      serialized: state.union.getResultAsUint8Array()
+    };
+  } catch (e) {
+    throw new Error(Module.getExceptionMessage(e));
+  } finally {
+    state.union.delete();
+    state.union = null;
+  }
+}
+
+export function deserialize(state) {
+  return state;
+}
+
+export function merge(state, other_state) {
+  ensureUnion(state);
+  if (other_state.serialized) {
+    try {
+      state.union.updateWithBytes(other_state.serialized, other_state.seed);
+      other_state.serialized = null;
+    } catch (e) {
+      throw new Error(Module.getExceptionMessage(e));
+    }
+  }
+}
+
+export function finalize(state) {
+  return serialize(state).serialized;
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_filter_low_high_seed.sqlx b/tuple/sqlx/tuple_sketch_int64_filter_low_high_seed.sqlx
new file mode 100644
index 0000000..2c85f24
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_filter_low_high_seed.sqlx
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES, low INT64, high INT64, seed INT64)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+var sketchObject = null;
+try {
+  sketchObject = Module.compact_tuple_sketch_int64.deserializeFromB64(sketch, seed ? BigInt(seed) : BigInt(Module.DEFAULT_SEED));
+  return sketchObject.filterB64(low, high);
+} finally {
+  if (sketchObject != null) sketchObject.delete();
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_from_theta_sketch_seed.sqlx b/tuple/sqlx/tuple_sketch_int64_from_theta_sketch_seed.sqlx
new file mode 100644
index 0000000..ad68093
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_from_theta_sketch_seed.sqlx
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES, value INT64, seed INT64)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+var sketchObject = null;
+try {
+  sketchObject = Module.compact_tuple_sketch_int64.convertThetaFromB64(sketch, BigInt(value), seed ? BigInt(seed) : BigInt(Module.DEFAULT_SEED));
+  return sketchObject.serializeAsB64();
+} finally {
+  if (sketchObject != null) sketchObject.delete();
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_get_estimate.sqlx b/tuple/sqlx/tuple_sketch_int64_get_estimate.sqlx
new file mode 100644
index 0000000..79d16d2
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_get_estimate.sqlx
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES)
+RETURNS FLOAT64
+AS (
+  $BQ_DATASET.tuple_sketch_int64_get_estimate_seed(sketch, NULL)
+);
diff --git a/tuple/sqlx/tuple_sketch_int64_get_estimate_seed.sqlx b/tuple/sqlx/tuple_sketch_int64_get_estimate_seed.sqlx
new file mode 100644
index 0000000..692a0c0
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_get_estimate_seed.sqlx
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES, seed INT64)
+RETURNS FLOAT64
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+try {
+  var sketchObject = null;
+  try {
+    sketchObject = Module.compact_tuple_sketch_int64.deserializeFromB64(sketch, seed ? BigInt(seed) : BigInt(Module.DEFAULT_SEED));
+    return sketchObject.getEstimate();
+  } finally {
+    if (sketchObject != null) sketchObject.delete();
+  }
+} catch (e) {
+  throw new Error(Module.getExceptionMessage(e));
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_intersection_seed_mode.sqlx b/tuple/sqlx/tuple_sketch_int64_intersection_seed_mode.sqlx
new file mode 100644
index 0000000..b585f1e
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_intersection_seed_mode.sqlx
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketchA BYTES, sketchB BYTES, seed INT64, mode STRING)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+const default_seed = BigInt(Module.DEFAULT_SEED);
+try {
+  var intersection = null;
+  try {
+    intersection = new Module.tuple_intersection_int64(seed ? BigInt(seed) : default_seed, mode ? mode : "");
+    intersection.updateWithB64(sketchA, seed ? BigInt(seed) : default_seed);
+    intersection.updateWithB64(sketchB, seed ? BigInt(seed) : default_seed);
+    return intersection.getResultB64();
+  } finally {
+    if (intersection != null) intersection.delete();
+  }
+} catch (e) {
+  throw new Error(Module.getExceptionMessage(e));
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_to_string.sqlx b/tuple/sqlx/tuple_sketch_int64_to_string.sqlx
new file mode 100644
index 0000000..540ba6f
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_to_string.sqlx
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES)
+RETURNS STRING
+AS (
+  $BQ_DATASET.tuple_sketch_int64_to_string_seed(sketch, NULL)
+);
diff --git a/tuple/sqlx/tuple_sketch_int64_to_string_seed.sqlx b/tuple/sqlx/tuple_sketch_int64_to_string_seed.sqlx
new file mode 100644
index 0000000..9569474
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_to_string_seed.sqlx
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketch BYTES, seed INT64)
+RETURNS STRING
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+try {
+  var sketchObject = null;
+  try {
+    sketchObject = Module.compact_tuple_sketch_int64.deserializeFromB64(sketch, seed ? BigInt(seed) : BigInt(Module.DEFAULT_SEED));
+    return sketchObject.toString();
+  } finally {
+    if (sketchObject != null) sketchObject.delete();
+  }
+} catch (e) {
+  throw new Error(Module.getExceptionMessage(e));
+}
+""";
diff --git a/tuple/sqlx/tuple_sketch_int64_union.sqlx b/tuple/sqlx/tuple_sketch_int64_union.sqlx
new file mode 100644
index 0000000..2789e3c
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_union.sqlx
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketchA BYTES, sketchB BYTES)
+RETURNS BYTES
+AS (
+  $BQ_DATASET.tuple_sketch_int64_union_lgk_seed_mode(sketchA, sketchB, NULL, NULL, NULL)
+);
diff --git a/tuple/sqlx/tuple_sketch_int64_union_lgk_seed_mode.sqlx b/tuple/sqlx/tuple_sketch_int64_union_lgk_seed_mode.sqlx
new file mode 100644
index 0000000..45726c2
--- /dev/null
+++ b/tuple/sqlx/tuple_sketch_int64_union_lgk_seed_mode.sqlx
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+config { hasOutput: true }
+
+CREATE OR REPLACE FUNCTION ${self()}(sketchA BYTES, sketchB BYTES, lg_k BYTEINT, seed INT64, mode STRING)
+RETURNS BYTES
+LANGUAGE js
+OPTIONS (
+  library=["gs://$GCS_BUCKET/tuple_sketch_int64.js"]
+) AS R"""
+const default_lg_k = Number(Module.DEFAULT_LG_K);
+const default_seed = BigInt(Module.DEFAULT_SEED);
+try {
+  var union = null;
+  try {
+    union = new Module.tuple_union_int64(lg_k ? lg_k : default_lg_k, seed ? BigInt(seed) : default_seed, mode ? mode : "");
+    union.updateWithB64(sketchA, seed ? BigInt(seed) : default_seed)
+    union.updateWithB64(sketchB, seed ? BigInt(seed) : default_seed)
+    return union.getResultB64();
+  } finally {
+    if (union != null) union.delete();
+  }
+} catch (e) {
+  throw new Error(Module.getExceptionMessage(e));
+}
+""";
diff --git a/tuple/test/tuple_sketch_int_test.sql b/tuple/test/tuple_sketch_int_test.sql
new file mode 100644
index 0000000..17a61d8
--- /dev/null
+++ b/tuple/test/tuple_sketch_int_test.sql
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+create or replace table $BQ_DATASET.tuple_sketch(sketch bytes);
+
+insert into $BQ_DATASET.tuple_sketch
+(select $BQ_DATASET.tuple_sketch_int64_from_theta_sketch_seed($BQ_DATASET.theta_sketch_agg_string(cast(value as string)), 1, null) from unnest(GENERATE_ARRAY(1, 10000, 1)) as value);
+insert into $BQ_DATASET.tuple_sketch
+(select $BQ_DATASET.tuple_sketch_int64_from_theta_sketch_seed($BQ_DATASET.theta_sketch_agg_string(cast(value as string)), 1, null) from unnest(GENERATE_ARRAY(100000, 110000, 1)) as value);
+
+
+# expected about 20000
+select $BQ_DATASET.tuple_sketch_int64_get_estimate(
+  $BQ_DATASET.tuple_sketch_int64_agg_union(sketch)
+) from $BQ_DATASET.tuple_sketch;
+
+# expected estimate about 20000
+select $BQ_DATASET.tuple_sketch_int64_to_string(
+  $BQ_DATASET.tuple_sketch_int64_agg_union(sketch)
+) from $BQ_DATASET.tuple_sketch;
+
+drop table $BQ_DATASET.tuple_sketch;
+
+# expected 5
+select $BQ_DATASET.tuple_sketch_int64_get_estimate_seed(
+  $BQ_DATASET.tuple_sketch_int64_union_lgk_seed_mode(
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["a", "b", "c"]) as str),
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["c", "d", "e"]) as str),
+    10,
+    null,
+    "MIN"
+  ),
+  null
+);
+
+# expected 5
+select $BQ_DATASET.tuple_sketch_int64_get_estimate_seed(
+  $BQ_DATASET.tuple_sketch_int64_union(
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["a", "b", "c"]) as str),
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["c", "d", "e"]) as str)
+  ),
+  null
+);
+
+# expected 1
+select $BQ_DATASET.tuple_sketch_int64_get_estimate_seed(
+  $BQ_DATASET.tuple_sketch_int64_intersection_seed_mode(
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["a", "b", "c"]) as str),
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["c", "d", "e"]) as str),
+    null,
+    null
+  ),
+  null
+);
+
+# expected 2
+select $BQ_DATASET.tuple_sketch_int64_get_estimate_seed(
+  $BQ_DATASET.tuple_sketch_int64_a_not_b_seed(
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["a", "b", "c"]) as str),
+    (select $BQ_DATASET.tuple_sketch_int64_agg_string(str, 1) from unnest(["c", "d", "e"]) as str),
+    null
+  ),
+  null
+);
+
+/*
+# expected 0.2
+select $BQ_DATASET.tuple_sketch_jaccard_similarity(
+  (select $BQ_DATASET.tuple_sketch_agg_string(str) from unnest(["a", "b", "c"]) as str),
+  (select $BQ_DATASET.tuple_sketch_agg_string(str) from unnest(["c", "d", "e"]) as str),
+  null
+);
+*/
diff --git a/tuple/tuple_sketch_int64.cpp b/tuple/tuple_sketch_int64.cpp
new file mode 100644
index 0000000..0c59ade
--- /dev/null
+++ b/tuple/tuple_sketch_int64.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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 <emscripten/bind.h>
+
+#include <tuple_sketch.hpp>
+#include <tuple_union.hpp>
+#include <tuple_intersection.hpp>
+#include <tuple_a_not_b.hpp>
+#include <theta_sketch.hpp>
+
+#include "../base64.hpp"
+
+using Summary = uint64_t;
+using Update = uint64_t;
+
+enum tuple_mode {SUM, MIN, MAX, ONE, NOP};
+
+template<typename S, typename U>
+class tuple_update_policy {
+public:
+  tuple_update_policy(tuple_mode mode): mode_(mode) {}
+  Summary create() const {
+    return S();
+  }
+  void update(S& summary, const U& update) const {
+    if (mode_ == SUM) summary += update;
+    else if (mode_ == MIN) summary = std::min(summary, update);
+    else if (mode_ == MAX) summary = std::max(summary, update);
+    else if (mode_ == ONE) summary = 1;
+  }
+private:
+  tuple_mode mode_;
+};
+using update_tuple_sketch_int64 = datasketches::update_tuple_sketch<Summary, Update, tuple_update_policy<Summary, Update>>;
+using compact_tuple_sketch_int64 = datasketches::compact_tuple_sketch<Summary>;
+
+template<typename S>
+class tuple_union_policy {
+public:
+  tuple_union_policy(tuple_mode mode): mode_(mode) {}
+  void operator()(Summary& summary, const Summary& other) const {
+    if (mode_ == SUM) summary += other;
+    else if (mode_ == MIN) summary = std::min(summary, other);
+    else if (mode_ == MAX) summary = std::max(summary, other);
+    else if (mode_ == ONE) summary = 1;
+  }
+private:
+  tuple_mode mode_;
+};
+using tuple_union_int64 = datasketches::tuple_union<Summary, tuple_union_policy<Summary>>;
+
+template<typename S> using tuple_intersection_policy = tuple_union_policy<S>;
+using tuple_intersection_int64 = datasketches::tuple_intersection<Summary, tuple_intersection_policy<Summary>>;
+
+using tuple_a_not_b_int64 = datasketches::tuple_a_not_b<Summary>;
+
+tuple_mode convert_mode(const std::string& mode_str) {
+  if (mode_str == "" || mode_str == "SUM") return SUM;
+  if (mode_str == "MIN") return MIN;
+  if (mode_str == "MAX") return MAX;
+  if (mode_str == "ONE") return ONE;
+  if (mode_str == "NOP") return NOP;
+  throw std::invalid_argument("unrecognized mode " + mode_str);
+}
+
+const emscripten::val Uint8Array = emscripten::val::global("Uint8Array");
+
+EMSCRIPTEN_BINDINGS(tuple_sketch_int64) {
+  emscripten::register_vector<double>("VectorDouble");
+
+  emscripten::function("getExceptionMessage", emscripten::optional_override([](intptr_t ptr) {
+    return std::string(reinterpret_cast<std::exception*>(ptr)->what());
+  }));
+
+  emscripten::constant("DEFAULT_LG_K", datasketches::theta_constants::DEFAULT_LG_K);
+  emscripten::constant("DEFAULT_SEED", datasketches::DEFAULT_SEED);
+
+  emscripten::class_<update_tuple_sketch_int64>("update_tuple_sketch_int64")
+    .constructor(emscripten::optional_override([](uint8_t lg_k, uint64_t seed, float p, const std::string& mode_str) {
+      const auto policy = tuple_update_policy<Summary, Update>(convert_mode(mode_str));
+      return new update_tuple_sketch_int64(update_tuple_sketch_int64::builder(policy).set_lg_k(lg_k).set_seed(seed).set_p(p).build());
+    }))
+    .function("updateString", emscripten::optional_override([](update_tuple_sketch_int64& self, const std::string& key, Update value) {
+      self.update(key, value);
+    }))
+    .function("serializeAsUint8Array", emscripten::optional_override([](const update_tuple_sketch_int64& self) {
+      auto bytes = self.compact().serialize();
+      return Uint8Array.new_(emscripten::typed_memory_view(bytes.size(), bytes.data()));
+    }))
+    ;
+
+  emscripten::class_<compact_tuple_sketch_int64>("compact_tuple_sketch_int64")
+    .class_function("deserializeFromB64", emscripten::optional_override([](const std::string& b64, uint64_t seed) {
+      std::vector<char> bytes(b64_dec_len(b64.data(), b64.size()));
+      b64_decode(b64.data(), b64.size(), bytes.data());
+      return new compact_tuple_sketch_int64(compact_tuple_sketch_int64::deserialize(bytes.data(), bytes.size(), seed));
+    }), emscripten::allow_raw_pointers())
+    .class_function("deserializeFromBinary", emscripten::optional_override([](const std::string& bytes, uint64_t seed) {
+      return new compact_tuple_sketch_int64(compact_tuple_sketch_int64::deserialize(bytes.data(), bytes.size(), seed));
+    }), emscripten::allow_raw_pointers())
+    .class_function("convertThetaFromB64", emscripten::optional_override([](const std::string& b64, uint64_t value, uint64_t seed) {
+      std::vector<char> bytes(b64_dec_len(b64.data(), b64.size()));
+      b64_decode(b64.data(), b64.size(), bytes.data());
+      // converting constructor does not currently take wrapped compact theta sketch
+      const auto sketch = datasketches::compact_theta_sketch::deserialize(bytes.data(), bytes.size(), seed);
+      return new compact_tuple_sketch_int64(sketch, value);
+    }), emscripten::allow_raw_pointers())
+    .function("getEstimate", emscripten::optional_override([](const compact_tuple_sketch_int64& self) {
+      return self.get_estimate();
+    }))
+    .function("toString", emscripten::optional_override([](const compact_tuple_sketch_int64& self) {
+      return std::string(self.to_string());
+    }))
+    .function("serializeAsB64", emscripten::optional_override([](const compact_tuple_sketch_int64& self) {
+      auto bytes = self.serialize();
+      std::vector<char> b64(b64_enc_len(bytes.size()));
+      b64_encode((const char*) bytes.data(), bytes.size(), b64.data());
+      return std::string(b64.data(), b64.size());
+    }))
+    .function("filterB64", emscripten::optional_override([](const compact_tuple_sketch_int64& self, int low, int high) {
+      auto sketch = self.filter([low, high](int v){return v >= low && v <= high;});
+      auto bytes = sketch.serialize();
+      std::vector<char> b64(b64_enc_len(bytes.size()));
+      b64_encode((const char*) bytes.data(), bytes.size(), b64.data());
+      return std::string(b64.data(), b64.size());
+    }))
+    ;
+
+  emscripten::class_<tuple_union_int64>("tuple_union_int64")
+    .constructor(emscripten::optional_override([](uint8_t lg_k, uint64_t seed, std::string mode_str) {
+      const auto policy = tuple_union_policy<Summary>(convert_mode(mode_str));
+      return new tuple_union_int64(tuple_union_int64::builder(policy).set_lg_k(lg_k).set_seed(seed).build());
+    }))
+    .function("updateWithCompactSketch", emscripten::optional_override([](tuple_union_int64& self, const compact_tuple_sketch_int64& sketch) {
+      self.update(sketch);
+    }), emscripten::allow_raw_pointers())
+    .function("updateWithBytes", emscripten::optional_override([](tuple_union_int64& self, const std::string& bytes, uint64_t seed) {
+      self.update(compact_tuple_sketch_int64::deserialize(bytes.data(), bytes.size(), seed));
+    }), emscripten::allow_raw_pointers())
+    .function("updateWithB64", emscripten::optional_override([](tuple_union_int64& self, const std::string& b64, uint64_t seed) {
+      std::vector<char> bytes(b64_dec_len(b64.data(), b64.size()));
+      b64_decode(b64.data(), b64.size(), bytes.data());
+      self.update(compact_tuple_sketch_int64::deserialize(bytes.data(), bytes.size(), seed));
+    }), emscripten::allow_raw_pointers())
+    .function("getResultAsUint8Array", emscripten::optional_override([](tuple_union_int64& self) {
+      auto bytes = self.get_result().serialize();
+      return Uint8Array.new_(emscripten::typed_memory_view(bytes.size(), bytes.data()));
+    }))
+    .function("getResultB64", emscripten::optional_override([](tuple_union_int64& self) {
+      auto bytes = self.get_result().serialize();
+      std::vector<char> b64(b64_enc_len(bytes.size()));
+      b64_encode((const char*) bytes.data(), bytes.size(), b64.data());
+      return std::string(b64.data(), b64.size());
+    }))
+    ;
+
+  emscripten::class_<tuple_intersection_int64>("tuple_intersection_int64")
+    .constructor(emscripten::optional_override([](uint64_t seed, const std::string& mode_str) {
+      return new tuple_intersection_int64(seed, tuple_intersection_policy<Summary>(convert_mode(mode_str)));
+    }))
+    .function("updateWithB64", emscripten::optional_override([](tuple_intersection_int64& self, const std::string& b64, uint64_t seed) {
+      std::vector<char> bytes(b64_dec_len(b64.data(), b64.size()));
+      b64_decode(b64.data(), b64.size(), bytes.data());
+      self.update(compact_tuple_sketch_int64::deserialize(bytes.data(), bytes.size(), seed));
+    }), emscripten::allow_raw_pointers())
+    .function("getResultB64", emscripten::optional_override([](tuple_intersection_int64& self) {
+      auto bytes = self.get_result().serialize();
+      std::vector<char> b64(b64_enc_len(bytes.size()));
+      b64_encode((const char*) bytes.data(), bytes.size(), b64.data());
+      return std::string(b64.data(), b64.size());
+    }))
+    ;
+
+  emscripten::class_<tuple_a_not_b_int64>("tuple_a_not_b_int64")
+    .constructor(emscripten::optional_override([](uint64_t seed) {
+      return new tuple_a_not_b_int64(seed);
+    }))
+    .function("computeWithB64ReturnB64", emscripten::optional_override([](tuple_a_not_b_int64& self,
+      const std::string& b64_1, const std::string& b64_2, uint64_t seed) {
+      std::vector<char> bytes1(b64_dec_len(b64_1.data(), b64_1.size()));
+      b64_decode(b64_1.data(), b64_1.size(), bytes1.data());
+      std::vector<char> bytes2(b64_dec_len(b64_2.data(), b64_2.size()));
+      b64_decode(b64_2.data(), b64_2.size(), bytes2.data());
+      auto bytes = self.compute(
+        compact_tuple_sketch_int64::deserialize(bytes1.data(), bytes1.size(), seed),
+        compact_tuple_sketch_int64::deserialize(bytes2.data(), bytes2.size(), seed)
+      ).serialize();
+      std::vector<char> b64(b64_enc_len(bytes.size()));
+      b64_encode((const char*) bytes.data(), bytes.size(), b64.data());
+      return std::string(b64.data(), b64.size());
+    }))
+    ;
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org