Skip to content

Commit 6123a67

Browse files
committed
uhugeint conversion
1 parent d3cbd55 commit 6123a67

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

bindings/src/duckdb_node_bindings.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,14 +1263,33 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
12631263
// function uhugeint_to_double(uhugeint: bigint): number
12641264
Napi::Value uhugeint_to_double(const Napi::CallbackInfo& info) {
12651265
auto env = info.Env();
1266-
throw Napi::Error::New(env, "Not implemented yet");
1266+
auto uhugeint_as_bigint = info[0].As<Napi::BigInt>();
1267+
int sign_bit;
1268+
size_t word_count = 2;
1269+
uint64_t words[2];
1270+
uhugeint_as_bigint.ToWords(&sign_bit, &word_count, words);
1271+
if (word_count > 2 || sign_bit) {
1272+
throw Napi::Error::New(env, "bigint out of uhugeint range");
1273+
}
1274+
uint64_t lower = word_count > 0 ? words[0] : 0;
1275+
uint64_t upper = word_count > 1 ? words[1] : 0;
1276+
duckdb_uhugeint uhugeint = { lower, upper };
1277+
auto output_double = duckdb_uhugeint_to_double(uhugeint);
1278+
return Napi::Number::New(env, output_double);
12671279
}
12681280

12691281
// DUCKDB_API duckdb_uhugeint duckdb_double_to_uhugeint(double val);
12701282
// function double_to_uhugeint(double: number): bigint
12711283
Napi::Value double_to_uhugeint(const Napi::CallbackInfo& info) {
12721284
auto env = info.Env();
1273-
throw Napi::Error::New(env, "Not implemented yet");
1285+
auto input_double = info[0].As<Napi::Number>().DoubleValue();
1286+
auto uhugeint = duckdb_double_to_uhugeint(input_double);
1287+
int sign_bit = 0;
1288+
size_t word_count = 2;
1289+
uint64_t words[2];
1290+
words[0] = uhugeint.lower;
1291+
words[1] = uhugeint.upper;
1292+
return Napi::BigInt::New(env, sign_bit, word_count, words);
12741293
}
12751294

12761295
// DUCKDB_API duckdb_decimal duckdb_double_to_decimal(double val, uint8_t width, uint8_t scale);

bindings/test/conversion.test.ts

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,12 @@ suite('conversion', () => {
179179
});
180180
});
181181
suite('hugeint_to_double', () => {
182-
test('one', () => {
183-
expect(duckdb.hugeint_to_double(1n)).toBe(1);
184-
});
185182
test('zero', () => {
186183
expect(duckdb.hugeint_to_double(0n)).toBe(0);
187184
});
185+
test('one', () => {
186+
expect(duckdb.hugeint_to_double(1n)).toBe(1);
187+
});
188188
test('negative one', () => {
189189
expect(duckdb.hugeint_to_double(-1n)).toBe(-1);
190190
});
@@ -212,17 +212,20 @@ suite('conversion', () => {
212212
test('near max', () => {
213213
expect(duckdb.hugeint_to_double(2n ** 127n - 2n ** 74n)).toBe(1.7014118346046922e+38);
214214
});
215-
test('out of range', () => {
215+
test('out of range (positive)', () => {
216216
expect(() => duckdb.hugeint_to_double(2n ** 129n)).toThrowError('bigint out of hugeint range');
217217
});
218+
test('out of range (negative)', () => {
219+
expect(() => duckdb.hugeint_to_double(-(2n ** 129n))).toThrowError('bigint out of hugeint range');
220+
});
218221
});
219222
suite('double_to_hugeint', () => {
220-
test('one', () => {
221-
expect(duckdb.double_to_hugeint(1)).toBe(1n);
222-
});
223223
test('zero', () => {
224224
expect(duckdb.double_to_hugeint(0)).toBe(0n);
225225
});
226+
test('one', () => {
227+
expect(duckdb.double_to_hugeint(1)).toBe(1n);
228+
});
226229
test('negative one', () => {
227230
expect(duckdb.double_to_hugeint(-1)).toBe(-1n);
228231
});
@@ -245,4 +248,47 @@ suite('conversion', () => {
245248
expect(duckdb.double_to_hugeint(1.7014118346046922e+38)).toBe(2n ** 127n - 2n ** 74n);
246249
});
247250
});
251+
suite('uhugeint_to_double', () => {
252+
test('zero', () => {
253+
expect(duckdb.uhugeint_to_double(0n)).toBe(0);
254+
});
255+
test('one', () => {
256+
expect(duckdb.uhugeint_to_double(1n)).toBe(1);
257+
});
258+
test('one word', () => {
259+
expect(duckdb.uhugeint_to_double(2n ** 63n)).toBe(9.223372036854776e+18);
260+
});
261+
test('two words', () => {
262+
expect(duckdb.uhugeint_to_double(2n ** 65n)).toBe(3.6893488147419103e+19);
263+
});
264+
test('max', () => {
265+
expect(duckdb.uhugeint_to_double(2n ** 127n - 1n)).toBe(1.7014118346046923e+38);
266+
});
267+
test('near max', () => {
268+
expect(duckdb.uhugeint_to_double(2n ** 127n - 2n ** 74n)).toBe(1.7014118346046922e+38);
269+
});
270+
test('out of range (positive)', () => {
271+
expect(() => duckdb.uhugeint_to_double(2n ** 129n)).toThrowError('bigint out of uhugeint range');
272+
});
273+
test('out of range (negative)', () => {
274+
expect(() => duckdb.uhugeint_to_double(-1n)).toThrowError('bigint out of uhugeint range');
275+
});
276+
});
277+
suite('double_to_uhugeint', () => {
278+
test('zero', () => {
279+
expect(duckdb.double_to_uhugeint(0)).toBe(0n);
280+
});
281+
test('one', () => {
282+
expect(duckdb.double_to_uhugeint(1)).toBe(1n);
283+
});
284+
test('one word', () => {
285+
expect(duckdb.double_to_uhugeint(9.223372036854776e+18)).toBe(2n ** 63n);
286+
});
287+
test('two words', () => {
288+
expect(duckdb.double_to_uhugeint(3.6893488147419103e+19)).toBe(2n ** 65n);
289+
});
290+
test('near max', () => {
291+
expect(duckdb.double_to_uhugeint(1.7014118346046922e+38)).toBe(2n ** 127n - 2n ** 74n);
292+
});
293+
});
248294
});

0 commit comments

Comments
 (0)