Skip to content

Commit a591e53

Browse files
committed
try implementation the other direction
1 parent 9eedb75 commit a591e53

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

r/R/as-array.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,9 @@ storage_decimal_for_decimal <- function(numbers, scale) {
488488
if (scale > 0) {
489489
rounded_formatted <- sprintf("%0.*f", scale, numbers)
490490
rounded_formatted[is.na(numbers)] <- NA_character_
491+
rounded_formatted
491492
} else {
492493
rounded_formatted <- as.character(round(numbers, scale))
494+
gsub(paste0("0{", -scale, "}$"), "", rounded_formatted)
493495
}
494-
495-
rounded_formatted
496496
}

r/R/convert-array.R

+10-9
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,16 @@ convert_array.double <- function(array, to, ...) {
161161
schema <- infer_nanoarrow_schema(array)
162162
parsed <- nanoarrow_schema_parse(schema)
163163
if (parsed$type == "decimal128") {
164-
assert_arrow_installed(
165-
sprintf(
166-
"convert %s array to object of type double",
167-
nanoarrow_schema_formatted(schema)
168-
)
169-
)
170-
171-
arrow_array <- as_arrow_array.nanoarrow_array(array)
172-
arrow_array$as_vector()
164+
# assert_arrow_installed(
165+
# sprintf(
166+
# "convert %s array to object of type double",
167+
# nanoarrow_schema_formatted(schema)
168+
# )
169+
# )
170+
#
171+
# arrow_array <- as_arrow_array.nanoarrow_array(array)
172+
# arrow_array$as_vector()
173+
NextMethod()
173174
} else {
174175
NextMethod()
175176
}

r/src/convert_array.c

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include "altrep.h"
2525
#include "array.h"
26-
#include "array_view.h"
2726
#include "convert.h"
2827
#include "util.h"
2928

r/src/materialize_dbl.h

+84
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@
2121
#include <R.h>
2222
#include <Rinternals.h>
2323

24+
#include "buffer.h"
2425
#include "materialize_common.h"
2526
#include "nanoarrow.h"
2627

2728
// bit64::as.integer64(2^53)
2829
#define MAX_DBL_AS_INTEGER 9007199254740992
2930

31+
static inline int nanoarrow_decimal_to_chr(struct ArrowDecimal* item,
32+
struct ArrowBuffer* buffer, int scale);
33+
3034
static inline int nanoarrow_materialize_dbl(struct RConverter* converter) {
3135
if (converter->src.array_view->array->dictionary != NULL) {
3236
return ENOTSUP;
@@ -109,6 +113,43 @@ static inline int nanoarrow_materialize_dbl(struct RConverter* converter) {
109113
}
110114
break;
111115

116+
case NANOARROW_TYPE_DECIMAL32:
117+
case NANOARROW_TYPE_DECIMAL64:
118+
case NANOARROW_TYPE_DECIMAL128:
119+
case NANOARROW_TYPE_DECIMAL256: {
120+
struct ArrowDecimal item;
121+
ArrowDecimalInit(&item, converter->schema_view.decimal_bitwidth,
122+
converter->schema_view.decimal_precision,
123+
converter->schema_view.decimal_scale);
124+
125+
// Buffer to manage the building of the digits output
126+
SEXP buffer_xptr = PROTECT(buffer_owning_xptr());
127+
struct ArrowBuffer* digits = (struct ArrowBuffer*)R_ExternalPtrAddr(buffer_xptr);
128+
129+
// A length one character() we'll use as input to Rf_asReal()
130+
SEXP decimal_as_chr = PROTECT(Rf_allocVector(STRSXP, 1));
131+
132+
for (R_xlen_t i = 0; i < dst->length; i++) {
133+
if (is_valid != NULL && !ArrowBitGet(is_valid, raw_src_offset + i)) {
134+
result[dst->offset + i] = NA_REAL;
135+
continue;
136+
}
137+
138+
ArrowArrayViewGetDecimalUnsafe(src->array_view, src->offset + i, &item);
139+
int status = nanoarrow_decimal_to_chr(&item, digits, item.scale);
140+
if (status != NANOARROW_OK) {
141+
UNPROTECT(2);
142+
return status;
143+
}
144+
145+
SET_STRING_ELT(decimal_as_chr, i,
146+
Rf_mkCharLen((char*)digits->data, (int)digits->size_bytes));
147+
result[dst->offset + i] = Rf_asReal(decimal_as_chr);
148+
}
149+
UNPROTECT(2);
150+
return NANOARROW_OK;
151+
}
152+
112153
default:
113154
return EINVAL;
114155
}
@@ -121,4 +162,47 @@ static inline int nanoarrow_materialize_dbl(struct RConverter* converter) {
121162
return NANOARROW_OK;
122163
}
123164

165+
static inline int nanoarrow_decimal_to_chr(struct ArrowDecimal* item,
166+
struct ArrowBuffer* buffer, int scale) {
167+
buffer->size_bytes = 0;
168+
NANOARROW_RETURN_NOT_OK(ArrowDecimalAppendDigitsToBuffer(item, buffer));
169+
170+
if (scale <= 0) {
171+
// e.g., digits are -12345 and scale is -2 -> -1234500
172+
// Just add zeros to the end
173+
for (int i = scale; i <= 0; i++) {
174+
NANOARROW_RETURN_NOT_OK(ArrowBufferAppendInt8(buffer, '0'));
175+
}
176+
return NANOARROW_OK;
177+
}
178+
179+
int is_negative = buffer->data[0] == '-';
180+
int64_t num_digits = buffer->size_bytes - is_negative;
181+
if (num_digits <= scale) {
182+
// e.g., digits are -12345 and scale is 6 -> -0.012345
183+
// Insert "0.<some zeros>" between the (maybe) negative sign and the digits
184+
int num_zeros_after_decimal = scale - num_digits;
185+
NANOARROW_RETURN_NOT_OK(
186+
ArrowBufferResize(buffer, buffer->size_bytes + num_zeros_after_decimal + 2, 0));
187+
188+
uint8_t* digits_start = buffer->data + is_negative;
189+
memmove(digits_start + num_zeros_after_decimal + 2, digits_start, num_digits);
190+
*digits_start++ = '0';
191+
*digits_start++ = '.';
192+
for (int i = 0; i < num_zeros_after_decimal; i++) {
193+
*digits_start++ = '0';
194+
}
195+
196+
} else {
197+
// e.g., digits are -12345 and scale is 4 -> -1.2345
198+
// Insert a decimal point before scale digits of output
199+
NANOARROW_RETURN_NOT_OK(ArrowBufferResize(buffer, buffer->size_bytes + 1, 0));
200+
uint8_t* decimal_point_to_be = buffer->data + buffer->size_bytes - 1 - scale;
201+
memmove(decimal_point_to_be + 1, decimal_point_to_be, scale);
202+
*decimal_point_to_be = '.';
203+
}
204+
205+
return NANOARROW_OK;
206+
}
207+
124208
#endif

0 commit comments

Comments
 (0)