Skip to content

Commit 9a3aecf

Browse files
authored
[Quad] Add functions for conversion between quad and string (#237)
This patch adds Sleef_strtoq and Sleef_qtostr which can be used to convert between a quad value and a string. These functions are not vectorized. The corresponding testers are also added. This patch also adds functions for subtraction. Intel compiler testing is temporarily disabled because of license expiration( #238 ).
1 parent a053716 commit 9a3aecf

File tree

12 files changed

+487
-14
lines changed

12 files changed

+487
-14
lines changed

Jenkinsfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pipeline {
4343
'''
4444
}
4545
}
46-
46+
/*
4747
stage('Intel Compiler') {
4848
agent { label 'icc' }
4949
steps {
@@ -64,7 +64,7 @@ pipeline {
6464
'''
6565
}
6666
}
67-
67+
*/
6868
stage('FMA4') {
6969
agent { label 'fma4' }
7070
steps {

src/arch/helperavx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,11 @@ static INLINE vdouble vmin_vd_vd_vd(vdouble x, vdouble y) { return _mm256_min_pd
215215
#if CONFIG == 1
216216
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vadd_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
217217
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
218+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(z, vmul_vd_vd_vd(x, y)); }
218219
#else
219220
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_macc_pd(x, y, z); }
220221
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_msub_pd(x, y, z); }
222+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_nmacc_pd(x, y, z); }
221223
static INLINE vdouble vfma_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_macc_pd(x, y, z); }
222224
static INLINE vdouble vfmapp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_macc_pd(x, y, z); }
223225
static INLINE vdouble vfmapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return _mm256_msub_pd(x, y, z); }

src/arch/helperpower_128.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ static INLINE vdouble vsqrt_vd_vd(vdouble d) { return vec_sqrt(d); }
211211
#if CONFIG == 1
212212
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vec_madd(x, y, z); }
213213
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vec_msub(x, y, z); }
214+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vec_nmsub(x, y, z); }
214215
#else
215216
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vadd_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
216217
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }

src/arch/helperpurec_scalar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static INLINE vdouble vmin_vd_vd_vd(vdouble x, vdouble y) { return x < y ? x : y
205205
#ifndef ENABLE_FMA_DP
206206
static INLINE vdouble vmla_vd_vd_vd_vd (vdouble x, vdouble y, vdouble z) { return x * y + z; }
207207
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return x * y - z; }
208+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return -x * y + z; }
208209
#else
209210
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return FMA(x, y, z); }
210211
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return FMA(x, y, -z); }

src/arch/helpersse2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ static INLINE vdouble vabs_vd_vd(vdouble d) { return _mm_andnot_pd(_mm_set1_pd(-
191191
static INLINE vdouble vneg_vd_vd(vdouble d) { return _mm_xor_pd(_mm_set1_pd(-0.0), d); }
192192
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vadd_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
193193
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
194+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(z, vmul_vd_vd_vd(x, y)); }
194195
static INLINE vdouble vmax_vd_vd_vd(vdouble x, vdouble y) { return _mm_max_pd(x, y); }
195196
static INLINE vdouble vmin_vd_vd_vd(vdouble x, vdouble y) { return _mm_min_pd(x, y); }
196197

src/arch/helpersve.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,9 @@ static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y,
547547
vdouble z) { // z = x * y - z
548548
return svnmsb_f64_x(ptrue, x, y, z);
549549
}
550+
static INLINE vdouble vmlanp_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) {
551+
return svmsb_f64_x(ptrue, x, y, z);
552+
}
550553
#else
551554
static INLINE vdouble vmla_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vadd_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }
552555
static INLINE vdouble vmlapn_vd_vd_vd_vd(vdouble x, vdouble y, vdouble z) { return vsub_vd_vd_vd(vmul_vd_vd_vd(x, y), z); }

src/quad-tester/qiutsimd.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,45 @@ typedef union {
171171
} \
172172
}
173173

174+
#define func_strtoq(funcStr) { \
175+
while (startsWith(buf, funcStr " ")) { \
176+
sentinel = 0; \
177+
char s[64]; \
178+
sscanf(buf, funcStr " %63s", s); \
179+
Sleef_quad1 a0; \
180+
a0 = Sleef_strtoq(s, NULL, 10); \
181+
cnv128 c0; \
182+
c0.q = a0.s[0]; \
183+
printf("%" PRIx64 ":%" PRIx64 "\n", c0.h, c0.l); \
184+
fflush(stdout); \
185+
if (fgets(buf, BUFSIZE-1, stdin) == NULL) break; \
186+
} \
187+
}
188+
189+
#define func_qtostr(funcStr) { \
190+
while (startsWith(buf, funcStr " ")) { \
191+
sentinel = 0; \
192+
cnv128 c0; \
193+
sscanf(buf, funcStr " %" PRIx64 ":%" PRIx64, &c0.h, &c0.l); \
194+
Sleef_quad1 a0; \
195+
a0.s[0] = c0.q; \
196+
char s[64]; \
197+
Sleef_qtostr(s, 63, a0, 10); \
198+
printf("%s\n", s); \
199+
fflush(stdout); \
200+
if (fgets(buf, BUFSIZE-1, stdin) == NULL) break; \
201+
} \
202+
}
203+
174204
int do_test(int argc, char **argv) {
175205
xsrand(time(NULL));
176206

177207
{
178208
int k = 0;
179209
k += 1;
210+
#ifdef ENABLE_PUREC_SCALAR
211+
k += 2; // Enable string testing
212+
#endif
180213
printf("%d\n", k);
181214
fflush(stdout);
182215
}
@@ -187,9 +220,13 @@ int do_test(int argc, char **argv) {
187220

188221
while(!feof(stdin) && sentinel < 2) {
189222
func_q_q_q("addq_u05", xaddq_u05);
223+
func_q_q_q("subq_u05", xsubq_u05);
190224
func_q_q_q("mulq_u05", xmulq_u05);
191225
func_q_q_q("divq_u05", xdivq_u05);
192226
func_q_q("sqrtq_u05", xsqrtq_u05);
227+
func_q_q("negq", xnegq);
228+
func_strtoq("strtoq");
229+
func_qtostr("qtostr");
193230
sentinel++;
194231
}
195232

src/quad-tester/qtester.c

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,34 @@ typedef union {
139139
return c0.q; \
140140
} while(0)
141141

142+
#define child_q_str(funcStr, arg) do { \
143+
char str[256]; \
144+
sprintf(str, funcStr " %s\n", arg); \
145+
write(ptoc[1], str, strlen(str)); \
146+
if (fgets(str, 255, fpctop) == NULL) stop("child " funcStr); \
147+
cnv128 c; \
148+
sscanf(str, "%" PRIx64 ":%" PRIx64, &c.h, &c.l); \
149+
return c.q; \
150+
} while(0)
151+
152+
#define child_str_q(funcStr, ret, arg) do { \
153+
char str[256]; \
154+
cnv128 c; \
155+
c.q = arg; \
156+
sprintf(str, funcStr " %" PRIx64 ":%" PRIx64 "\n", c.h, c.l); \
157+
write(ptoc[1], str, strlen(str)); \
158+
if (fgets(str, 255, fpctop) == NULL) stop("child " funcStr); \
159+
sscanf(str, "%63s", ret); \
160+
} while(0)
161+
142162
Sleef_quad child_addq_u05(Sleef_quad x, Sleef_quad y) { child_q_q_q("addq_u05", x, y); }
143163
Sleef_quad child_subq_u05(Sleef_quad x, Sleef_quad y) { child_q_q_q("subq_u05", x, y); }
144164
Sleef_quad child_mulq_u05(Sleef_quad x, Sleef_quad y) { child_q_q_q("mulq_u05", x, y); }
145165
Sleef_quad child_divq_u05(Sleef_quad x, Sleef_quad y) { child_q_q_q("divq_u05", x, y); }
146166
Sleef_quad child_sqrtq_u05(Sleef_quad x) { child_q_q("sqrtq_u05", x); }
167+
Sleef_quad child_negq(Sleef_quad x) { child_q_q("negq", x); }
168+
Sleef_quad child_strtoq(const char *s) { child_q_str("strtoq", s); }
169+
void child_qtostr(char *ret, Sleef_quad x) { child_str_q("qtostr", ret, x); }
147170

148171
Sleef_quad child_copysignq(Sleef_quad x, Sleef_quad y) { child_q_q_q("copysignq", x, y); }
149172
Sleef_quad child_fabsq(Sleef_quad x) { child_q_q("fabsq", x); }
@@ -240,7 +263,7 @@ Sleef_quad child_fminq(Sleef_quad x, Sleef_quad y) { child_q_q_q("fminq", x, y);
240263
} while(0)
241264

242265
#define checkAccuracyOuterLoop_q(mpfrFunc, childFunc, minStr, maxStr, nLoop, bound, seed) do { \
243-
xsrand(seed); \
266+
xsrand(seed); \
244267
Sleef_quad min = cast_q_str(minStr), max = cast_q_str(maxStr); \
245268
for(int i=0;i<nLoop && success;i++) { \
246269
Sleef_quad x = rndf128(min, max); \
@@ -263,7 +286,7 @@ void checkResult(int success, double e) {
263286
#define STR_QUAD_MAX "1.18973149535723176508575932662800702e+4932"
264287
#define STR_QUAD_DENORM_MIN "6.475175119438025110924438958227646552e-4966"
265288

266-
void do_test() {
289+
void do_test(int options) {
267290
mpfr_set_default_prec(256);
268291
mpfr_t frx, fry, frz;
269292
mpfr_inits(frx, fry, frz, NULL);
@@ -274,6 +297,7 @@ void do_test() {
274297
"0.0", "-0.0", "+0.5", "-0.5", "+1.0", "-1.0", "+1.5", "-1.5", "+2.0", "-2.0", "+2.5", "-2.5",
275298
"1.234", "-1.234", "+1.234e+100", "-1.234e+100", "+1.234e-100", "-1.234e-100",
276299
"+1.234e+3000", "-1.234e+3000", "+1.234e-3000", "-1.234e-3000",
300+
"3.1415926535897932384626433832795028841971693993751058209749445923078164",
277301
"+" STR_QUAD_MIN, "-" STR_QUAD_MIN,
278302
"+" STR_QUAD_DENORM_MIN, "-" STR_QUAD_DENORM_MIN,
279303
"NaN", "Inf", "-Inf"
@@ -291,6 +315,13 @@ void do_test() {
291315
checkAccuracyOuterLoop_q_q(mpfr_add, child_addq_u05, "0", "Inf", 5 * NTEST, errorBound, 1);
292316
checkResult(success, maxError);
293317

318+
fprintf(stderr, "subq_u05 : ");
319+
maxError = 0;
320+
cmpDenormOuterLoop_q_q(mpfr_sub, child_subq_u05, stdCheckVals);
321+
checkAccuracyOuterLoop_q_q(mpfr_sub, child_subq_u05, "1e-100", "1e+100", 5 * NTEST, errorBound, 0);
322+
checkAccuracyOuterLoop_q_q(mpfr_sub, child_subq_u05, "0", "Inf", 5 * NTEST, errorBound, 1);
323+
checkResult(success, maxError);
324+
294325
fprintf(stderr, "mulq_u05 : ");
295326
maxError = 0;
296327
cmpDenormOuterLoop_q_q(mpfr_mul, child_mulq_u05, stdCheckVals);
@@ -311,11 +342,50 @@ void do_test() {
311342
checkAccuracyOuterLoop_q(mpfr_sqrt, child_sqrtq_u05, "1e-100", "1e+100", 5 * NTEST, errorBound, 0);
312343
checkAccuracyOuterLoop_q(mpfr_sqrt, child_sqrtq_u05, "0", "Inf", 5 * NTEST, errorBound, 1);
313344
checkResult(success, maxError);
345+
346+
fprintf(stderr, "negq : ");
347+
maxError = 0;
348+
cmpDenormOuterLoop_q(mpfr_neg, child_negq, stdCheckVals);
349+
checkAccuracyOuterLoop_q(mpfr_neg, child_negq, "1e-100", "1e+100", 5 * NTEST, errorBound, 0);
350+
checkAccuracyOuterLoop_q(mpfr_neg, child_negq, "0", "Inf", 5 * NTEST, errorBound, 1);
351+
checkResult(success, maxError);
352+
353+
if ((options & 2) != 0) {
354+
fprintf(stderr, "strtoq : ");
355+
for(int i=0;i<sizeof(stdCheckVals)/sizeof(char *);i++) {
356+
Sleef_quad a0 = cast_q_str(stdCheckVals[i]);
357+
Sleef_quad a1 = child_strtoq(stdCheckVals[i]);
358+
if (memcmp(&a0, &a1, sizeof(Sleef_quad)) == 0) continue;
359+
if (isnanf128(a0) && isnanf128(a1)) continue;
360+
361+
fprintf(stderr, "\narg = %s\ntest = %s\ncorrect = %s\n",
362+
stdCheckVals[i], sprintf128(a1), sprintf128(a0));
363+
success = 0;
364+
break;
365+
}
366+
checkResult(success, maxError);
367+
368+
fprintf(stderr, "qtostr : ");
369+
for(int i=0;i<sizeof(stdCheckVals)/sizeof(char *);i++) {
370+
Sleef_quad a0 = cast_q_str(stdCheckVals[i]);
371+
char s[100];
372+
child_qtostr(s, a0);
373+
Sleef_quad a1 = cast_q_str(s);
374+
if (memcmp(&a0, &a1, sizeof(Sleef_quad)) == 0) continue;
375+
if (isnanf128(a0) && isnanf128(a1)) continue;
376+
377+
fprintf(stderr, "\narg = %s\nteststr = %s\ntest = %s\ncorrect = %s\n",
378+
stdCheckVals[i], s, sprintf128(a0), sprintf128(a1));
379+
success = 0;
380+
break;
381+
}
382+
checkResult(success, maxError);
383+
}
314384
}
315385

316386
int main(int argc, char **argv) {
317387
char *argv2[argc+2], *commandSde = NULL;
318-
int i, a2s;
388+
int i, a2s, options;
319389

320390
// BUGFIX: this flush is to prevent incorrect syncing with the
321391
// `iut*` executable that causes failures in the CPU detection on
@@ -343,11 +413,10 @@ int main(int argc, char **argv) {
343413

344414
{
345415
char str[256];
346-
int u;
347416

348417
if (readln(ctop[0], str, 255) < 1 ||
349-
sscanf(str, "%d", &u) != 1 ||
350-
(u & 1) == 0) {
418+
sscanf(str, "%d", &options) != 1 ||
419+
(options & 1) == 0) {
351420
if (commandSde != NULL) {
352421
close(ctop[0]);
353422
close(ptoc[1]);
@@ -360,8 +429,8 @@ int main(int argc, char **argv) {
360429
startChild(argv2[0], argv2);
361430

362431
if (readln(ctop[0], str, 255) < 1) stop("Feature detection(sde, readln)");
363-
if (sscanf(str, "%d", &u) != 1) stop("Feature detection(sde, sscanf)");
364-
if ((u & 1) == 0) {
432+
if (sscanf(str, "%d", &options) != 1) stop("Feature detection(sde, sscanf)");
433+
if ((options & 1) == 0) {
365434
fprintf(stderr, "\n\nTester : *** CPU does not support the necessary feature(SDE)\n");
366435
return 0;
367436
}
@@ -378,7 +447,7 @@ int main(int argc, char **argv) {
378447

379448
fpctop = fdopen(ctop[0], "r");
380449

381-
do_test();
450+
do_test(options);
382451

383452
fprintf(stderr, "\n\n*** All tests passed\n");
384453

src/quad-tester/tester2simdqp.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stdio.h>
77
#include <stdlib.h>
88
#include <stdint.h>
9+
#include <string.h>
910
#include <mpfr.h>
1011
#include <time.h>
1112
#include <float.h>
@@ -284,6 +285,21 @@ int main(int argc,char **argv)
284285
}
285286
}
286287

288+
{
289+
mpfr_set_f128(frx, q0, GMP_RNDN);
290+
mpfr_set_f128(fry, q1, GMP_RNDN);
291+
mpfr_sub(frz, frx, fry, GMP_RNDN);
292+
293+
double u0 = countULPf128(t = vget(xsubq_u05(a0, a1), e), frz, 0);
294+
295+
if (u0 > 0.5000000001) {
296+
printf(ISANAME " sub arg=%s %s ulp=%.20g\n", sprintf128(q0), sprintf128(q1), u0);
297+
printf("test = %s\n", sprintf128(t));
298+
printf("corr = %s\n\n", sprintf128(mpfr_get_f128(frz, GMP_RNDN)));
299+
fflush(stdout); ecnt++;
300+
}
301+
}
302+
287303
{
288304
mpfr_set_f128(frx, q0, GMP_RNDN);
289305
mpfr_set_f128(fry, q1, GMP_RNDN);
@@ -327,5 +343,17 @@ int main(int argc,char **argv)
327343
fflush(stdout); ecnt++;
328344
}
329345
}
346+
347+
#ifdef ENABLE_PUREC_SCALAR
348+
if ((cnt & 15) == 1) {
349+
char s[64];
350+
Sleef_qtostr(s, 63, a0, 10);
351+
Sleef_quad q1 = vget(Sleef_strtoq(s, NULL, 10), e);
352+
if (memcmp(&q0, &q1, sizeof(Sleef_quad)) != 0 && !(isnanf128(q0) && isnanf128(q1))) {
353+
printf("qtostr/strtoq arg=%s\n", sprintf128(q0));
354+
fflush(stdout); ecnt++;
355+
}
356+
}
357+
#endif
330358
}
331359
}

src/quad/qfuncproto.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,21 @@ typedef struct {
2222
funcType:
2323
0 : vargquad func(vargquad);
2424
1 : vargquad func(vargquad, vargquad);
25-
2 : vargquad2 func(vargquad); GNUABI : void func(vargquad, double *, double *);
25+
2 : vargquad2 func(vargquad);
2626
3 : vargquad func(vargquad, vint);
2727
4 : vint func(vargquad);
2828
5 : vargquad func(vargquad, vargquad, vargquad);
29-
6 : vargquad2 func(vargquad); GNUABI : vargquad func(vargquad, double *);
29+
6 : vargquad2 func(vargquad);
3030
7 : int func(int);
3131
8 : void *func(int);
3232
*/
3333

3434
funcSpec funcList[] = {
3535
{ "add", 5, 2, 1, 0 },
36+
{ "sub", 5, 2, 1, 0 },
3637
{ "mul", 5, 2, 1, 0 },
3738
{ "div", 5, 2, 1, 0 },
39+
{ "neg", -1, 0, 0, 0 },
3840
{ "sqrt", 5, 2, 0, 0 },
3941
//{ "sincos", 10, 1, 2, 0 },
4042
//{ "ldexp", -1, 0, 3, 0 },

0 commit comments

Comments
 (0)