Update to use safe scaling algorithm from Reference-LAPACK PR 527

This commit is contained in:
Martin Kroeker 2023-07-12 23:02:36 +02:00 committed by GitHub
parent 2edebc5fb9
commit e08743d977
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 22 deletions

View File

@ -1,9 +1,11 @@
#include <math.h> #include <math.h>
#include <float.h>
#include "common.h" #include "common.h"
#ifdef FUNCTION_PROFILE #ifdef FUNCTION_PROFILE
#include "functable.h" #include "functable.h"
#endif #endif
#ifndef CBLAS #ifndef CBLAS
void NAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){ void NAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
@ -14,17 +16,27 @@ void CNAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
#endif #endif
#ifdef DOUBLE
long double safmin = DBL_MIN;
#else
long double safmin = FLT_MIN;
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) || defined(_M_IX86) #if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) || defined(_M_IX86)
long double da = *DA; long double da = *DA;
long double db = *DB; long double db = *DB;
long double c; long double c;
long double s; long double s;
long double r, roe, z; long double r, z;
long double sigma, dascal,dbscal;
long double ada = fabsl(da); long double ada = fabsl(da);
long double adb = fabsl(db); long double adb = fabsl(db);
long double scale = ada + adb; long double maxab = MAX(ada,adb);
long double safmax;
long double scale;
#ifndef CBLAS #ifndef CBLAS
PRINT_DEBUG_NAME; PRINT_DEBUG_NAME;
@ -32,17 +44,25 @@ void CNAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
PRINT_DEBUG_CNAME; PRINT_DEBUG_CNAME;
#endif #endif
roe = db; if (adb == ZERO) {
if (ada > adb) roe = da;
if (scale == ZERO) {
*C = ONE; *C = ONE;
*S = ZERO; *S = ZERO;
*DA = ZERO;
*DB = ZERO; *DB = ZERO;
} else if (ada == ZERO) {
*C = ZERO;
*S = ONE;
*DA = *DB;
*DB = ONE;
} else { } else {
r = sqrt(da * da + db * db); safmax = 1./safmin;
if (roe < 0) r = -r; scale = MIN(MAX(safmin,maxab), safmax);
if (ada > adb)
sigma = copysign(1.,da);
else
sigma = copysign(1.,db);
dascal = da / scale;
dbscal = db / scale;
r = sigma * (scale * sqrt(dascal * dascal + dbscal * dbscal));
c = da / r; c = da / r;
s = db / r; s = db / r;
z = ONE; z = ONE;
@ -65,11 +85,22 @@ void CNAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
FLOAT db = *DB; FLOAT db = *DB;
FLOAT c = *C; FLOAT c = *C;
FLOAT s = *S; FLOAT s = *S;
FLOAT r, roe, z; FLOAT sigma;
FLOAT r, z;
FLOAT ada = fabs(da); FLOAT ada = fabs(da);
FLOAT adb = fabs(db); FLOAT adb = fabs(db);
FLOAT scale = ada + adb; FLOAT maxab = MAX(ada,adb);
long double safmax ;
FLOAT scale ;
safmax = 1./safmin;
scale = MIN(MAX(safmin,maxab), safmax);
if (ada > adb)
sigma = sign(1.,da);
else
sigma = sign(1.,db);
#ifndef CBLAS #ifndef CBLAS
PRINT_DEBUG_NAME; PRINT_DEBUG_NAME;
@ -77,20 +108,17 @@ void CNAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
PRINT_DEBUG_CNAME; PRINT_DEBUG_CNAME;
#endif #endif
roe = db;
if (ada > adb) roe = da;
if (scale == ZERO) { if (adb == ZERO) {
*C = ONE; *C = ONE;
*S = ZERO; *S = ZERO;
*DA = ZERO; DA = ZERO;
*DB = ZERO; *DB = ZERO;
} else { } else {
FLOAT aa = da / scale; FLOAT aa = da / scale;
FLOAT bb = db / scale; FLOAT bb = db / scale;
r = scale * sqrt(aa * aa + bb * bb); r = sigma * scale * sqrt(aa * aa + bb * bb);
if (roe < 0) r = -r;
c = da / r; c = da / r;
s = db / r; s = db / r;
z = ONE; z = ONE;

View File

@ -1,9 +1,11 @@
#include <math.h> #include <math.h>
#include <float.h>
#include "common.h" #include "common.h"
#ifdef FUNCTION_PROFILE #ifdef FUNCTION_PROFILE
#include "functable.h" #include "functable.h"
#endif #endif
#ifndef CBLAS #ifndef CBLAS
void NAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){ void NAME(FLOAT *DA, FLOAT *DB, FLOAT *C, FLOAT *S){
@ -14,6 +16,12 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
FLOAT *S = (FLOAT*) VS; FLOAT *S = (FLOAT*) VS;
#endif /* CBLAS */ #endif /* CBLAS */
#ifdef DOUBLE
long double safmin = DBL_MIN;
#else
long double safmin = FLT_MIN;
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) || defined(_M_IX86) #if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) || defined(_M_IX86)
long double da_r = *(DA + 0); long double da_r = *(DA + 0);
@ -23,6 +31,7 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
long double r; long double r;
long double ada = fabsl(da_r) + fabsl(da_i); long double ada = fabsl(da_r) + fabsl(da_i);
long double adb = sqrt(db_r * db_r + db_i * db_i);
PRINT_DEBUG_NAME; PRINT_DEBUG_NAME;
@ -38,10 +47,24 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
*(DA + 1) = db_i; *(DA + 1) = db_i;
} else { } else {
long double alpha_r, alpha_i; long double alpha_r, alpha_i;
long double safmax = 1./safmin;
long double sigma;
long double maxab = MAX(ada,adb);
long double scale = MIN(MAX(safmin,maxab), safmax);
ada = sqrt(da_r * da_r + da_i * da_i);
r = sqrt(da_r * da_r + da_i * da_i + db_r * db_r + db_i * db_i); long double aa_r = da_r / scale;
long double aa_i = da_i / scale;
long double bb_r = db_r / scale;
long double bb_i = db_i / scale;
if (ada > adb)
sigma = copysign(1.,da_r);
else
sigma = copysign(1.,db_r);
r = sigma * scale * sqrt(aa_r * aa_r + aa_i * aa_i + bb_r * bb_r + bb_i * bb_i);
alpha_r = da_r / ada; alpha_r = da_r / ada;
alpha_i = da_i / ada; alpha_i = da_i / ada;
@ -60,7 +83,7 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
FLOAT r; FLOAT r;
FLOAT ada = fabs(da_r) + fabs(da_i); FLOAT ada = fabs(da_r) + fabs(da_i);
FLOAT adb; FLOAT ada = fabs(db_r) + fabs(db_i);
PRINT_DEBUG_NAME; PRINT_DEBUG_NAME;
@ -75,6 +98,7 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
*(DA + 0) = db_r; *(DA + 0) = db_r;
*(DA + 1) = db_i; *(DA + 1) = db_i;
} else { } else {
long double safmax = 1./safmin;
FLOAT scale; FLOAT scale;
FLOAT aa_r, aa_i, bb_r, bb_i; FLOAT aa_r, aa_i, bb_r, bb_i;
FLOAT alpha_r, alpha_i; FLOAT alpha_r, alpha_i;
@ -108,14 +132,20 @@ void CNAME(void *VDA, void *VDB, FLOAT *C, void *VS) {
scale = (bb_i / bb_r); scale = (bb_i / bb_r);
adb = bb_r * sqrt(ONE + scale * scale); adb = bb_r * sqrt(ONE + scale * scale);
} }
scale = ada + adb; FLOAT maxab = MAX(ada,adb);
scale = MIN(MAX(safmin,maxab), safmax);
aa_r = da_r / scale; aa_r = da_r / scale;
aa_i = da_i / scale; aa_i = da_i / scale;
bb_r = db_r / scale; bb_r = db_r / scale;
bb_i = db_i / scale; bb_i = db_i / scale;
r = scale * sqrt(aa_r * aa_r + aa_i * aa_i + bb_r * bb_r + bb_i * bb_i); if (ada > adb)
sigma = copysign(1.,da_r);
else
sigma = copysign(1.,db_r);
r = sigma * scale * sqrt(aa_r * aa_r + aa_i * aa_i + bb_r * bb_r + bb_i * bb_i);
alpha_r = da_r / ada; alpha_r = da_r / ada;
alpha_i = da_i / ada; alpha_i = da_i / ada;