===================================================================
@@ -31,13 +31,13 @@
WRITE(buffer,"(G12.5E5,'<')") -10000.
if (buffer.ne."************<") call abort
WRITE(buffer,"(G13.5E5,'<')") -10000.
- if (buffer.ne."-10000. <") call abort
+ if (buffer.ne."*************<") call abort
WRITE(buffer,"(G14.5E5,'<')") -10000.
- if (buffer.ne." -10000. <") call abort
+ if (buffer.ne."-10000. <") call abort
WRITE(buffer,"(G15.5E5,'<')") -10000.
- if (buffer.ne." -10000. <") call abort
+ if (buffer.ne." -10000. <") call abort
WRITE(buffer,"(G16.5E5,'<')") -10000.
- if (buffer.ne." -10000. <") call abort
+ if (buffer.ne." -10000. <") call abort
STOP
END
===================================================================
@@ -2,19 +2,19 @@
! PR36420 Fortran 2008: g0 edit descriptor
! Test case provided by Jerry DeLisle <jvdelisle@gcc.gnu.org>
character(25) :: string = "(g0,g0,g0)"
- character(33) :: buffer
+ character(50) :: buffer
write(buffer, '(g0,g0,g0)') ':',12340,':'
if (buffer.ne.":12340:") call abort
write(buffer, string) ':',0,':'
if (buffer.ne.":0:") call abort
- write(buffer, string) ':',1.0/3.0,':'
- if (buffer.ne.":.33333334:") call abort
- write(buffer, '(1x,a,g0,a)') ':',1.0/3.0,':'
- if (buffer.ne." :.33333334:") call abort
+ write(buffer, string) ':',1.0_8/3.0_8,':'
+ if (buffer.ne.":.33333333333333331:") call abort
+ write(buffer, '(1x,a,g0,a)') ':',1.0_8/3.0_8,':'
+ if (buffer.ne." :.33333333333333331:") call abort
write(buffer, string) ':',"hello",':'
- if (buffer.ne.":hello:") call abort
+ if (buffer.ne.":hello:") call abort
write(buffer, "(g0,g0,g0,g0)") ':',.true.,.false.,':'
if (buffer.ne.":TF:") call abort
- write(buffer, "(g0,g0,',',g0,g0)") '(',( 1.2345, 2.4567 ),')'
- if (buffer.ne."(1.2345001,2.4567001)") call abort
+ write(buffer, "(g0,g0,',',g0,g0)") '(',( 1.2345_8, 2.4567_8 ),')'
+ if (buffer.ne."(1.2344999999999999,2.4567000000000001)") call abort
end
===================================================================
@@ -0,0 +1,75 @@
+! { dg-do run }
+! PR48615 Invalid UP/DOWN rounding with E and ES descriptors
+! Test case provided by Thomas Henlich.
+program pr48615
+ call checkfmt("(RU,F17.0)", 2.5, " 3.")
+ call checkfmt("(RU,-1P,F17.1)", 2.5, " 0.3")
+ call checkfmt("(RU,E17.1)", 2.5, " 0.3E+01") ! 0.2E+01
+ call checkfmt("(RU,1P,E17.0)", 2.5, " 3.E+00")
+ call checkfmt("(RU,ES17.0)", 2.5, " 3.E+00") ! 2.E+00
+ call checkfmt("(RU,EN17.0)", 2.5, " 3.E+00")
+
+ call checkfmt("(RD,F17.0)", 2.5, " 2.")
+ call checkfmt("(RD,-1P,F17.1)", 2.5, " 0.2")
+ call checkfmt("(RD,E17.1)", 2.5, " 0.2E+01")
+ call checkfmt("(RD,1P,E17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RD,ES17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RD,EN17.0)", 2.5, " 2.E+00")
+
+ call checkfmt("(RC,F17.0)", 2.5, " 3.")
+ call checkfmt("(RC,-1P,F17.1)", 2.5, " 0.3")
+ call checkfmt("(RC,E17.1)", 2.5, " 0.3E+01") ! 0.2E+01
+ call checkfmt("(RC,1P,E17.0)", 2.5, " 3.E+00")
+ call checkfmt("(RC,ES17.0)", 2.5, " 3.E+00") ! 2.E+00
+ call checkfmt("(RC,EN17.0)", 2.5, " 3.E+00")
+
+ call checkfmt("(RN,F17.0)", 2.5, " 2.")
+ call checkfmt("(RN,-1P,F17.1)", 2.5, " 0.2")
+ call checkfmt("(RN,E17.1)", 2.5, " 0.2E+01")
+ call checkfmt("(RN,1P,E17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RN,ES17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RN,EN17.0)", 2.5, " 2.E+00")
+
+ call checkfmt("(RZ,F17.0)", 2.5, " 2.")
+ call checkfmt("(RZ,-1P,F17.1)", 2.5, " 0.2")
+ call checkfmt("(RZ,E17.1)", 2.5, " 0.2E+01")
+ call checkfmt("(RZ,1P,E17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RZ,ES17.0)", 2.5, " 2.E+00")
+ call checkfmt("(RZ,EN17.0)", 2.5, " 2.E+00")
+
+ call checkfmt("(RZ,F17.0)", -2.5, " -2.")
+ call checkfmt("(RZ,-1P,F17.1)", -2.5, " -0.2")
+ call checkfmt("(RZ,E17.1)", -2.5, " -0.2E+01")
+ call checkfmt("(RZ,1P,E17.0)", -2.5, " -2.E+00")
+ call checkfmt("(RZ,ES17.0)", -2.5, " -2.E+00")
+ call checkfmt("(RZ,EN17.0)", -2.5, " -2.E+00")
+
+ call checkfmt("(RN,F17.0)", -2.5, " -2.")
+ call checkfmt("(RN,-1P,F17.1)", -2.5, " -0.2")
+ call checkfmt("(RN,E17.1)", -2.5, " -0.2E+01")
+ call checkfmt("(RN,1P,E17.0)", -2.5, " -2.E+00")
+ call checkfmt("(RN,ES17.0)", -2.5, " -2.E+00")
+ call checkfmt("(RN,EN17.0)", -2.5, " -2.E+00")
+
+ call checkfmt("(RC,F17.0)", -2.5, " -3.")
+ call checkfmt("(RC,-1P,F17.1)", -2.5, " -0.3")
+ call checkfmt("(RC,E17.1)", -2.5, " -0.3E+01") ! -0.2E+01
+ call checkfmt("(RC,1P,E17.0)", -2.5, " -3.E+00")
+ call checkfmt("(RC,ES17.0)", -2.5, " -3.E+00") ! -2.E+00
+ call checkfmt("(RC,EN17.0)", -2.5, " -3.E+00")
+
+ call checkfmt("(RU,E17.1)", nearest(2.0, 1.0), " 0.3E+01") ! 0.2E+01
+ call checkfmt("(RD,E17.1)", nearest(3.0, -1.0), " 0.2E+01") ! 0.3E+01
+
+contains
+ subroutine checkfmt(fmt, x, cmp)
+ character(len=*), intent(in) :: fmt
+ real, intent(in) :: x
+ character(len=*), intent(in) :: cmp
+ character(len=40) :: s
+
+ write(s, fmt) x
+ if (s /= cmp) call abort
+ !if (s /= cmp) print "(a,1x,a,' expected: ',1x)", fmt, s, cmp
+ end subroutine
+end program
===================================================================
@@ -9,5 +9,5 @@
namelist /mynml/ x
x = 1
! ( dg-output "^" }
- print mynml ! { dg-output "&MYNML(\n|\r\n|\r) X= 1.0000000 ,(\n|\r\n|\r) /(\n|\r\n|\r)" }
+ print mynml ! { dg-output "&MYNML(\n|\r\n|\r) X= 1.00000000 ,(\n|\r\n|\r) /(\n|\r\n|\r)" }
end
===================================================================
@@ -5,7 +5,7 @@
! Test case prepared by Jerry DeLisle <jvdelisle@gcc.gnu.org>
program char4_iunit_1
implicit none
- character(kind=4,len=42) :: string
+ character(kind=4,len=44) :: string
integer(kind=4) :: i,j
real(kind=4) :: inf, nan, large
@@ -24,11 +24,11 @@ program char4_iunit_1
write(string, *) .true., .false. , .true.
if (string .ne. 4_" T F T ") call abort
write(string, *) 1.2345e-06, 4.2846e+10_8
- if (string .ne. 4_" 1.23450002E-06 42846000000.000000 ") call abort
+ if (string .ne. 4_" 1.23450002E-06 42846000000.000000 ") call abort
write(string, *) nan, inf
- if (string .ne. 4_" NaN Infinity ") call abort
+ if (string .ne. 4_" NaN Infinity ") call abort
write(string, '(10x,f3.1,3x,f9.1)') nan, inf
- if (string .ne. 4_" NaN Infinity ") call abort
+ if (string .ne. 4_" NaN Infinity ") call abort
write(string, *) (1.2, 3.4 )
- if (string .ne. 4_" ( 1.2000000 , 3.4000001 ) ") call abort
+ if (string .ne. 4_" ( 1.20000005 , 3.40000010 ) ") call abort
end program char4_iunit_1
===================================================================
@@ -5,7 +5,7 @@ integer :: i
real :: a(10) = [ (i*1.3, i=1,10) ]
real :: b(10)
complex :: c
-character(34) :: complex
+character(36) :: complex
namelist /nm/ a
open(99,file="mynml",form="formatted",decimal="point",status="replace")
@@ -18,9 +18,9 @@ close(99, status="delete")
c = (3.123,4.456)
write(complex,*,decimal="comma") c
-if (complex.ne." ( 3,1229999 ; 4,4559999 )") call abort
+if (complex.ne." ( 3,12299991 ; 4,45599985 )") call abort
c = (0.0, 0.0)
read(complex,*,decimal="comma") c
-if (complex.ne." ( 3,1229999 ; 4,4559999 )") call abort
+if (complex.ne." ( 3,12299991 ; 4,45599985 )") call abort
end
===================================================================
@@ -9,7 +9,7 @@ program ex2
implicit none
real, allocatable :: z(:)[:]
integer :: image
- character(len=80) :: str
+ character(len=128) :: str
allocate(z(3)[*])
write(*,*) 'z allocated on image',this_image()
@@ -25,18 +25,18 @@ program ex2
str = repeat('X', len(str))
write(str,*) 'z=',z(:),' on image',this_image()
- if (str /= " z= 1.2000000 1.2000000 1.2000000 on image 1") &
- call abort ()
+ if (str /= " z= 1.20000005 1.20000005 1.20000005 on image 1") &
+ call abort
str = repeat('X', len(str))
write(str,*) 'z=',z,' on image',this_image()
- if (str /= " z= 1.2000000 1.2000000 1.2000000 on image 1") &
- call abort ()
+ if (str /= " z= 1.20000005 1.20000005 1.20000005 on image 1") &
+ call abort
str = repeat('X', len(str))
write(str,*) 'z=',z(1:3)[this_image()],' on image',this_image()
- if (str /= " z= 1.2000000 1.2000000 1.2000000 on image 1") &
- call abort ()
+ if (str /= " z= 1.20000005 1.20000005 1.20000005 on image 1") &
+ call abort
call ex2a()
call ex5()
@@ -46,7 +46,7 @@ subroutine ex2a()
implicit none
real, allocatable :: z(:,:)[:,:]
integer :: image
- character(len=100) :: str
+ character(len=128) :: str
allocate(z(2,2)[1,*])
write(*,*) 'z allocated on image',this_image()
@@ -62,38 +62,38 @@ subroutine ex2a()
str = repeat('X', len(str))
write(str,*) 'z=',z(:,:),' on image',this_image()
- if (str /= " z= 1.2000000 1.2000000 1.2000000 1.2000000 on image 1") &
- call abort ()
+ if (str /= " z= 1.20000005 1.20000005 1.20000005 1.20000005 on image 1") &
+ call abort
str = repeat('X', len(str))
write(str,*) 'z=',z,' on image',this_image()
- if (str /= " z= 1.2000000 1.2000000 1.2000000 1.2000000 on image 1") &
- call abort ()
+ if (str /= " z= 1.20000005 1.20000005 1.20000005 1.20000005 on image 1") &
+ call abort
end subroutine ex2a
subroutine ex5
implicit none
integer :: me
real, save :: w(4)[*]
- character(len=100) :: str
+ character(len=128) :: str
me = this_image()
w = me
str = repeat('X', len(str))
write(str,*) 'In main on image',this_image(), 'w= ',w
- if (str /= " In main on image 1 w= 1.0000000 1.0000000 1.0000000 1.0000000") &
- call abort ()
+ if (str /= " In main on image 1 w= 1.00000000 1.00000000 1.00000000 1.00000000") &
+ call abort
str = repeat('X', len(str))
write(str,*) 'In main on image',this_image(), 'w= ',w(1:4)
- if (str /= " In main on image 1 w= 1.0000000 1.0000000 1.0000000 1.0000000") &
- call abort ()
+ if (str /= " In main on image 1 w= 1.00000000 1.00000000 1.00000000 1.00000000") &
+ call abort
str = repeat('X', len(str))
write(str,*) 'In main on image',this_image(), 'w= ',w(:)[1]
- if (str /= " In main on image 1 w= 1.0000000 1.0000000 1.0000000 1.0000000") &
- call abort ()
+ if (str /= " In main on image 1 w= 1.00000000 1.00000000 1.00000000 1.00000000") &
+ call abort
sync all
call ex5_sub(me,w)
@@ -103,10 +103,10 @@ subroutine ex5_sub(n,w)
implicit none
integer :: n
real :: w(n)
- character(len=50) :: str
+ character(len=75) :: str
str = repeat('X', len(str))
write(str,*) 'In sub on image',this_image(), 'w= ',w
- if (str /= " In sub on image 1 w= 1.0000000") &
- call abort ()
+ if (str /= " In sub on image 1 w= 1.00000000") &
+ call abort
end subroutine ex5_sub
===================================================================
@@ -14,9 +14,9 @@ enddo
write(out,nl1)
if (out(1).ne."&NL1") call abort
-if (out(2).ne." A= 1.0000000 ,") call abort
-if (out(3).ne." B= 2.0000000 ,") call abort
-if (out(4).ne." C= 3.0000000 ,") call abort
+if (out(2).ne." A= 1.00000000 ,") call abort
+if (out(3).ne." B= 2.00000000 ,") call abort
+if (out(4).ne." C= 3.00000000 ,") call abort
if (out(5).ne." /") call abort
end program oneline
===================================================================
@@ -3,9 +3,10 @@
! pr40330 incorrect io.
! test case derived from pr40662, <jvdelisle@gcc.gnu.org>
program astap
- character(40) teststring
- arlxca = 0.0
- open(10, status="scratch")
+ implicit none
+ character(34) :: teststring
+ real(4) :: arlxca = 0.0
+ open(10)
write(10,40) arlxca
write(10,40) arlxca
40 format(t4,"arlxca = ",1pg13.6,t27,"arlxcc = ",g13.6,t53,
@@ -21,13 +22,12 @@
. "ebalnc = ",g13.6,t79,"ebalsa = ",g13.6,t105,
. "ebalsc = ",g13.6)
rewind 10
- rewind 10
teststring = ""
read(10,'(a)') teststring
- if (teststring.ne." arlxca = 0.00000 arlxcc = ")call abort
+ if (teststring.ne." arlxca = 0.00000 arlxcc =")call abort
teststring = ""
read(10,'(a)') teststring
- if (teststring.ne." arlxca = 0.00000 arlxcc = ")call abort
+ if (teststring.ne." arlxca = 0.00000 arlxcc =")call abort
end program astap
===================================================================
@@ -43,5 +43,5 @@ program char4_iunit_2
write(widestring,*)"test",i, x, str_default,&
trim(str_char4)
if (widestring .ne. &
- k_" test 345 52.542999 0 hijklmnp qwertyuiopasd") call abort
+ k_" test 345 52.5429993 0 hijklmnp qwertyuiopasd") call abort
end program char4_iunit_2
===================================================================
@@ -42,15 +42,15 @@ program main
if (trim(adjustl(str)) .ne. 'NaN') call abort
write(str,*) z
- if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
+ if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
write(str,*) z2
- if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
+ if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
write(str,*) z3
- if (trim(adjustl(str)) .ne. '( Infinity, -Infinity)') call abort
+ if (trim(adjustl(str)) .ne. '( Infinity, -Infinity)') call abort
write(str,*) z4
- if (trim(adjustl(str)) .ne. '( 0.0000000 , -0.0000000 )') call abort
+ if (trim(adjustl(str)) .ne. '( 0.00000000 , -0.00000000 )') call abort
end program main
===================================================================
@@ -1155,35 +1155,35 @@ write_z (st_parameter_dt *dtp, const fnode *f, con
void
write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_float (dtp, f, p, len);
+ write_float (dtp, f, p, len, 0);
}
void
write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_float (dtp, f, p, len);
+ write_float (dtp, f, p, len, 0);
}
void
write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_float (dtp, f, p, len);
+ write_float (dtp, f, p, len, 0);
}
void
write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_float (dtp, f, p, len);
+ write_float (dtp, f, p, len, 0);
}
void
write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_float (dtp, f, p, len);
+ write_float (dtp, f, p, len, 0);
}
@@ -1432,8 +1432,8 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f,
switch (length)
{
case 4:
- f->u.real.w = 15;
- f->u.real.d = 8;
+ f->u.real.w = 16;
+ f->u.real.d = 9;
f->u.real.e = 2;
break;
case 8:
@@ -1442,13 +1442,13 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f,
f->u.real.e = 3;
break;
case 10:
- f->u.real.w = 29;
- f->u.real.d = 20;
+ f->u.real.w = 30;
+ f->u.real.d = 21;
f->u.real.e = 4;
break;
case 16:
- f->u.real.w = 44;
- f->u.real.d = 35;
+ f->u.real.w = 45;
+ f->u.real.d = 36;
f->u.real.e = 4;
break;
default:
@@ -1468,7 +1468,7 @@ write_real (st_parameter_dt *dtp, const char *sour
int org_scale = dtp->u.p.scale_factor;
dtp->u.p.scale_factor = 1;
set_fnode_default (dtp, &f, length);
- write_float (dtp, &f, source , length);
+ write_float (dtp, &f, source , length, 1);
dtp->u.p.scale_factor = org_scale;
}
@@ -1476,12 +1476,20 @@ write_real (st_parameter_dt *dtp, const char *sour
void
write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
{
- fnode f ;
+ fnode f;
+ int comp_d;
set_fnode_default (dtp, &f, length);
if (d > 0)
f.u.real.d = d;
+
+ /* Compensate for extra digits when using scale factor, d is not
+ specified, and the magnitude is such that E editing is used. */
+ if (dtp->u.p.scale_factor > 0 && d == 0)
+ comp_d = 1;
+ else
+ comp_d = 0;
dtp->u.p.g0_no_blanks = 1;
- write_float (dtp, &f, source , length);
+ write_float (dtp, &f, source , length, comp_d);
dtp->u.p.g0_no_blanks = 0;
}
===================================================================
@@ -289,8 +289,9 @@ output_float (st_parameter_dt *dtp, const fnode *f
}
else if (nbefore + nafter < ndigits)
{
- ndigits = nbefore + nafter;
- i = ndigits;
+ i = ndigits = nbefore + nafter;
+ if (d == 0 && digits[1] == '0')
+ goto skip;
if (digits[i] >= rchar)
{
/* Propagate the carry. */
@@ -812,7 +813,8 @@ CALCULATE_EXP(16)
static void \
output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
GFC_REAL_ ## x m, char *buffer, size_t size, \
- int sign_bit, bool zero_flag, int ndigits, int edigits) \
+ int sign_bit, bool zero_flag, int ndigits, \
+ int edigits, int comp_d) \
{ \
int e = f->u.real.e;\
int d = f->u.real.d;\
@@ -850,7 +852,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, co
{ \
newf->format = FMT_E;\
newf->u.real.w = w;\
- newf->u.real.d = d;\
+ newf->u.real.d = d - comp_d;\
newf->u.real.e = e;\
nb = 0;\
goto finish;\
@@ -864,11 +866,10 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, co
\
while (low <= high)\
{ \
- GFC_REAL_ ## x temp;\
+ volatile GFC_REAL_ ## x temp;\
mid = (low + high) / 2;\
\
temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
- asm volatile ("" : "+m" (temp));\
\
if (m < temp)\
{ \
@@ -894,22 +895,11 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, co
}\
}\
\
- if (e > 4)\
- e = 4;\
- if (e < 0)\
- nb = 4;\
- else\
- nb = e + 2;\
-\
- nb = nb >= w ? 0 : nb;\
+ nb = e <= 0 ? 4 : e + 2;\
+ nb = nb >= w ? w - 1 : nb;\
newf->format = FMT_F;\
- newf->u.real.w = f->u.real.w - nb;\
-\
- if (m == 0.0)\
- newf->u.real.d = d - 1;\
- else\
- newf->u.real.d = - (mid - d - 1);\
-\
+ newf->u.real.w = w - nb;\
+ newf->u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
dtp->u.p.scale_factor = 0;\
\
finish:\
@@ -931,7 +921,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, co
gfc_char4_t *p4 = (gfc_char4_t *) p;\
memset4 (p4, pad, nb);\
}\
- else\
+ else \
memset (p, pad, nb);\
}\
}\
@@ -1010,19 +1000,20 @@ __qmath_(quadmath_snprintf) (buffer, sizeof buffer
edigits);\
else \
output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
- zero_flag, ndigits, edigits);\
+ zero_flag, ndigits, edigits, comp_d);\
}\
/* Output a real number according to its format. */
static void
-write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
+write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
+ int len, int comp_d)
{
#if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
-# define MIN_FIELD_WIDTH 48
+# define MIN_FIELD_WIDTH 49
#else
-# define MIN_FIELD_WIDTH 31
+# define MIN_FIELD_WIDTH 32
#endif
#define STR(x) STR1(x)
#define STR1(x) #x
@@ -1039,23 +1030,8 @@ static void
to handle the largest number of exponent digits expected. */
edigits=4;
- if (f->format == FMT_F || f->format == FMT_EN || f->format == FMT_G
- || ((f->format == FMT_D || f->format == FMT_E)
- && dtp->u.p.scale_factor != 0))
- {
- /* Always convert at full precision to avoid double rounding. */
- ndigits = MIN_FIELD_WIDTH - 4 - edigits;
- }
- else
- {
- /* The number of digits is known, so let printf do the rounding. */
- if (f->format == FMT_ES)
- ndigits = f->u.real.d + 1;
- else
- ndigits = f->u.real.d;
- if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
- ndigits = MIN_FIELD_WIDTH - 4 - edigits;
- }
+ /* Always convert at full precision to avoid double rounding. */
+ ndigits = MIN_FIELD_WIDTH - 4 - edigits;
switch (len)
{