/* ***************************************************************************** * libg1m/bcd.h -- BCD-encoded numbers manipulation. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. * libg1m is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3.0 of the License, * or (at your option) any later version. * * libg1m is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libg1m; if not, see . * * BCD are the main number format CASIO uses in its calculators. * Each semi-byte is a digit going from 0 to 9 (0xA to 0xF aren't used). * This format has the huge advantage to make 0.1 + 0.2 and 0.3 equal. * * The first three digits are the exponent. * If the exponent is more than 500, then remove 500, and that means the * number is negative. * Then you have to remove 100 to have the real exponent. * * Before applying these operations, you should check the most significant bit * of the upper nibble of the first binary-coded digit of the exponent. * If it is 1, then the number has a complex part. Anyway, always set this * bit to zero before interpreting the exponent. * * The other 15 digits are the mantissa. So the number is: (M ** (E + 1)) * ************************************************************************** */ #ifndef LIBG1M_BCD_H # define LIBG1M_BCD_H # ifdef __cplusplus extern "C" { # endif /* Type definition */ typedef struct bcd { /* the BCD value itself */ unsigned char BCDval[9]; /* some 4-bytes alignment stuff */ unsigned char _align[3]; } g1m_bcd_t; /* ************************************************************************** */ /* BCD utilities */ /* ************************************************************************** */ /* Arithmetic */ int g1m_bcd_is_nonzero(g1m_bcd_t *bcd); /* String/BCD */ char *g1m_bcdtoa(g1m_bcd_t *bcd); /* ************************************************************************** */ /* Inline BCD utilities */ /* ************************************************************************** */ /** * g1m_bcd_is_negative: * Quick check. * * @arg bcd pointer to the BCD number. * @return a boolean. */ static inline int g1m_bcd_is_negative(g1m_bcd_t *bcd) { return (bcd->BCDval[0] >= 0x50); } /** * g1m_bcd_high_bit: * Quick check. * * @arg bcd pointer to the BCD number. * @return a boolean. */ static inline int g1m_bcd_high_bit(g1m_bcd_t *bcd) { return (bcd->BCDval[0] & 0x80); } /* macros */ # define g1m_bcd_is_positive(B) (!g1m_bcd_is_negative(B)) # define g1m_bcd_is_zero(B) (!g1m_bcd_is_nonzero(B)) # define g1m_bcd_has_complex(B) (g1m_bcd_high_bit(B)) # ifdef __cplusplus } # endif #endif /* LIBG1M_BCD_H */