🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #177

Re: Exponentiation operator proposal

#177
From: John F Carr
Date: Wed, 16 Sep 1992 00:57
302 lines
9135 bytes
I have implemented the exponentiation proposal for gcc and g++.  Here are
the changes.  This was a very quick implementation, and is intended only for
people to gain experience using the feature.  I am certain there are bugs
and missing features.

Your line numbers may vary as the patches here are for the gcc development
sources, not the 2.2.2 release.

This requires one additional library routine: double __ipow(double, int)
which is like pow() except for the argument types.



add to expr.c:expand_expr()


    case EXPON_EXPR:
      if (target == 0)
	target = gen_reg_rtx (tmode != VOIDmode
			      ? tmode : TYPE_MODE (TREE_TYPE (exp)));
      return expand_pow (exp, target);


add to expr.c:


static rtx expand_pow (exp, target)
register tree exp;
rtx target;
{
  enum machine_mode tmode;
  register rtx op0, op1;
  tree arg0, arg1;

  arg0 = TREE_OPERAND (exp, 0);
  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);

  arg1 = TREE_OPERAND (exp, 1);
  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);

  tmode = GET_MODE (target);

  /* Special case: -1 *^ j */
  if (op0 == constm1_rtx
      && (GET_CODE (op1) == CONST_INT
	  || GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT))
    {
      enum machine_mode op1mode = (GET_CODE (op1) == CONST_INT
				? tmode : (enum machine_mode)GET_MODE (op1));
#if BITS_BIG_ENDIAN
      return extract_bit_field (op1, 1, GET_MODE_BITSIZE (op1mode), 0,
				target, op1mode, tmode,
				GET_MODE_BITSIZE (op1mode),
				GET_MODE_BITSIZE (op1mode));
#else
      return extract_bit_field (op1, 1, 0, 0, target, op1mode, tmode,
				GET_MODE_BITSIZE (op1mode),
				GET_MODE_BITSIZE (op1mode));
#endif
    }

  /* Optimize small integer exponents.  */
  if (GET_CODE (op1) == CONST_INT)
    {
      rtx tmp = op0;
      switch (INTVAL (op1))
	{
	case 0:
	  return const_tiny_rtx[1][tmode];

	case 1:
	  return op0;

	case 3:
	  tmp = expand_mult (tmode, op0, op0, NULL_RTX, 0);
	  /* fall through */
	case 2:
	  return expand_mult (tmode, op0, tmp, target, 0);

	case -1:
	  if (GET_MODE_CLASS (tmode) == MODE_FLOAT)
	    return expand_binop (tmode, flodiv_optab, const_tiny_rtx[1][tmode],
				 op0, target, 0, OPTAB_LIB_WIDEN);
	}
    }

  /* For now, always pass a floating point first argument to the
     library function.  */
  if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE)
    {
      rtx tmp = gen_reg_rtx (DFmode);
      expand_float (tmp, op0, 0);
      op0 = tmp;
    }

  if (GET_CODE (op1) == CONST_INT
      || GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT)
    emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__ipow"), 1,
		       DFmode, 2, op0, DFmode, op1, SImode);
  else
    emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "pow"), 1,
		       DFmode, 2, op0, DFmode,
		       convert_to_mode (DFmode, op1, 0),
		       DFmode);

  if (GET_MODE_CLASS (GET_MODE (target)) == MODE_INT)
    expand_fix (target, hard_libcall_value (DFmode), 0);
  else
    convert_move (target, hard_libcall_value (DFmode));

  return target;
}


add to c-typeck.c:build_binary_op and cp-typeck.c:build_binary_op_nodefault()

    case EXPON_EXPR:
      /* Rules for exponent: type of result is always converted type of LHS.
	 If RHS is integer, no conversions.
	 If RHS is real and LHS is integer, convert LHS to RHS.  */

      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
	  && code1 == INTEGER_TYPE)
	{
	  result_type = type0;
	  converted = 1;
	}
      else if (code0 == REAL_TYPE && code1 == REAL_TYPE)
	{
	  result_type = type0;
	  converted = 1;
	}
      else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
	{
	  op0 = convert (type1, op0);
	  result_type = type1;
	  converted = 1;
	}
      break;


*** cp-parse.y.orig	Thu Sep  3 22:27:15 1992
--- cp-parse.y	Sat Sep 12 13:11:06 1992
***************
*** 190,195 ****
--- 190,196 ----
  %left <code> '+' '-'
  %left <code> '*' '/' '%'
  %right <code> UNARY PLUSPLUS MINUSMINUS
+ %right <code> EXPON
  %left HYPERUNARY
  %left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
  %left <code> POINTSAT POINTSAT_STAR '.' DOT_STAR '(' '['
***************
*** 1209,1214 ****
--- 1210,1217 ----
  		{ $$ = build_x_binary_op ($2, $$, $3); }
  	| expr_no_commas '*' expr_no_commas
  		{ $$ = build_x_binary_op ($2, $$, $3); }
+ 	| expr_no_commas EXPON expr_no_commas
+ 		{ $$ = build_x_binary_op ($2, $$, $3); }
  	| expr_no_commas '/' expr_no_commas
  		{ $$ = build_x_binary_op ($2, $$, $3); }
  	| expr_no_commas '%' expr_no_commas
***************
*** 3736,3741 ****
--- 3739,3746 ----
  operator_name:
  	  OPERATOR '*'
  		{ $$ = ansi_opname[MULT_EXPR]; }
+ 	| OPERATOR EXPON
+ 		{ $$ = ansi_opname[EXPON_EXPR]; }
  	| OPERATOR '/'
  		{ $$ = ansi_opname[TRUNC_DIV_EXPR]; }
  	| OPERATOR '%'

*** c-parse.y	Wed Aug 26 20:42:25 1992
--- c-parse.y	Sun Sep 13 12:30:22 1992
***************
*** 130,135 ****
--- 130,136 ----
  %left <code> '+' '-'
  %left <code> '*' '/' '%'
  %right <code> UNARY PLUSPLUS MINUSMINUS
+ %right <code> EXPON
  %left HYPERUNARY
  %left <code> POINTSAT '.' '(' '['
  
***************
*** 402,407 ****
--- 403,410 ----
  		{ $$ = parser_build_binary_op ($2, $1, $3); }
  	| expr_no_commas '*' expr_no_commas
  		{ $$ = parser_build_binary_op ($2, $1, $3); }
+ 	| expr_no_commas EXPON expr_no_commas
+ 		{ $$ = parser_build_binary_op ($2, $$, $3); }
  	| expr_no_commas '/' expr_no_commas
  		{ $$ = parser_build_binary_op ($2, $1, $3); }
  	| expr_no_commas '%' expr_no_commas

*** c-lex.c	Tue Sep  1 20:23:56 1992
--- c-lex.c	Sun Sep 13 12:34:45 1992
***************
*** 1889,1894 ****
--- 1889,1910 ----
  	    }
  	else if ((c == '-') && (c1 == '>'))
  	  { value = POINTSAT; goto done; }
+ 	else if (c == '*' && c1 == '^')
+ 	  {
+ 	    yylval.code = EXPON_EXPR;
+ 	    token_buffer[2] = c1 = getc (finput);
+ 	    if (c1 == '=')
+ 	      {
+ 		value = ASSIGN;
+ 		goto done;
+ 	      }
+ 	    ungetc (c1, finput);
+ 	    token_buffer[2] = 0;
+ 	    value = EXPON;
+ 	    goto done;
+ 	  }
+ 
+ 
  	ungetc (c1, finput);
  	token_buffer[1] = 0;
  
*** cp-lex.c.orig	Thu Sep  3 22:27:06 1992
--- cp-lex.c	Sat Sep 12 13:30:12 1992
***************
*** 480,485 ****
--- 485,492 ----
    ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
    ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
    ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
+   ansi_opname[(int) EXPON_EXPR] = get_identifier ("__exp");
+   IDENTIFIER_OPNAME_P (ansi_opname[(int) EXPON_EXPR]) = 1;
    ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
    IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
    ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
***************
*** 658,663 ****
--- 665,671 ----
    opname_tab[(int) PLUS_EXPR] = "+";
    opname_tab[(int) MINUS_EXPR] = "-";
    opname_tab[(int) MULT_EXPR] = "*";
+   opname_tab[(int) EXPON_EXPR] = "*^";
    opname_tab[(int) TRUNC_DIV_EXPR] = "/";
    opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
    opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
***************
*** 707,712 ****
--- 715,721 ----
    assignop_tab[(int) MINUS_EXPR] = "-=";
    assignop_tab[(int) NEGATE_EXPR] = "-=";
    assignop_tab[(int) MULT_EXPR] = "*=";
+   assignop_tab[(int) MULT_EXPR] = "*^=";
    assignop_tab[(int) INDIRECT_REF] = "*=";
    assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
    assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
***************
*** 3592,3597 ****
--- 3605,3626 ----
  		     token_buffer);
  	    goto done;
  	  }
+ 	else if (c == '*' && c1 == '^')
+ 	  {
+ 	    c1 = getch ();
+ 	    yylval.code = EXPON_EXPR;
+ 	    if (c1 == '=')
+ 	      {
+ 		value = ASSIGN;
+ 		nextchar = -1;
+ 	      }
+ 	    else
+ 	      {
+ 		value = EXPON;
+ 		nextchar = c1;
+ 	      }
+ 	    goto done;
+ 	  }
  
  	nextchar = c1;
  	token_buffer[1] = 0;
*** c-common.c.orig	Tue Jul 28 23:46:51 1992
--- c-common.c	Sat Sep 12 13:45:45 1992
***************
*** 476,481 ****
--- 476,483 ----
      case LROTATE_EXPR:
      case RROTATE_EXPR:
        opname = "rotate"; break;
+     case EXPON_EXPR:
+       opname = "exponentiation"; break;
      }
    error ("invalid operands to binary %s", opname);
  }

--
    John Carr (jfc@athena.mit.edu)
Technical Details
Message-ID: <1992Sep16.005748.20420@athena.mit.edu>
Path: arc1-ca.pugleaf.net!sparky!uunet!haven.umd.edu!darwin.sura.net!wupost!micro-heart-of-gold.mit.edu!mintaka.lcs.mit.edu!bloom-picayune.mit.edu!athena.mit.edu!jfc
References: <1992Sep13.193507.27813@ima.isc.com> <MATT.92Sep14225005@physics2.berkeley.edu> <1992Sep15.201801.26417@murdoch.acc.Virginia.EDU>

Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c++,comp.lang.c++
Path: arc1-ca.pugleaf.net!sparky!uunet!haven.umd.edu!darwin.sura.net!wupost!micro-heart-of-gold.mit.edu!mintaka.lcs.mit.edu!bloom-picayune.mit.edu!athena.mit.edu!jfc
From: jfc@athena.mit.edu (John F Carr)
Subject: Re: Exponentiation operator proposal
Message-ID: <1992Sep16.005748.20420@athena.mit.edu>
Sender: news@athena.mit.edu (News system)
Nntp-Posting-Host: achates.mit.edu
Organization: Massachusetts Institute of Technology
References: <1992Sep13.193507.27813@ima.isc.com> <MATT.92Sep14225005@physics2.berkeley.edu> <1992Sep15.201801.26417@murdoch.acc.Virginia.EDU>
Date: Wed, 16 Sep 1992 00:57:48 GMT
Lines: 302