极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5309|回复: 4

用纯C11标准写泛型例程

[复制链接]
发表于 2012-9-23 19:20:45 | 显示全部楼层 |阅读模式
本帖最后由 test01 于 2019-2-18 17:15 编辑

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <stdint.h>
#include <iso646.h>
#include <math.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include “tgmath_avr.h“

/* C11 Overload

#define def_max(a, b) (((a) >= (b)) ? (a) : (b))
                             
#define def_min(a, b) (((a) < (b)) ? (a) : (b))
                                                       
#define read_bit(_source_bits, _source_width, _n) _Generic(_source_bits, uint8_t: read_bit_ui8, \
                                                                         uint16_t: read_bit_ui16, \
                                                                         uint32_t: read_bit_ui32, \
                                                                                                                                             uint64_t: read_bit_ui64, \
                                                                                                                                             default: read_bit_ui64 \
                                                                                                                  )(_source_bits, _source_width, _n)
                                                                                                                  
#define write_bit(_source_bits, _source_width, _n, _a_bit) _Generic(_source_bits, uint8_t: write_bit_ui8, \
                                                                                  uint16_t: write_bit_ui16, \
                                                                                                                                                              uint32_t: write_bit_ui32, \
                                                                                                                                                              uint64_t: write_bit_ui64, \
                                                                                                                                                              default: write_bit_ui64 \
                                                                                                                                   )(_source_bits, _source_width, _n, _a_bit)
                                                                                                                                  
#define xor_bit(_source_bits, _source_width, _n, _a_bit) _Generic(_source_bits, uint8_t: xor_bit_ui8, \
                                                                                uint16_t: xor_bit_ui16, \
                                                                                                                                                            uint32_t: xor_bit_ui32, \
                                                                                                                                                            uint64_t: xor_bit_ui64, \
                                                                                                                                                            default: xor_bit_ui64 \
                                                                                                                                 )(_source_bits, _source_width, _n, _a_bit)
                                                                                                                                 
#define random_round(_x, _rounded_to_exp10) _Generic(_x, float: random_round_f, \
                                                         double: random_round_d, \
                                                                                                                 default: random_round_f \
                                                                                                        )(_x, _rounded_to_exp10)

#define integer_number_to_string(_input_number, _leader_character, _display_width, _numeric_string, _array_len) _Generic(_input_number, int8_t: integer_number_to_string_i8, \
                                                                                                                                        int16_t: integer_number_to_string_i16, \
                                                                                                                                                                                                                                                                                int32_t: integer_number_to_string_i32, \
                                                                                                                                                                                                                                                                                default: integer_number_to_string_i32 \
                                                                                                                                                                                                                                                )(_input_number, _leader_character, _display_width, _numeric_string, _array_len)

#define floating_number_to_string(_input_number, _decimal_digits, _numeric_string, _array_len) _Generic(_input_number, float: floating_number_to_string_f, \
                                                                                                                       double: floating_number_to_string_d, \
                                                                                                                                                                                                                                       default: floating_number_to_string_f \
                                                                                                                                                                                                           )(_input_number, _decimal_digits, _numeric_string, _array_len)
*/

//Begin GCC Overload
#define max(_a, _b) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), int8_t), max_i8(_a, _b), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), uint8_t), max_ui8(_a, _b), \
          __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), int16_t), max_i16(_a, _b), \
           __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), uint16_t), max_ui16(_a, _b), \
            __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), int32_t), max_i32(_a, _b), \
             __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), uint32_t), max_ui32(_a, _b), \
              __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), int64_t), max_i64(_a, _b), \
               __builtin_choose_expr(__builtin_types_compatible_p(typeof(sizeof(_a) >= sizeof(_b) ? _a : _b), uint64_t), max_ui64(_a, _b), \
                                                                                                                         max_i64(_a, _b) \
                                    ) \
                                   ) \
                                  ) \
                                 ) \
                                ) \
                               ) \
                              ) \
                             )

#define read_bit(_source_bits, _source_width, _n) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint8_t), read_bit_ui8(_source_bits, _source_width, _n), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint16_t), read_bit_ui16(_source_bits, _source_width, _n), \
          __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint32_t), read_bit_ui32(_source_bits, _source_width, _n), \
           __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint64_t), read_bit_ui64(_source_bits, _source_width, _n), \
                                                                                               read_bit_ui64(_source_bits, _source_width, _n) \
                                                                ) \
                                                           ) \
                                                          ) \
                                                         )
                                                         
#define write_bit(_source_bits, _source_width, _n, _a_bit) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint8_t), write_bit_ui8(_source_bits, _source_width, _n, _a_bit), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint16_t), write_bit_ui16(_source_bits, _source_width, _n, _a_bit), \
          __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint32_t), write_bit_ui32(_source_bits, _source_width, _n, _a_bit), \
           __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint64_t), write_bit_ui64(_source_bits, _source_width, _n, _a_bit), \
                                                                                               write_bit_ui64(_source_bits, _source_width, _n, _a_bit) \
                                ) \
                               ) \
                              ) \
                             )

#define xor_bit(_source_bits, _source_width, _n, _a_bit) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint8_t), xor_bit_ui8(_source_bits, _source_width, _n, _a_bit), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint16_t), xor_bit_ui16(_source_bits, _source_width, _n, _a_bit), \
          __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint32_t), xor_bit_ui32(_source_bits, _source_width, _n, _a_bit), \
           __builtin_choose_expr(__builtin_types_compatible_p(typeof(_source_bits), uint64_t), xor_bit_ui64(_source_bits, _source_width, _n, _a_bit), \
                                                                                               xor_bit_ui64(_source_bits, _source_width, _n, _a_bit) \
                                ) \
                               ) \
                              ) \
                             )

#define random_round(_x, _rounded_to_exp10) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_x), float), random_round_f(_x, _rounded_to_exp10), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_x),double), random_round_d(_x, _rounded_to_exp10), \
                                                                                random_round_f(_x, _rounded_to_exp10) \
                              ) \
                             )

#define integer_number_to_string(_input_number, _leader_character, _display_width, _numeric_string, _array_len) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_input_number), int8_t), integer_number_to_string_i8(_input_number, _leader_character, _display_width, _numeric_string, _array_len), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_input_number), int16_t), integer_number_to_string_i16(_input_number, _leader_character, _display_width, _numeric_string, _array_len), \
          __builtin_choose_expr(__builtin_types_compatible_p(typeof(_input_number), int32_t), integer_number_to_string_i32(_input_number, _leader_character, _display_width, _numeric_string, _array_len), \
                                                                                              integer_number_to_string_i32(_input_number, _leader_character, _display_width, _numeric_string, _array_len)) \
                               ) \
                              ) \
                             )

#define floating_number_to_string(_input_number, _decimal_digits, _numeric_string, _array_len) \
        __builtin_choose_expr(__builtin_types_compatible_p(typeof(_input_number), float), floating_number_to_string_f(_input_number, _decimal_digits, _numeric_string, _array_len), \
         __builtin_choose_expr(__builtin_types_compatible_p(typeof(_input_number),double), floating_number_to_string_d(_input_number, _decimal_digits, _numeric_string, _array_len), \
                                                                                           floating_number_to_string_f(_input_number, _decimal_digits, _numeric_string, _array_len) \
                              ) \
                             )
//End GCC Overload.

inline int8_t max_i8(int8_t a, int8_t b)
{
        return a > b ? a : b;
}

inline uint8_t max_ui8(uint8_t a, uint8_t b)
{
        return a > b ? a : b;
}

inline int16_t max_i16(int16_t a, int16_t b)
{
        return a > b ? a : b;
}

inline uint16_t max_ui16(uint16_t a, uint16_t b)
{
        return a > b ? a : b;
}

inline int32_t max_i32(int32_t a, int32_t b)
{
        return a > b ? a : b;
}

inline uint32_t max_ui32(uint32_t a, uint32_t b)
{
        return a > b ? a : b;
}

inline int64_t max_i64(int64_t a, int64_t b)
{
        return a > b ? a : b;
}

inline uint64_t max_ui64(uint64_t a, uint64_t b)
{
        return a > b ? a : b;
}

uint8_t read_bit_ui8(uint8_t source_bits, uint_fast8_t source_width, uint_fast8_t n)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 8;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        return (source_bits >> n) bitand ((uint8_t)0x01);
}

uint16_t read_bit_ui16(uint16_t source_bits, uint_fast8_t source_width, uint_fast8_t n)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 16;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        return (source_bits >> n) bitand ((uint16_t)0x01);
}

uint32_t read_bit_ui32(uint32_t source_bits, uint_fast8_t source_width, uint_fast8_t n)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 32;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        return (source_bits >> n) bitand ((uint32_t)0x01);
}

uint64_t read_bit_ui64(uint64_t source_bits, uint_fast8_t source_width, uint_fast8_t n)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 64;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        return (source_bits >> n) bitand ((uint64_t)0x01);
}

uint8_t write_bit_ui8(uint8_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 8;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        (a_bit == 0) ? (source_bits and_eq (compl(((uint8_t)0x01) << n))) : (source_bits or_eq (((uint8_t)0x01) << n));
        return source_bits;
}

uint16_t write_bit_ui16(uint16_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 16;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        (a_bit == 0) ? (source_bits and_eq (compl(((uint16_t)0x01) << n))) : (source_bits or_eq (((uint16_t)0x01) << n));
        return source_bits;
}

uint32_t write_bit_ui32(uint32_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 32;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        (a_bit == 0) ? (source_bits and_eq (compl(((uint32_t)0x01) << n))) : (source_bits or_eq (((uint32_t)0x01) << n));
        return source_bits;
}

uint64_t write_bit_ui64(uint64_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 64;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        (a_bit == 0) ? (source_bits and_eq (compl(((uint64_t)0x01) << n))) : (source_bits or_eq (((uint64_t)0x01) << n));
        return source_bits;
}

uint8_t xor_bit_ui8(uint8_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 8;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        return source_bits xor (((uint8_t)a_bit) << n);
}

uint16_t xor_bit_ui16(uint16_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 16;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        return source_bits xor (((uint16_t)a_bit) << n);
}

uint32_t xor_bit_ui32(uint32_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 32;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        return source_bits xor (((uint32_t)a_bit) << n);
}

uint64_t xor_bit_ui64(uint64_t source_bits, uint_fast8_t source_width, uint_fast8_t n, uint_fast8_t a_bit)  //Lowest order is 0
{
        const uint_fast8_t MAXIMUM_WIDTH_BIT = 64;
       
        if ((source_bits >> source_width) not_eq 0)
        {
                return source_bits;
        }
        if (source_width > MAXIMUM_WIDTH_BIT)
        {
                return source_bits;
        }
        if (n >= source_width)
        {
                return source_bits;
        }
        if ((a_bit >> 1) not_eq 0)
        {
                return source_bits;
        }
        return source_bits xor (((uint64_t)a_bit) << n);
}

float random_round_f(float x, int_fast8_t rounded_to_exp10)
{
        const uint_fast8_t MAX_SIGNIFICANT_FIGURES = FLT_DIG - 1;
       
        if (not isfinite(x))
        {
                return x;
        }
        float absolute_value = fabs(x);
        if ((floor(log10(absolute_value)) - rounded_to_exp10) >= MAX_SIGNIFICANT_FIGURES)
        {
                return x;
        }
       
        float integer_part, decimal_part;
        decimal_part = modff(absolute_value * pow(10, -rounded_to_exp10), &integer_part);
        if (decimal_part > 0.5)
        {
                integer_part += 1;
        }
        else
        {
                if (decimal_part == 0.5)
                {
                        integer_part += rand() % 2;
                }
        }
        return copysign((integer_part + 0.1) * pow(10, rounded_to_exp10), x);
}

double random_round_d(double x, int_fast8_t rounded_to_exp10)
{
        const uint_fast8_t MAX_SIGNIFICANT_FIGURES = DBL_DIG - 1;
       
        if (not isfinite(x))
        {
                return x;
        }
        double absolute_value = fabs(x);
        if ((floor(log10(absolute_value)) - rounded_to_exp10) >= MAX_SIGNIFICANT_FIGURES)
        {
                return x;
        }
       
        double integer_part, decimal_part;
        decimal_part = modf(absolute_value * pow(10, -rounded_to_exp10), &integer_part);
        if (decimal_part > 0.5)
        {
                integer_part += 1;
        }
        else
        {
                if (decimal_part == 0.5)
                {
                        integer_part += rand() % 2;
                }
        }
        return copysign((integer_part + 0.1) * pow(10, rounded_to_exp10), x);
}

uint_fast8_t integer_number_to_string_i8(int8_t input_number, char leader_character, uint_fast8_t display_width, char numeric_string[], uint_fast8_t array_len)  //input_number range is INT8_MAX to INT8_MIN. Returns the numeric string length.
{
        const uint_fast8_t INTERMEDIATE_MAX_WIDTH = 1 + (floor(log10(-INT8_MIN)) + 1);  //sign + Max significant figures
       
        char intermediate_string[INTERMEDIATE_MAX_WIDTH + 1];
       
        if (leader_character < '\x0')
        {
                return 0;
        }
        if (display_width >= array_len)
        {
                return 0;
        }
        if (array_len <= 1)
        {
                return 0;
        }
       
        int_fast8_t intermediate_len = sprintf(intermediate_string, "%-"PRIi8, input_number);
        if (intermediate_len > display_width)
        {
                return 0;
        }

        int_fast8_t i = 0;
        int_fast8_t n = display_width - (intermediate_len + 1);
        if (isgraph(leader_character))
        {
                while (i <= n)
                {
                        numeric_string = leader_character;
                        ++i;
                }
        }
        n = i + intermediate_len;
        int_fast8_t j = 0;
        while (i <= n)
        {
                numeric_string = intermediate_string[j];
                ++i;
                ++j;
        }
        i -= 1;
        return i;  //Returns the numeric string length
}

uint_fast8_t integer_number_to_string_i16(int16_t input_number, char leader_character, uint_fast8_t display_width, char numeric_string[], uint_fast8_t array_len)  //input_number range is INT16_MAX to INT16_MIN. Returns the numeric string length.
{
        const uint_fast8_t INTERMEDIATE_MAX_WIDTH = 1 + (floor(log10(-(float)INT16_MIN)) + 1);  //sign + Max significant figures
       
        char intermediate_string[INTERMEDIATE_MAX_WIDTH + 1];
       
        if (leader_character < '\x0')
        {
                return 0;
        }
        if (display_width >= array_len)
        {
                return 0;
        }
        if (array_len <= 1)
        {
                return 0;
        }
       
        int_fast8_t intermediate_len = sprintf(intermediate_string, "%-"PRIi16, input_number);
        if (intermediate_len > display_width)
        {
                return 0;
        }

        int_fast8_t i = 0;
        int_fast8_t n = display_width - (intermediate_len + 1);
        if (isgraph(leader_character))
        {
                while (i <= n)
                {
                        numeric_string = leader_character;
                        ++i;
                }
        }
        n = i + intermediate_len;
        int_fast8_t j = 0;
        while (i <= n)
        {
                numeric_string = intermediate_string[j];
                ++i;
                ++j;
        }
        i -= 1;
        return i;  //Returns the numeric string length
}

uint_fast8_t integer_number_to_string_i32(int32_t input_number, char leader_character, uint_fast8_t display_width, char numeric_string[], uint_fast8_t array_len)  //input_number range is INT32_MAX to INT32_MIN. Returns the numeric string length.
{
        const uint_fast8_t INTERMEDIATE_MAX_WIDTH = 1 + (floor(log10(-(double)INT32_MIN)) + 1);  //sign + Max significant figures
       
        char intermediate_string[INTERMEDIATE_MAX_WIDTH + 1];
       
        if (leader_character < '\x0')
        {
                return 0;
        }
        if (display_width >= array_len)
        {
                return 0;
        }
        if (array_len <= 1)
        {
                return 0;
        }
       
        int_fast8_t intermediate_len = sprintf(intermediate_string, "%-"PRIi32, input_number);
        if (intermediate_len > display_width)
        {
                return 0;
        }

        int_fast8_t i = 0;
        int_fast8_t n = display_width - (intermediate_len + 1);
        if (isgraph(leader_character))
        {
                while (i <= n)
                {
                        numeric_string = leader_character;
                        ++i;
                }
        }
        n = i + intermediate_len;
        int_fast8_t j = 0;
        while (i <= n)
        {
                numeric_string = intermediate_string[j];
                ++i;
                ++j;
        }
        i -= 1;
        return i;  //Returns the numeric string length
}

uint_fast8_t floating_number_to_string_f(float input_number, uint_fast8_t decimal_digits, char numeric_string[], uint_fast8_t array_len)  //input_number range is (pow(10, MAX_SIGNIFICANT_FIGURES) - 1) to pow(10, -MIN_DECIMAL). Returns the numeric string length. The random roundoff, pay attention to the random number seed.
{
        const uint_fast8_t MAX_SIGNIFICANT_FIGURES = FLT_DIG - 1;
        const uint_fast8_t MIN_DECIMAL = MAX_SIGNIFICANT_FIGURES + 1;
       
        char temp_string[1 + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + 1), (1 + 1 + MIN_DECIMAL))) + 1];  //a sign + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + a decimal), (a zero + a decimal + MIN_DECIMAL))) + '\x0'
        float absolute_value;
        float num_exp10;

        if (not isfinite(input_number))
        {
                return 0;
        }
        if (decimal_digits > MIN_DECIMAL)
        {
                return 0;
        }
       
        absolute_value = fabs(input_number);
        num_exp10 = floor(log10(absolute_value));
        if (num_exp10 >= MAX_SIGNIFICANT_FIGURES)
        {  //Value ultra range error
                return 0;
        }
        float num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
        input_number = random_round_d(absolute_value, lround(num_tail_exp10));
       
        absolute_value = fabs(input_number);
        num_exp10 = floor(log10(absolute_value));
        int_fast8_t num_int_exp10 = lround(num_exp10);
        if (num_int_exp10 >= MAX_SIGNIFICANT_FIGURES)
        {  //Value ultra range error
                return 0;
        }
        num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
        int_fast8_t num_int_tail_exp10 = lround(num_tail_exp10);
        if (num_int_tail_exp10 > num_int_exp10)
        {
                num_exp10 = num_tail_exp10;
                num_int_exp10 = num_int_tail_exp10;
        }
       
        uint_fast8_t num_count = num_int_exp10 - num_int_tail_exp10 + 1;
        float intermediate_number = absolute_value * pow(10, -num_exp10);
        float digital_character[num_count];
        for (int_fast8_t i = 0; i < num_count; ++i)
        {
                intermediate_number = modff(intermediate_number, &digital_character) * 10;
        }
       
        int_fast8_t i = 0;
        uint_fast8_t n;
        if ((input_number < 0 ? 1 : 0) == 1)
        {
                temp_string = '-'; ++i;
        }
        int_fast8_t j = 0;
        if (num_int_exp10 >= 0)
        {
                n = i + num_int_exp10;
                while(i <= n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
                if ((num_int_tail_exp10 < 0 ? 1 : 0) == 1)
                {
                        temp_string = '.'; ++i;
                }
                n = i + abs(num_int_tail_exp10);
                while(i < n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
        }
        else
        {
                temp_string = '0'; ++i;
                temp_string = '.'; ++i;
                n = i + (-1 - num_int_exp10);
                while(i < n)
                {
                        temp_string = '0'; ++i;
                }
                n = i + (num_int_exp10 - num_int_tail_exp10);
                while(i <= n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
        }
        temp_string = '\x0';
        n = i;
        if ((n + 1) > array_len)
        {
                return 0;
        }
        for (i=0; i <= n; ++i)
        {
                numeric_string = temp_string;
        }
        return n;  //Returns the numeric string length
}

uint_fast8_t floating_number_to_string_d(double input_number, uint_fast8_t decimal_digits, char numeric_string[], uint_fast8_t array_len)  //input_number range is (pow(10, MAX_SIGNIFICANT_FIGURES) - 1) to pow(10, -MIN_DECIMAL). Returns the numeric string length. The random roundoff, pay attention to the random number seed.
{
        const uint_fast8_t MAX_SIGNIFICANT_FIGURES = DBL_DIG - 1;
        const uint_fast8_t MIN_DECIMAL = MAX_SIGNIFICANT_FIGURES + 1;
       
        char temp_string[1 + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + 1), (1 + 1 + MIN_DECIMAL))) + 1];  //a sign + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + a decimal), (a zero + a decimal + MIN_DECIMAL))) + '\x0'
        double absolute_value;
        double num_exp10;

        if (not isfinite(input_number))
        {
                return 0;
        }
        if (decimal_digits > MIN_DECIMAL)
        {
                return 0;
        }
       
        absolute_value = fabs(input_number);
        num_exp10 = floor(log10(absolute_value));
        if (num_exp10 >= MAX_SIGNIFICANT_FIGURES)
        {  //Value ultra range error
                return 0;
        }
        double num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
        input_number = random_round_d(absolute_value, lround(num_tail_exp10));
       
        absolute_value = fabs(input_number);
        num_exp10 = floor(log10(absolute_value));
        int_fast8_t num_int_exp10 = lround(num_exp10);
        if (num_int_exp10 >= MAX_SIGNIFICANT_FIGURES)
        {  //Value ultra range error
                return 0;
        }
        num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
        int_fast8_t num_int_tail_exp10 = lround(num_tail_exp10);
        if (num_int_tail_exp10 > num_int_exp10)
        {
                num_exp10 = num_tail_exp10;
                num_int_exp10 = num_int_tail_exp10;
        }
       
        uint_fast8_t num_count = num_int_exp10 - num_int_tail_exp10 + 1;
        double intermediate_number = absolute_value * pow(10, -num_exp10);
        double digital_character[num_count];
        for (int_fast8_t i = 0; i < num_count; ++i)
        {
                intermediate_number = modf(intermediate_number, &digital_character) * 10;
        }
       
        int_fast8_t i = 0;
        uint_fast8_t n;
        if ((input_number < 0 ? 1 : 0) == 1)
        {
                temp_string = '-'; ++i;
        }
        int_fast8_t j = 0;
        if (num_int_exp10 >= 0)
        {
                n = i + num_int_exp10;
                while(i <= n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
                if ((num_int_tail_exp10 < 0 ? 1 : 0) == 1)
                {
                        temp_string = '.'; ++i;
                }
                n = i + abs(num_int_tail_exp10);
                while(i < n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
        }
        else
        {
                temp_string = '0'; ++i;
                temp_string = '.'; ++i;
                n = i + (-1 - num_int_exp10);
                while(i < n)
                {
                        temp_string = '0'; ++i;
                }
                n = i + (num_int_exp10 - num_int_tail_exp10);
                while(i <= n)
                {
                        temp_string = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
                        ++i;
                        ++j;
                }
        }
        temp_string = '\x0';
        n = i;
        if ((n + 1) > array_len)
        {
                return 0;
        }
        for (i=0; i <= n; ++i)
        {
                numeric_string = temp_string;
        }
        return n;  //Returns the numeric string length
}
======================================
这样写出来的代码,以后换16位msp430也好换32位ARM也好,都不用修改调用代码
用防御式编程,可以更容易定位错误

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2012-9-23 20:57:31 | 显示全部楼层
高手,佩服
回复 支持 反对

使用道具 举报

发表于 2012-9-23 22:13:19 | 显示全部楼层
这个小白真心看不懂了。。。。。。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-9-23 22:41:02 | 显示全部楼层
简单说就是C写法的函数重载
一个函数分别写好8位版16位版32位版
编译时根据类型自动选择用的版本
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-13 02:45:18 | 显示全部楼层
为更方便大家应用,变更了开源许可证
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-28 13:28 , Processed in 0.041867 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表