blob: 0e044940af107ca014ac17e9b94e364c62cd1966 [file] [log] [blame]
// 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 "kudu/util/decimal_util.h"
#include <string>
#include <glog/logging.h>
#include "kudu/gutil/port.h"
namespace kudu {
using std::string;
// Workaround for an ASAN build issue documented here:
// https://bugs.llvm.org/show_bug.cgi?id=16404
ATTRIBUTE_NO_SANITIZE_UNDEFINED
int128_t MaxUnscaledDecimal(int8_t precision) {
DCHECK_GE(precision, kMinDecimalPrecision);
DCHECK_LE(precision, kMaxDecimalPrecision);
int128_t result = 1;
for (; precision > 0; precision--) {
result = result * 10;
}
return result - 1;
}
int128_t MinUnscaledDecimal(int8_t precision) {
return -MaxUnscaledDecimal(precision);
}
// Workaround for an ASAN build issue documented here:
// https://bugs.llvm.org/show_bug.cgi?id=16404
ATTRIBUTE_NO_SANITIZE_UNDEFINED
string DecimalToString(int128_t d, int8_t scale) {
// 38 digits, 1 extra leading zero, decimal point,
// and sign are good for 128-bit or smaller decimals.
char local[41];
char *p = local + sizeof(local);
int128_t n = d < 0? -d : d;
int position = 0;
while (n) {
// Print the decimal in the scale position.
// No decimal is output when scale is 0.
if (scale != 0 && position == scale) {
*--p = '.';
}
// Unroll the next digits.
*--p = '0' + n % 10;
n /= 10;
position++;
}
// True if the value is between 1 and -1.
bool fractional = position <= scale;
// Pad with zeros until the scale
while (position < scale) {
*--p = '0';
position++;
}
// Add leading "0.".
if (fractional) {
if (d != 0) {
*--p = '.';
}
*--p = '0';
}
// Add sign for negative values.
if (d < 0) {
*--p = '-';
}
return string(p, local + sizeof(local));
}
} // namespace kudu