Skip to content

Commit d3cbd55

Browse files
committed
hugeint conversion
1 parent c1b886d commit d3cbd55

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

bindings/src/duckdb_node_bindings.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,14 +1230,33 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
12301230
// function hugeint_to_double(hugeint: bigint): number
12311231
Napi::Value hugeint_to_double(const Napi::CallbackInfo& info) {
12321232
auto env = info.Env();
1233-
throw Napi::Error::New(env, "Not implemented yet");
1233+
auto hugeint_as_bigint = info[0].As<Napi::BigInt>();
1234+
int sign_bit;
1235+
size_t word_count = 2;
1236+
uint64_t words[2];
1237+
hugeint_as_bigint.ToWords(&sign_bit, &word_count, words);
1238+
if (word_count > 2) {
1239+
throw Napi::Error::New(env, "bigint out of hugeint range");
1240+
}
1241+
uint64_t lower = word_count > 0 ? (sign_bit ? -1 : 1) * words[0] : 0;
1242+
int64_t upper = word_count > 1 ? (sign_bit ? -1 : 1) * words[1] : (word_count > 0 && sign_bit ? -1 : 0);
1243+
duckdb_hugeint hugeint = { lower, upper };
1244+
auto output_double = duckdb_hugeint_to_double(hugeint);
1245+
return Napi::Number::New(env, output_double);
12341246
}
12351247

12361248
// DUCKDB_API duckdb_hugeint duckdb_double_to_hugeint(double val);
12371249
// function double_to_hugeint(double: number): bigint
12381250
Napi::Value double_to_hugeint(const Napi::CallbackInfo& info) {
12391251
auto env = info.Env();
1240-
throw Napi::Error::New(env, "Not implemented yet");
1252+
auto input_double = info[0].As<Napi::Number>().DoubleValue();
1253+
auto hugeint = duckdb_double_to_hugeint(input_double);
1254+
int sign_bit = input_double < 0 ? 1 : 0;
1255+
size_t word_count = hugeint.upper == -1 ? 1 : 2;
1256+
uint64_t words[2];
1257+
words[0] = (sign_bit ? -1 : 1) * hugeint.lower;
1258+
words[1] = (sign_bit ? -1 : 1) * hugeint.upper;
1259+
return Napi::BigInt::New(env, sign_bit, word_count, words);
12411260
}
12421261

12431262
// DUCKDB_API double duckdb_uhugeint_to_double(duckdb_uhugeint val);

bindings/test/conversion.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,71 @@ suite('conversion', () => {
178178
expect(duckdb.is_finite_timestamp({ micros: -(2n ** 63n - 1n) })).toBe(false);
179179
});
180180
});
181+
suite('hugeint_to_double', () => {
182+
test('one', () => {
183+
expect(duckdb.hugeint_to_double(1n)).toBe(1);
184+
});
185+
test('zero', () => {
186+
expect(duckdb.hugeint_to_double(0n)).toBe(0);
187+
});
188+
test('negative one', () => {
189+
expect(duckdb.hugeint_to_double(-1n)).toBe(-1);
190+
});
191+
test('one word', () => {
192+
expect(duckdb.hugeint_to_double(2n ** 63n)).toBe(9.223372036854776e+18);
193+
});
194+
test('two words', () => {
195+
expect(duckdb.hugeint_to_double(2n ** 65n)).toBe(3.6893488147419103e+19);
196+
});
197+
test('negative one word', () => {
198+
expect(duckdb.hugeint_to_double(-(2n ** 63n))).toBe(-9.223372036854776e+18);
199+
});
200+
test('negative two words', () => {
201+
expect(duckdb.hugeint_to_double(-(2n ** 65n))).toBe(-3.6893488147419103e+19);
202+
});
203+
test('min', () => {
204+
expect(duckdb.hugeint_to_double(-(2n ** 127n - 1n))).toBe(-1.7014118346046923e+38);
205+
});
206+
test('max', () => {
207+
expect(duckdb.hugeint_to_double(2n ** 127n - 1n)).toBe(1.7014118346046923e+38);
208+
});
209+
test('near min', () => {
210+
expect(duckdb.hugeint_to_double(-(2n ** 127n - 2n ** 74n))).toBe(-1.7014118346046922e+38);
211+
});
212+
test('near max', () => {
213+
expect(duckdb.hugeint_to_double(2n ** 127n - 2n ** 74n)).toBe(1.7014118346046922e+38);
214+
});
215+
test('out of range', () => {
216+
expect(() => duckdb.hugeint_to_double(2n ** 129n)).toThrowError('bigint out of hugeint range');
217+
});
218+
});
219+
suite('double_to_hugeint', () => {
220+
test('one', () => {
221+
expect(duckdb.double_to_hugeint(1)).toBe(1n);
222+
});
223+
test('zero', () => {
224+
expect(duckdb.double_to_hugeint(0)).toBe(0n);
225+
});
226+
test('negative one', () => {
227+
expect(duckdb.double_to_hugeint(-1)).toBe(-1n);
228+
});
229+
test('one word', () => {
230+
expect(duckdb.double_to_hugeint(9.223372036854776e+18)).toBe(2n ** 63n);
231+
});
232+
test('two words', () => {
233+
expect(duckdb.double_to_hugeint(3.6893488147419103e+19)).toBe(2n ** 65n);
234+
});
235+
test('negative one word', () => {
236+
expect(duckdb.double_to_hugeint(-9.223372036854776e+18)).toBe(-(2n ** 63n));
237+
});
238+
test('negative two words', () => {
239+
expect(duckdb.double_to_hugeint(-3.6893488147419103e+19)).toBe(-(2n ** 65n));
240+
});
241+
test('near min', () => {
242+
expect(duckdb.double_to_hugeint(-1.7014118346046922e+38)).toBe(-(2n ** 127n - 2n ** 74n));
243+
});
244+
test('near max', () => {
245+
expect(duckdb.double_to_hugeint(1.7014118346046922e+38)).toBe(2n ** 127n - 2n ** 74n);
246+
});
247+
});
181248
});

0 commit comments

Comments
 (0)