#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "f00f.h"
const byte * const cijfer[] = {
"nul", "één", "twee", "drie", "vier",
"vijf", "zes", "zeven", "acht", "negen",
"tien", "elf", "twaalf", "dertien", "veertien",
"vijftien", "zestien", "zeventien", "achttien", "negentien"
};
const byte * const cijferordinaal[] = {
"nul", "eer", "twee", "der", "vier",
"vijf", "zes", "zeven", "acht", "negen",
"tien", "elf", "twaalf", "dertien", "veertien",
"vijftien", "zestien", "zeventien", "achttien", "negentien"
};
const byte * const tiental[] = {
"", "", "twintig", "dertig", "veertig",
"vijftig", "zestig", "zeventig", "tachtig", "negentig"
};
const byte * const factor[] = {
"", "duizend",
"miljoen", "miljard",
"biljoen", "biljard",
"triljoen", "triljard",
"quadriljoen", "quadriljard",
"quintiljoen", "quintiljard"
};
const byte * const voorvoegsel[] = {
"yocto", "zepto", "atto", "femto", "pico", "nano", "micro", "milli",
"",
"kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta"
};
const byte * const eenheid[NRDIMENSIES] = {
"meter",
"gram",
"seconde",
"ampère",
"kelvin",
"candela",
"mol",
"euro",
"bit",
"joule",
"volt",
"farad",
"pascal",
"hertz",
"ohm",
"tesla",
"newton",
"coulomb",
"watt",
"weber",
"becquerel",
"sievert",
"henry",
};
void spreek_honderdtal(splitbuf_t *spreek, int n) {
int h, t, c;
h = n / 100;
t = (n / 10) % 10;
c = n % 10;
if(t == 1) {
t = 0;
c += 10;
}
if(h) {
if(h != 1)
qstrcat(spreek, cijfer[h]);
qstrcat(spreek, "honderd");
}
if(t) {
if(c) {
qstrcat(spreek, cijfer[c]);
if(cijfer[c][strlen(cijfer[c]) - 1] == 'e')
qstrcat(spreek, "ën");
else
qstrcat(spreek, "en");
}
qstrcat(spreek, tiental[t]);
} else {
if(!(c == 0 && h != 0))
qstrcat(spreek, cijfer[c]);
}
}
int stukje_int(byte *stukje, int len) {
int i = 0;
while(len--) {
i *= 10;
i += *stukje++ - '0';
}
return i;
}
void spreek_geheel(splitbuf_t *spreek, byte *geheel) {
int l, e, x;
l = strlen(geheel) - 1;
if(!l && *geheel == '0') {
qstrcat(spreek, "nul");
return;
}
if(l == 3 && stukje_int(geheel, 2) > 10 && stukje_int(geheel + 1, 1)) {
spreek_honderdtal(spreek, stukje_int(geheel, 2));
qstrcat(spreek, "honderd");
l -= 2;
geheel += 2;
if(!stukje_int(geheel, 2))
l -= 5;
}
for(e = l / 3; e >= 0; e--) {
if(stukje_int(geheel, x = l % 3 + 1)) {
spreek_honderdtal(spreek, stukje_int(geheel, x));
qstrcat(spreek, factor[e]);
l -= x;
geheel += x;
}
}
}
void spreek_honderdtalordinaal(splitbuf_t *spreek, int n) {
int h, t, c;
const byte *e = "";
h = n / 100;
t = (n / 10) % 10;
c = n % 10;
if(t == 1) {
t = 0;
c += 10;
}
if(h) {
if(h != 1)
qstrcat(spreek, cijfer[h]);
qstrcat(spreek, e = "honderd");
}
if(t) {
if(c) {
qstrcat(spreek, cijfer[c]);
if(cijfer[c][strlen(cijfer[c]) - 1] == 'e')
qstrcat(spreek, "ën");
else
qstrcat(spreek, "en");
}
qstrcat(spreek, e = tiental[t]);
} else {
if(!(c == 0 && h != 0))
qstrcat(spreek, e = cijferordinaal[c]);
}
if(strchr("efnrs", e[strlen(e) - 1]))
qstrcat(spreek, "de");
else
qstrcat(spreek, "ste");
}
void spreek_cijfertjes(splitbuf_t *spreek, byte *cijfertjes) {
while(*cijfertjes) {
qstrcat(spreek, cijfer[*cijfertjes++ - '0']);
if(*cijfertjes)
qstrcat(spreek, " ");
}
}
void spreek_real(splitbuf_t *spreek, real getal) {
byte *geprint, *geheel, *fractie, *exponent;
unsigned long long int fractint;
int exp;
if(isnan(getal)) {
qstrcat(spreek, "geen getal");
return;
}
if(signbit(getal)) {
qstrcat(spreek, "min ");
getal = -getal;
}
if(isinf(getal)) {
qstrcat(spreek, "oneindig");
return;
}
if(asprintf((char **)&geprint, "%.15Lg", getal) == -1)
return;
geheel = geprint;
exponent = strchr(geprint, 'e');
if(exponent)
*exponent++ = '\0';
fractie = strchr(geprint, '.');
if(fractie)
*fractie++ = '\0';
spreek_geheel(spreek, geheel);
if(fractie) {
sscanf(fractie, "%Lu", &fractint);
qstrcat(spreek, " komma ");
if (fractint < 10000UL && *fractie != '0')
spreek_geheel(spreek, fractie);
else
spreek_cijfertjes(spreek, fractie);
}
if(exponent) {
exp = atoi(exponent);
qstrcat(spreek, " maal tien tot de ");
if(abs(exp) < 1000) {
if(exp < 0)
qstrcat(spreek, "min ");
spreek_honderdtalordinaal(spreek, abs(exp));
} else {
qstrcat(spreek, "macht ");
if(exp < 0)
qstrcat(spreek, "min ");
spreek_real(spreek, abs(exp));
}
}
/*
if(getal > 1.0e-14) {
if(l >= 0)
qstrcat(spreek, " ");
if(isnoemer(getal, 2.0)) {
qstrcat(spreek, cijfer[(int)(getal * 2.0 + 0.1)]);
qstrcat(spreek, " half");
}
else if(isnoemer(getal, 3.0)) {
qstrcat(spreek, cijfer[(int)(getal * 3.0 + 0.1)]);
qstrcat(spreek, " derde");
}
else if(isnoemer(getal, 4.0)) {
qstrcat(spreek, cijfer[(int)(getal * 4.0 + 0.1)]);
qstrcat(spreek, " kwart");
} else {
for(i = 5; i < 1000; i++) {
if(isnoemer(getal, (real)i)) {
qstrcat(spreek, h = spreek_honderdtal(getal * (real)i + 0.1));
free(h);
qstrcat(spreek, " ");
qstrcat(spreek, h = spreek_honderdtal(i));
free(h);
if(strchr("efnrs", spreek[strlen(spreek) - 1]))
qstrcat(spreek, "de");
else
qstrcat(spreek, "ste");
break;
}
}
if(i >= 1000) {
if(l < 0)
qstrcat(spreek, "nul ");
qstrcat(spreek, "komma");
sprintf(cijfertjes, "%.14Lf", getal);
for(c = cijfertjes + strlen(cijfertjes) - 1; *c == '0'; c--)
*c = '\0';
for(c = cijfertjes + 2; *c; c++) {
qstrcat(spreek, " ");
qstrcat(spreek, cijfer[*c - '0']);
}
}
}
} else {
if(l < 0)
qstrcat(spreek, "nul");
}
*/
free(geprint);
}
void spreek_echt(splitbuf_t *spreek, echt_t getal) {
bool pernodig;
int i, j;
if(getal.dim[DIM_MASSA]) {
getal.echt *= pow(0.001, getal.dim[DIM_MASSA]);
getal.imag *= pow(0.001, getal.dim[DIM_MASSA]);
}
if(!(getal.echt == 0.0 && getal.imag != 0.0)) {
spreek_real(spreek, getal.echt);
}
if(getal.imag != 0.0) {
if(getal.echt != 0.0) {
qstrcat(spreek, " ");
if(getal.echt != 0.0 && getal.imag > 0.0)
qstrcat(spreek, "plus ");
}
spreek_real(spreek, getal.imag);
qstrcat(spreek, " i");
}
if(!isdimensieloos(getal)) {
for(j = 0; j < NRDIMENSIES; j++) {
i = eenheidvolgorde[j];
if(getal.dim[i] > 0) {
qstrcat(spreek, " ");
if(i == DIM_LENGTE) {
if(getal.dim[i] == 2)
qstrcat(spreek, "vierkante ");
else if(getal.dim[i] == 3)
qstrcat(spreek, "kubieke ");
}
if(i == DIM_MASSA)
qstrcat(spreek, "kilo");
qstrcat(spreek, eenheid[i]);
if(getal.dim[i] == 2 && i != DIM_LENGTE)
qstrcat(spreek, " kwadraat");
else if(getal.dim[i] > 3 || (getal.dim[i] > 1 && i != DIM_LENGTE)) {
qstrcat(spreek, " tot de ");
if(getal.dim[i] < 1000) {
spreek_honderdtalordinaal(spreek, getal.dim[i]);
} else {
qstrcat(spreek, "macht ");
spreek_real(spreek, getal.dim[i]);
}
}
}
}
pernodig = TRUE;
for(j = 0; j < NRDIMENSIES; j++) {
i = eenheidvolgorde[j];
if(getal.dim[i] < 0) {
if(pernodig) {
qstrcat(spreek, " per");
pernodig = FALSE;
}
qstrcat(spreek, " ");
if(i == DIM_LENGTE) {
if(-getal.dim[i] == 2)
qstrcat(spreek, "vierkante ");
else if(-getal.dim[i] == 3)
qstrcat(spreek, "kubieke ");
}
if(i == DIM_MASSA)
qstrcat(spreek, "kilo");
qstrcat(spreek, eenheid[i]);
if(-getal.dim[i] == 2 && i != DIM_LENGTE)
qstrcat(spreek, " kwadraat");
else if(-getal.dim[i] > 3 || (-getal.dim[i] > 1 && i != DIM_LENGTE)) {
qstrcat(spreek, " tot de ");
if(getal.dim[i] < 1000) {
spreek_honderdtalordinaal(spreek, -getal.dim[i]);
} else {
qstrcat(spreek, "macht ");
spreek_real(spreek, -getal.dim[i]);
}
}
}
}
}
}