Subversion Repositories shark

Rev

Rev 1619 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/* Project:     OSLib
2
 * Description: The OS Construction Kit
3
 * Date:                1.6.2000
4
 * Idea by:             Luca Abeni & Gerardo Lamastra
5
 *
6
 * OSLib is an SO project aimed at developing a common, easy-to-use
7
 * low-level infrastructure for developing OS kernels and Embedded
8
 * Applications; it partially derives from the HARTIK project but it
9
 * currently is independently developed.
10
 *
11
 * OSLib is distributed under GPL License, and some of its code has
12
 * been derived from the Linux kernel source; also some important
13
 * ideas come from studying the DJGPP go32 extender.
14
 *
15
 * We acknowledge the Linux Community, Free Software Foundation,
16
 * D.J. Delorie and all the other developers who believe in the
17
 * freedom of software and ideas.
18
 *
19
 * For legalese, check out the included GPL license.
20
 */
21
 
1621 fabio 22
#include <arch/i386/stdlib.h>
23
#include <arch/i386/string.h>
24
#include <arch/i386/limits.h>
25
#include <arch/i386/float.h>
2 pj 26
#include <ll/i386/mem.h>
1621 fabio 27
#include <arch/stdarg.h>
28
#include <arch/ctype.h>
29
#include <arch/math.h>
2 pj 30
#include "sprintf.h"
31
 
32
FILE(fcvt);
33
 
34
unsigned fcvt(double v,char *buffer,int width,int prec,int flag)
35
{
36
    double ip,fp,val;
37
    register int l=0;
38
    register int digits;
39
    int conv,got_a_digit,exceeded,len = 0;
40
    char tmp[300];
41
    memset(tmp,0,300);
42
    /* Manage Inf & NaN */
43
    if (isspecial(v,buffer)) return(strlen(buffer));
44
    /* Check for negative value & add optional + sign */
45
    if (v < 0) {
46
        *buffer++ = '-';
47
        v = -v;
48
        len++;
49
    } else if (flag & ADD_PLUS) {
50
        *buffer++ = '+';
51
        len++;
52
    }
53
    /* Extract integer part & mantissa */
54
    fp = modf(v,&ip);
55
    /* Process integer part */
56
    digits = 0;
57
    if (ip >= 1.0) {
58
        while (ip >= 1.0) {
59
            /* The 0.01 here is used to correct rounding errors*/
60
            /* Ex: 1.2 --> 1.1999999999999... adjust to 1.2 */
61
            /*
62
            ip = ip / 10.0;
63
            modf(ip,&val);
64
            val = (ip - val)*10.0;
65
            */
66
            val = fmod(ip,10.0);
67
            ip = ip / 10.0;
68
            tmp[digits++] = todigit((unsigned)(val));
69
        }
70
        len += digits;
71
        /* Now reverse the temporary buffer into output buffer  */
72
        /* Translate only the last 15 digits                    */
73
        /* The others are beyond double precision limit!        */     
74
        for (l = digits-1; l >= max(digits-15,0); l--) *buffer++ = tmp[l];
75
        if (l >= 0) for (l = digits-16; l >= 0; l--) *buffer++ = '0';
76
        *buffer = 0;
77
    /* If IP == 0 -> just put in a 0 */
78
    } else {
79
        *buffer++ = '0';
80
        len++;
81
    }
82
    /* Process fractionary part according to width specification */
83
    /* If RESPECT_WIDTH is set, scan until you reach wanted precision */
84
    /* Else scan until you find a not 0 digit */
85
    if (fp > 1e-307 && len < width+1) {
86
        *buffer++ = '.';
87
        len++;
88
        if (flag & RESPECT_WIDTH) got_a_digit = 1;
89
        else got_a_digit = 0;
90
        exceeded = 0;
91
        digits = 1;
92
        while (!exceeded) {
93
            /* The DBL_EPSILON here is used to correct rounding errors */
94
            fp = (fp + DBL_EPSILON) * 10.0;
95
            fp = modf(fp,&ip);
96
            conv = (int)(ip);
97
            if (conv != 0 && !got_a_digit) got_a_digit = 1;
98
            *buffer++ = todigit(conv);
99
            len++;
100
            digits++;
101
            if (got_a_digit && (digits > prec)) exceeded = 1;
102
            if (width < len) exceeded = 1;
103
        }
104
        /* Drop trailing zeros after decimal point */
105
        while (*--buffer == '0' && *(buffer-1) != '.') len--;
106
        buffer++;
107
    }
108
    *buffer = 0;
109
    return(len);
110
}
111
 
112