mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Add fixes performance and static web server
This commit is contained in:
parent
b6793d42d5
commit
c45e46f871
108 changed files with 2927 additions and 819 deletions
128
libc/fmt/fcvt.c
Normal file
128
libc/fmt/fcvt.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2009 Ian Piumarta │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
||||
│ of this software and associated documentation files (the 'Software'), to │
|
||||
│ deal in the Software without restriction, including without limitation the │
|
||||
│ rights to use, copy, modify, merge, publish, distribute, and/or sell copies │
|
||||
│ of the Software, and to permit persons to whom the Software is furnished to │
|
||||
│ do so, provided that the above copyright notice(s) and this permission │
|
||||
│ notice appear in all copies of the Software. Inclusion of the above │
|
||||
│ copyright notice(s) and this permission notice in supporting documentation │
|
||||
│ would be appreciated but is not required. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
ecvt, fcvt (MIT License)\\n\
|
||||
Copyright 2009 Ian Piumarta\"");
|
||||
|
||||
/**
|
||||
* @fileoverview Replacements for the functions ecvt() and fcvt()
|
||||
*
|
||||
* These functions were recently deprecated in POSIX. The interface and
|
||||
* behaviour is identical to the functions that they replace and faster.
|
||||
*
|
||||
* For details on the use of these functions, see your ecvt(3) manual
|
||||
* page. If you don't have one handy, there might still be one available
|
||||
* here: http://opengroup.org/onlinepubs/007908799/xsh/ecvt.html
|
||||
*
|
||||
* @see https://www.piumarta.com/software/fcvt/
|
||||
*/
|
||||
|
||||
static char *Fcvt(double value, int ndigit, int *decpt, int *sign, int fflag) {
|
||||
static char buf[128];
|
||||
double i;
|
||||
uint64_t l, mant;
|
||||
int exp2, exp10, ptr;
|
||||
memcpy(&l, &value, 8);
|
||||
exp2 = (0x7ff & (l >> 52)) - 1023;
|
||||
mant = l & 0x000fffffffffffffULL;
|
||||
if ((*sign = l >> 63)) value = -value;
|
||||
if (exp2 == 0x400) {
|
||||
*decpt = 0;
|
||||
return mant ? "nan" : "inf";
|
||||
}
|
||||
exp10 = (value == 0) ? !fflag : (int)ceil(log10(value));
|
||||
if (exp10 < -307) exp10 = -307; /* otherwise overflow in pow() */
|
||||
value *= pow(10.0, -exp10);
|
||||
if (value) {
|
||||
while (value < 0.1) {
|
||||
value *= 10;
|
||||
--exp10;
|
||||
}
|
||||
while (value >= 1.0) {
|
||||
value /= 10;
|
||||
++exp10;
|
||||
}
|
||||
}
|
||||
assert(value == 0 || (0.1 <= value && value < 1.0));
|
||||
if (fflag) {
|
||||
if (ndigit + exp10 < 0) {
|
||||
*decpt = -ndigit;
|
||||
return "";
|
||||
}
|
||||
ndigit += exp10;
|
||||
}
|
||||
*decpt = exp10;
|
||||
if (ARRAYLEN(buf) < ndigit + 2) abort();
|
||||
ptr = 1;
|
||||
#if 0 /* slow and safe (and dreadfully boring) */
|
||||
while (ptr <= ndigit) {
|
||||
i;
|
||||
value = modf(value * 10, &i);
|
||||
buf[ptr++] = '0' + (int)i;
|
||||
}
|
||||
if (value >= 0.5) {
|
||||
while (--ptr && ++buf[ptr] > '9') {
|
||||
buf[ptr] = '0';
|
||||
}
|
||||
}
|
||||
#else /* faster */
|
||||
memcpy(&l, &value, 8);
|
||||
exp2 = (0x7ff & (l >> 52)) - 1023;
|
||||
assert(value == 0 || (-4 <= exp2 && exp2 <= -1));
|
||||
mant = l & 0x000fffffffffffffULL;
|
||||
if (exp2 == -1023) {
|
||||
++exp2;
|
||||
} else {
|
||||
mant |= 0x0010000000000000ULL;
|
||||
}
|
||||
mant <<= (exp2 + 4); /* 56-bit denormalised signifier */
|
||||
while (ptr <= ndigit) {
|
||||
mant &= 0x00ffffffffffffffULL; /* mod 1.0 */
|
||||
mant = (mant << 1) + (mant << 3);
|
||||
buf[ptr++] = '0' + (mant >> 56);
|
||||
}
|
||||
if (mant & 0x0080000000000000ULL) /* 1/2 << 56 */
|
||||
while (--ptr && ++buf[ptr] > '9') buf[ptr] = '0';
|
||||
#endif
|
||||
if (ptr) {
|
||||
buf[ndigit + 1] = 0;
|
||||
return buf + 1;
|
||||
}
|
||||
if (fflag) {
|
||||
++ndigit;
|
||||
++*decpt;
|
||||
}
|
||||
buf[0] = '1';
|
||||
buf[ndigit] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *ecvt(double value, int ndigit, int *decpt, int *sign) {
|
||||
return Fcvt(value, ndigit, decpt, sign, 0);
|
||||
}
|
||||
|
||||
char *fcvt(double value, int ndigit, int *decpt, int *sign) {
|
||||
return Fcvt(value, ndigit, decpt, sign, 1);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue