mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +00:00
bugfix: 修复浮点数打印错误的bug
This commit is contained in:
parent
676260c537
commit
7670031b11
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -103,7 +103,8 @@
|
|||||||
"stddef.h": "c",
|
"stddef.h": "c",
|
||||||
"spinlock.h": "c",
|
"spinlock.h": "c",
|
||||||
"stat.h": "c",
|
"stat.h": "c",
|
||||||
"video.h": "c"
|
"video.h": "c",
|
||||||
|
"libm.h": "c"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "Enabled",
|
"C_Cpp.errorSquiggles": "Enabled",
|
||||||
"esbonio.sphinx.confDir": ""
|
"esbonio.sphinx.confDir": ""
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
kernel_common_subdirs:=libELF
|
kernel_common_subdirs:=libELF math
|
||||||
|
|
||||||
all: glib.o
|
all: glib.o
|
||||||
@list='$(kernel_common_subdirs)'; for subdir in $$list; do \
|
@list='$(kernel_common_subdirs)'; for subdir in $$list; do \
|
||||||
|
3
kernel/common/math.h
Normal file
3
kernel/common/math.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stddef.h"
|
||||||
|
int64_t pow(int64_t x, int y);
|
14
kernel/common/math/Makefile
Normal file
14
kernel/common/math/Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
CFLAGS += -I .
|
||||||
|
|
||||||
|
all: fabs.o round.o pow.o
|
||||||
|
|
||||||
|
fabs.o: fabs.c
|
||||||
|
gcc $(CFLAGS) -c fabs.c -o fabs.o
|
||||||
|
|
||||||
|
round.o: round.c
|
||||||
|
gcc $(CFLAGS) -c round.c -o round.o
|
||||||
|
|
||||||
|
pow.o: pow.c
|
||||||
|
gcc $(CFLAGS) -c pow.c -o pow.o
|
30
kernel/common/math/fabs.c
Normal file
30
kernel/common/math/fabs.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <common/math.h>
|
||||||
|
#include <common/sys/types.h>
|
||||||
|
#include "libm.h"
|
||||||
|
|
||||||
|
double fabs(double x)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
uint64_t i;
|
||||||
|
} u = {x};
|
||||||
|
u.i &= -1ULL / 2;
|
||||||
|
return u.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024
|
||||||
|
long double fabsl(long double x)
|
||||||
|
{
|
||||||
|
return fabs(x);
|
||||||
|
}
|
||||||
|
#elif (__LDBL_MANT_DIG__ == 64 || __LDBL_MANT_DIG__ == 113) && __LDBL_MAX_EXP__ == 16384
|
||||||
|
long double fabsl(long double x)
|
||||||
|
{
|
||||||
|
union ldshape u = {x};
|
||||||
|
|
||||||
|
u.i.se &= 0x7fff;
|
||||||
|
return u.f;
|
||||||
|
}
|
||||||
|
#endif
|
75
kernel/common/math/libm.h
Normal file
75
kernel/common/math/libm.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common/sys/types.h>
|
||||||
|
|
||||||
|
// ===== 描述long double 的数据比特结构
|
||||||
|
#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024
|
||||||
|
#elif __LDBL_MANT_DIG__ == 64 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
union ldshape
|
||||||
|
{
|
||||||
|
long double f;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t m;
|
||||||
|
uint16_t se;
|
||||||
|
} i;
|
||||||
|
};
|
||||||
|
#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
union ldshape
|
||||||
|
{
|
||||||
|
long double f;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t lo;
|
||||||
|
uint32_t mid;
|
||||||
|
uint16_t top;
|
||||||
|
uint16_t se;
|
||||||
|
} i;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t lo;
|
||||||
|
uint64_t hi;
|
||||||
|
} i2;
|
||||||
|
};
|
||||||
|
#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __BIG_ENDIAN
|
||||||
|
union ldshape
|
||||||
|
{
|
||||||
|
long double f;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t se;
|
||||||
|
uint16_t top;
|
||||||
|
uint32_t mid;
|
||||||
|
uint64_t lo;
|
||||||
|
} i;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t hi;
|
||||||
|
uint64_t lo;
|
||||||
|
} i2;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#error Unsupported long double representation
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FORCE_EVAL(x) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (sizeof(x) == sizeof(float)) \
|
||||||
|
{ \
|
||||||
|
volatile float __x; \
|
||||||
|
__x = (x); \
|
||||||
|
(void)__x; \
|
||||||
|
} \
|
||||||
|
else if (sizeof(x) == sizeof(double)) \
|
||||||
|
{ \
|
||||||
|
volatile double __x; \
|
||||||
|
__x = (x); \
|
||||||
|
(void)__x; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
volatile long double __x; \
|
||||||
|
__x = (x); \
|
||||||
|
(void)__x; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
10
kernel/common/math/pow.c
Normal file
10
kernel/common/math/pow.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <common/math.h>
|
||||||
|
#include <common/stddef.h>
|
||||||
|
|
||||||
|
int64_t pow(int64_t x, int y)
|
||||||
|
{
|
||||||
|
int64_t res = 1;
|
||||||
|
for (int i = 0; i < y; ++i)
|
||||||
|
res *= x;
|
||||||
|
return res;
|
||||||
|
}
|
43
kernel/common/math/round.c
Normal file
43
kernel/common/math/round.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "libm.h"
|
||||||
|
|
||||||
|
#if __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
|
||||||
|
#define EPS __DBL_EPSILON__
|
||||||
|
#elif __FLT_EVAL_METHOD__ == 2
|
||||||
|
#define EPS __LDBL_EPSILON__
|
||||||
|
#endif
|
||||||
|
static const double toint = 1 / EPS;
|
||||||
|
|
||||||
|
double round(double x)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
uint64_t i;
|
||||||
|
} u = {x};
|
||||||
|
|
||||||
|
int e = u.i >> 52 & 0x7ff;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
if (e >= 0x3ff + 52)
|
||||||
|
return x;
|
||||||
|
if (u.i >> 63)
|
||||||
|
x = -x;
|
||||||
|
if (e < 0x3ff - 1)
|
||||||
|
{
|
||||||
|
/* raise inexact if x!=0 */
|
||||||
|
FORCE_EVAL(x + toint);
|
||||||
|
return 0 * u.f;
|
||||||
|
}
|
||||||
|
y = x + toint - toint - x;
|
||||||
|
if (y > 0.5)
|
||||||
|
y = y + x - 1;
|
||||||
|
else if (y <= -0.5)
|
||||||
|
y = y + x + 1;
|
||||||
|
else
|
||||||
|
y = y + x;
|
||||||
|
if (u.i >> 63)
|
||||||
|
y = -y;
|
||||||
|
return y;
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <driver/uart/uart.h>
|
#include <driver/uart/uart.h>
|
||||||
#include <driver/video/video.h>
|
#include <driver/video/video.h>
|
||||||
|
#include "math.h"
|
||||||
//#include "linkage.h"
|
//#include "linkage.h"
|
||||||
|
|
||||||
struct printk_screen_info pos;
|
struct printk_screen_info pos;
|
||||||
@ -535,6 +535,7 @@ static char *write_num(char *str, ul num, int base, int field_width, int precisi
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags)
|
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -572,11 +573,11 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
|
|||||||
if (sign)
|
if (sign)
|
||||||
--field_width;
|
--field_width;
|
||||||
|
|
||||||
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
|
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
|
||||||
ul num_z = (ul)(num); // 获取整数部分
|
uint64_t num_z = (uint64_t)(num); // 获取整数部分
|
||||||
ul num_decimal = (ul)(round((num - num_z) * precision)); // 获取小数部分
|
uint64_t num_decimal = (uint64_t)(round(1.0*(num - num_z) * pow(10, precision))); // 获取小数部分
|
||||||
|
|
||||||
if (num == 0)
|
if (num == 0 || num_z == 0)
|
||||||
tmp_num_z[js_num_z++] = '0';
|
tmp_num_z[js_num_z++] = '0';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -605,18 +606,23 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
|
|||||||
*str++ = sign;
|
*str++ = sign;
|
||||||
|
|
||||||
// 输出整数部分
|
// 输出整数部分
|
||||||
while (js_num_z-- > 0)
|
// while (js_num_z-- > 0)
|
||||||
*str++ = tmp_num_z[js_num_z];
|
// *str++ = tmp_num_z[js_num_z];
|
||||||
|
while (js_num_z > 0)
|
||||||
|
{
|
||||||
|
*str++ = tmp_num_z[js_num_z - 1];
|
||||||
|
--js_num_z;
|
||||||
|
}
|
||||||
*str++ = '.';
|
*str++ = '.';
|
||||||
|
|
||||||
// 输出小数部分
|
// 输出小数部分
|
||||||
while (js_num_d-- > 0)
|
int total_dec_count = js_num_d;
|
||||||
|
for (int i = 0; i < precision && js_num_d-- > 0; ++i)
|
||||||
*str++ = tmp_num_d[js_num_d];
|
*str++ = tmp_num_d[js_num_d];
|
||||||
|
|
||||||
while (js_num_d < precision)
|
while (total_dec_count < precision)
|
||||||
{
|
{
|
||||||
--precision;
|
++total_dec_count;
|
||||||
*str++ = '0';
|
*str++ = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
run.sh
2
run.sh
@ -107,7 +107,7 @@ if [ $flag_can_run -eq 1 ]; then
|
|||||||
else
|
else
|
||||||
qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
|
qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
|
||||||
-boot order=d \
|
-boot order=d \
|
||||||
-monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu "IvyBridge,+apic,+x2apic,check,${allflags}" --enable-kvm -rtc clock=host,base=localtime -serial file:serial_opt.txt \
|
-monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu "IvyBridge,+apic,+x2apic,+fpu,check,${allflags}" --enable-kvm -rtc clock=host,base=localtime -serial file:serial_opt.txt \
|
||||||
-drive id=disk,file=bin/disk.img,if=none \
|
-drive id=disk,file=bin/disk.img,if=none \
|
||||||
-device ahci,id=ahci \
|
-device ahci,id=ahci \
|
||||||
-device ide-hd,drive=disk,bus=ahci.0 \
|
-device ide-hd,drive=disk,bus=ahci.0 \
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <libc/stdio.h>
|
#include <libc/stdio.h>
|
||||||
#include <libc/stdlib.h>
|
#include <libc/stdlib.h>
|
||||||
#include <libc/unistd.h>
|
#include <libc/unistd.h>
|
||||||
|
#include <libc/time.h>
|
||||||
|
#include <libc/math.h>
|
||||||
|
|
||||||
void print_ascii_logo()
|
void print_ascii_logo()
|
||||||
{
|
{
|
||||||
@ -26,11 +28,11 @@ int main()
|
|||||||
{
|
{
|
||||||
// printf("Hello World!\n");
|
// printf("Hello World!\n");
|
||||||
print_ascii_logo();
|
print_ascii_logo();
|
||||||
usleep(500000);
|
|
||||||
usleep(500000);
|
|
||||||
print_copyright();
|
print_copyright();
|
||||||
// exit(0);
|
// exit(0);
|
||||||
// while (1)
|
// while (1)
|
||||||
// ;
|
// ;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "stddef.h"
|
||||||
|
|
||||||
double fabs(double x);
|
double fabs(double x);
|
||||||
float fabsf(float x);
|
float fabsf(float x);
|
||||||
@ -7,4 +7,6 @@ long double fabsl(long double x);
|
|||||||
|
|
||||||
double round(double x);
|
double round(double x);
|
||||||
float roundf(float x);
|
float roundf(float x);
|
||||||
long double roundl(long double x);
|
long double roundl(long double x);
|
||||||
|
|
||||||
|
int64_t pow(int64_t x, int y);
|
@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
all: fabs.o round.o
|
|
||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
|
all: fabs.o round.o pow.o
|
||||||
|
|
||||||
fabs.o: fabs.c
|
fabs.o: fabs.c
|
||||||
gcc $(CFLAGS) -c fabs.c -o fabs.o
|
gcc $(CFLAGS) -c fabs.c -o fabs.o
|
||||||
|
|
||||||
round.o: round.c
|
round.o: round.c
|
||||||
gcc $(CFLAGS) -c round.c -o round.o
|
gcc $(CFLAGS) -c round.c -o round.o
|
||||||
|
|
||||||
|
pow.o: pow.c
|
||||||
|
gcc $(CFLAGS) -c pow.c -o pow.o
|
@ -1,6 +1,7 @@
|
|||||||
#include <libc/math.h>
|
#include <libc/math.h>
|
||||||
#include <libc/sys/types.h>
|
#include <libc/sys/types.h>
|
||||||
#include "libm.h"
|
#include "libm.h"
|
||||||
|
|
||||||
double fabs(double x)
|
double fabs(double x)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
|
10
user/libs/libc/math/pow.c
Normal file
10
user/libs/libc/math/pow.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "math.h"
|
||||||
|
#include <libc/stddef.h>
|
||||||
|
|
||||||
|
int64_t pow(int64_t x, int y)
|
||||||
|
{
|
||||||
|
int64_t res = 1;
|
||||||
|
for (int i = 0; i < y; ++i)
|
||||||
|
res *= x;
|
||||||
|
return res;
|
||||||
|
}
|
@ -9,7 +9,6 @@
|
|||||||
static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags);
|
static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags);
|
||||||
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags);
|
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags);
|
||||||
|
|
||||||
|
|
||||||
static int skip_and_atoi(const char **s)
|
static int skip_and_atoi(const char **s)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -323,10 +322,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
|
|||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
// 默认精度为3
|
// 默认精度为3
|
||||||
// printk("1111\n");
|
|
||||||
// va_arg(args, double);
|
|
||||||
// printk("222\n");
|
|
||||||
|
|
||||||
if (precision < 0)
|
if (precision < 0)
|
||||||
precision = 3;
|
precision = 3;
|
||||||
|
|
||||||
@ -497,11 +492,11 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
|
|||||||
if (sign)
|
if (sign)
|
||||||
--field_width;
|
--field_width;
|
||||||
|
|
||||||
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
|
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
|
||||||
uint64_t num_z = (uint64_t)(num); // 获取整数部分
|
uint64_t num_z = (uint64_t)(num); // 获取整数部分
|
||||||
uint64_t num_decimal = (uint64_t)(round((num - num_z) * precision)); // 获取小数部分
|
uint64_t num_decimal = (uint64_t)(round(1.0*(num - num_z) * pow(10, precision))); // 获取小数部分
|
||||||
|
|
||||||
if (num == 0)
|
if (num == 0 || num_z == 0)
|
||||||
tmp_num_z[js_num_z++] = '0';
|
tmp_num_z[js_num_z++] = '0';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -530,18 +525,23 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
|
|||||||
*str++ = sign;
|
*str++ = sign;
|
||||||
|
|
||||||
// 输出整数部分
|
// 输出整数部分
|
||||||
while (js_num_z-- > 0)
|
// while (js_num_z-- > 0)
|
||||||
*str++ = tmp_num_z[js_num_z];
|
// *str++ = tmp_num_z[js_num_z];
|
||||||
|
while (js_num_z > 0)
|
||||||
|
{
|
||||||
|
*str++ = tmp_num_z[js_num_z - 1];
|
||||||
|
--js_num_z;
|
||||||
|
}
|
||||||
*str++ = '.';
|
*str++ = '.';
|
||||||
|
|
||||||
// 输出小数部分
|
// 输出小数部分
|
||||||
while (js_num_d-- > 0)
|
int total_dec_count = js_num_d;
|
||||||
|
for (int i = 0; i < precision && js_num_d-- > 0; ++i)
|
||||||
*str++ = tmp_num_d[js_num_d];
|
*str++ = tmp_num_d[js_num_d];
|
||||||
|
|
||||||
while (js_num_d < precision)
|
while (total_dec_count < precision)
|
||||||
{
|
{
|
||||||
--precision;
|
++total_dec_count;
|
||||||
*str++ = '0';
|
*str++ = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user