原生结果series通过字节索引直传,C端使用Ryu精确回读编码和64 KiB批量写出;网页采用Float64缓存和CSV工作线程,减少结果处理与保存等待。 补充八路AME曲线核查、全流程分阶段计时、独立编码基准和复现工具,固定后续优化采用修正八路及rtol=1e-8。C写出1.1808→0.1638 s,点击到可查看8.0100→6.9756 s。 验证:最终10项编码专项、29项相关后端回归通过;8份原生结果逐位一致,16次网页结果/CSV/刷新恢复通过。前端构建及缓存/CSV专项在本轮结果处理工作中通过。环境、原始大结果与临时构建不纳入Git。
84 lines
3.0 KiB
C
84 lines
3.0 KiB
C
#include "json_numbers.h"
|
|
#include "ryu/ryu.h"
|
|
#include <float.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
_Static_assert(sizeof(double)==8 && DBL_MANT_DIG==53 && DBL_MAX_EXP==1024,
|
|
"Native JSON numbers require IEEE-754 binary64");
|
|
|
|
int native_json_format_double(char output[NATIVE_JSON_DOUBLE_CAPACITY], double value) {
|
|
uint64_t bits;
|
|
memcpy(&bits,&value,sizeof(bits));
|
|
uint64_t magnitude=bits & UINT64_C(0x7fffffffffffffff);
|
|
if (magnitude>=UINT64_C(0x7ff0000000000000)) return 0;
|
|
if (magnitude==0) {
|
|
if (bits>>63) { memcpy(output,"-0.0",4); return 4; }
|
|
output[0]='0'; return 1;
|
|
}
|
|
int length=d2s_buffered_n(value,output);
|
|
/* Ryu returns shortest significant digits in scientific notation. Use
|
|
ordinary notation only when its JSON token is shorter. This moves an
|
|
exact decimal point; it never recomputes or rounds the floating value. */
|
|
char digits[17];
|
|
int negative=output[0]=='-', count=0, pos=negative;
|
|
while (output[pos]!='E') {
|
|
if (output[pos]!='.') digits[count++]=output[pos];
|
|
pos++;
|
|
}
|
|
pos++;
|
|
int exponent_negative=output[pos]=='-';
|
|
if (exponent_negative) pos++;
|
|
int exponent=0;
|
|
while (pos<length) exponent=exponent*10+(output[pos++]-'0');
|
|
if (exponent_negative) exponent=-exponent;
|
|
int point=exponent+1;
|
|
int fixed_length=negative+(point<=0 ? 2-point+count : point>=count ? point : count+1);
|
|
if (fixed_length>=length) return length;
|
|
pos=0;
|
|
if (negative) output[pos++]='-';
|
|
if (point<=0) {
|
|
output[pos++]='0'; output[pos++]='.';
|
|
for (int i=0;i<-point;i++) output[pos++]='0';
|
|
memcpy(output+pos,digits,(size_t)count); pos+=count;
|
|
} else {
|
|
for (int i=0;i<count;i++) {
|
|
if (i==point) output[pos++]='.';
|
|
output[pos++]=digits[i];
|
|
}
|
|
for (int i=count;i<point;i++) output[pos++]='0';
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
static int write_bytes(FILE *file, const char *data, size_t length) {
|
|
return fwrite(data,1,length,file)==length && !ferror(file);
|
|
}
|
|
|
|
int native_json_write_number(FILE *file, double value) {
|
|
if (!file || ferror(file)) return 0;
|
|
char text[NATIVE_JSON_DOUBLE_CAPACITY];
|
|
int length=native_json_format_double(text,value);
|
|
return length>0 && write_bytes(file,text,(size_t)length);
|
|
}
|
|
|
|
int native_json_write_array(FILE *file, const double *values, size_t count, size_t stride) {
|
|
if (!file || ferror(file) || (count && !values)) return 0;
|
|
if (count>1 && (!stride || stride>(size_t)PTRDIFF_MAX/sizeof(double)/(count-1))) return 0;
|
|
char buffer[65536];
|
|
size_t used=1;
|
|
buffer[0]='[';
|
|
for (size_t i=0;i<count;i++) {
|
|
if (used>sizeof(buffer)-NATIVE_JSON_DOUBLE_CAPACITY-2) {
|
|
if (!write_bytes(file,buffer,used)) return 0;
|
|
used=0;
|
|
}
|
|
if (i) buffer[used++]=',';
|
|
int length=native_json_format_double(buffer+used,values[i*stride]);
|
|
if (!length) return 0;
|
|
used+=(size_t)length;
|
|
}
|
|
buffer[used++]=']';
|
|
return write_bytes(file,buffer,used);
|
|
}
|