| 45 | |
| 46 | template <typename in_type, typename out_type> |
| 47 | Status ShiftTime(KernelContext* ctx, const util::DivideOrMultiply factor_op, |
| 48 | const int64_t factor, const ArraySpan& input, ArraySpan* output) { |
| 49 | const CastOptions& options = checked_cast<const CastState&>(*ctx->state()).options; |
| 50 | const in_type* in_data = input.GetValues<in_type>(1); |
| 51 | out_type* out_data = output->GetValues<out_type>(1); |
| 52 | |
| 53 | if (factor == 1) { |
| 54 | for (int64_t i = 0; i < input.length; i++) { |
| 55 | out_data[i] = static_cast<out_type>(in_data[i]); |
| 56 | } |
| 57 | } else if (factor_op == util::MULTIPLY) { |
| 58 | if (options.allow_time_overflow) { |
| 59 | for (int64_t i = 0; i < input.length; i++) { |
| 60 | out_data[i] = static_cast<out_type>(in_data[i] * factor); |
| 61 | } |
| 62 | } else { |
| 63 | #define RAISE_OVERFLOW_CAST(VAL) \ |
| 64 | return Status::Invalid("Casting from ", input.type->ToString(), " to ", \ |
| 65 | output->type->ToString(), " would result in ", \ |
| 66 | "out of bounds timestamp: ", VAL); |
| 67 | |
| 68 | int64_t max_val = std::numeric_limits<int64_t>::max() / factor; |
| 69 | int64_t min_val = std::numeric_limits<int64_t>::min() / factor; |
| 70 | if (input.null_count != 0 && input.buffers[0].data != nullptr) { |
| 71 | BitmapReader bit_reader(input.buffers[0].data, input.offset, input.length); |
| 72 | for (int64_t i = 0; i < input.length; i++) { |
| 73 | if (bit_reader.IsSet() && (in_data[i] < min_val || in_data[i] > max_val)) { |
| 74 | RAISE_OVERFLOW_CAST(in_data[i]); |
| 75 | } |
| 76 | out_data[i] = static_cast<out_type>(in_data[i] * factor); |
| 77 | bit_reader.Next(); |
| 78 | } |
| 79 | } else { |
| 80 | for (int64_t i = 0; i < input.length; i++) { |
| 81 | if (in_data[i] < min_val || in_data[i] > max_val) { |
| 82 | RAISE_OVERFLOW_CAST(in_data[i]); |
| 83 | } |
| 84 | out_data[i] = static_cast<out_type>(in_data[i] * factor); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | #undef RAISE_OVERFLOW_CAST |
| 89 | } |
| 90 | } else { |
| 91 | if (options.allow_time_truncate) { |
| 92 | for (int64_t i = 0; i < input.length; i++) { |
| 93 | out_data[i] = static_cast<out_type>(in_data[i] / factor); |
| 94 | } |
| 95 | } else { |
| 96 | #define RAISE_INVALID_CAST(VAL) \ |
| 97 | return Status::Invalid("Casting from ", input.type->ToString(), " to ", \ |
| 98 | output->type->ToString(), " would lose data: ", VAL); |
| 99 | |
| 100 | if (input.null_count != 0 && input.buffers[0].data != nullptr) { |
| 101 | BitmapReader bit_reader(input.buffers[0].data, input.offset, input.length); |
| 102 | for (int64_t i = 0; i < input.length; i++) { |
| 103 | out_data[i] = static_cast<out_type>(in_data[i] / factor); |
| 104 | if (bit_reader.IsSet() && (out_data[i] * factor != in_data[i])) { |