2016-11-21 10:26:52 +01:00
|
|
|
/* ************************************************************************** */
|
|
|
|
/* _____ _ */
|
|
|
|
/* libg1m/bcd.h |_ _|__ _ _| |__ ___ _ _ */
|
|
|
|
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
|
|
/* Last updated: 2016/11/21 09:23:44 |___/ */
|
|
|
|
/* */
|
|
|
|
/* ************************************************************************** */
|
|
|
|
#ifndef LIBG1M_BCD_H
|
|
|
|
# define LIBG1M_BCD_H
|
2016-11-27 13:59:10 +01:00
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
# endif
|
2016-11-21 10:26:52 +01:00
|
|
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
/* Type definition */
|
|
|
|
/* ************************************************************************** */
|
|
|
|
/* 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.
|
|
|
|
*
|
2016-11-27 13:59:10 +01:00
|
|
|
* 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)) */
|
2016-11-21 10:26:52 +01:00
|
|
|
|
2017-02-19 23:31:46 +01:00
|
|
|
typedef struct bcd {
|
2016-11-21 10:26:52 +01:00
|
|
|
/* the BCD value itself */
|
|
|
|
unsigned char BCDval[9];
|
|
|
|
|
|
|
|
/* some 4-bytes alignment stuff */
|
|
|
|
unsigned char _align[3];
|
2017-02-19 23:31:46 +01:00
|
|
|
} g1m_bcd_t;
|
2016-11-21 10:26:52 +01:00
|
|
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
/* BCD utilities */
|
|
|
|
/* ************************************************************************** */
|
2016-11-21 17:01:24 +01:00
|
|
|
/* Arithmetic */
|
2017-02-19 23:31:46 +01:00
|
|
|
int g1m_bcd_is_nonzero(g1m_bcd_t *bcd);
|
2016-11-21 17:01:24 +01:00
|
|
|
|
|
|
|
/* String/BCD */
|
2017-02-19 23:31:46 +01:00
|
|
|
char *g1m_bcdtoa(g1m_bcd_t *bcd);
|
2016-11-21 17:01:24 +01:00
|
|
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
/* Inline BCD utilities */
|
|
|
|
/* ************************************************************************** */
|
2016-11-23 10:32:39 +01:00
|
|
|
/**
|
|
|
|
* g1m_bcd_is_negative:
|
|
|
|
* Quick check.
|
|
|
|
*
|
|
|
|
* @arg bcd pointer to the BCD number.
|
|
|
|
* @return a boolean.
|
|
|
|
*/
|
|
|
|
|
2017-02-19 23:31:46 +01:00
|
|
|
static inline int g1m_bcd_is_negative(g1m_bcd_t *bcd)
|
2016-11-21 17:01:24 +01:00
|
|
|
{
|
2016-11-23 10:32:39 +01:00
|
|
|
return (bcd->BCDval[0] >= 0x50);
|
2016-11-21 17:01:24 +01:00
|
|
|
}
|
|
|
|
|
2016-11-27 13:59:10 +01:00
|
|
|
/**
|
2016-12-08 16:57:14 +01:00
|
|
|
* g1m_bcd_high_bit:
|
2016-11-27 13:59:10 +01:00
|
|
|
* Quick check.
|
|
|
|
*
|
|
|
|
* @arg bcd pointer to the BCD number.
|
|
|
|
* @return a boolean.
|
|
|
|
*/
|
|
|
|
|
2017-02-19 23:31:46 +01:00
|
|
|
static inline int g1m_bcd_high_bit(g1m_bcd_t *bcd)
|
2016-11-27 13:59:10 +01:00
|
|
|
{
|
|
|
|
return (bcd->BCDval[0] & 0x80);
|
|
|
|
}
|
|
|
|
|
2016-11-21 17:01:24 +01:00
|
|
|
/* macros */
|
2016-11-23 10:32:39 +01:00
|
|
|
# define g1m_bcd_is_positive(B) (!g1m_bcd_is_negative(B))
|
2016-11-21 17:01:24 +01:00
|
|
|
# define g1m_bcd_is_zero(B) (!g1m_bcd_is_nonzero(B))
|
2016-12-08 16:57:14 +01:00
|
|
|
# define g1m_bcd_has_complex(B) (g1m_bcd_high_bit(B))
|
2016-11-21 10:26:52 +01:00
|
|
|
|
2016-11-27 13:59:10 +01:00
|
|
|
# ifdef __cplusplus
|
|
|
|
}
|
|
|
|
# endif
|
2016-11-21 10:26:52 +01:00
|
|
|
#endif /* LIBG1M_BCD_H */
|