-- Routines the compiler knows to emit special code for.
--
-- The first column is the routine signature to replace.  The second
-- column is what to use instead, with #num indicating a particular
-- argument.  The third column is what to use if arith checking is on.  If it
-- contains "same" then it is interpreted identically whether checking is
-- on or off.
--
-- New addition by Matt Kennel, UCSD.  If the third column is "nomacro"
-- then the routine will NOT be macroized when bounds checking or
-- arithmetic checking is on.  Of course this means that you must have
-- a version of the routine with real Sather source code.  The intended
-- goal is for matrix and array access "aset" and "aget" routines to
-- be macroized during optimized compilation, but when bounds checking is
-- on we need the compiler to generate the real code so that its bounds
-- checking logic gets emitted there.
--
-- A leading '@' is a signal to the compiler that there may be special
-- handling.

"INT::plus(INT):INT"	"#1+#2" 			"c_INT_plus_INT_INT_chk(#1,#2)"
"INT::minus(INT):INT"	"#1-#2"   			"c_INT_minus_INT_INT_chk(#1,#2)"
"INT::times(INT):INT"	"#1*#2"         		"c_INT_times_INT_INT_chk(#1,#2)"

-- div and mod are special because they cannot just use the C / and %
-- operators which _may_ do the wrong things for negative arguments.
"INT::div(INT):INT"	"c_INT_div_INT_INT_chk(#1,#2)"  "same"
"INT::mod(INT):INT"	"c_INT_mod_INT_INT_chk(#1,#2)"  "same"

"INT::uplus(INT):INT"	"((unsigned)#1)+((unsigned)#2)"	"c_INT_uplus_INT_INT_chk(#1,#2)"
"INT::uminus(INT):INT"	"((unsigned)#1)-((unsigned)#2)"	"c_INT_uminus_INT_INT_chk(#1,#2)"
"INT::utimes(INT):INT"	"((unsigned)#1)*((unsigned)#2)"	"c_INT_utimes_INT_INT_chk(#1,#2)"
"INT::udiv(INT):INT"	"((unsigned)#1)/((unsigned)#2)"	"c_INT_udiv_INT_INT_chk(#1,#2)"
"INT::umod(INT):INT"	"((unsigned)#1)%((unsigned)#2)"	"c_INT_umod_INT_INT_chk(#1,#2)"
"INT::mplus(INT):INT"	"((unsigned)#1)+((unsigned)#2)" "same"
"INT::mminus(INT):INT"	"((unsigned)#1)-((unsigned)#2)" "same"
"INT::mtimes(INT):INT"	"((unsigned)#1)*((unsigned)#2)" "same"
"INT::mnegate:INT"	"-#1"                           "same"
"INT::is_lt(INT):BOOL"	"#1<#2"				"same"
"INT::is_gt(INT):BOOL"	"#1>#2"				"same"
"INT::is_leq(INT):BOOL"	"#1<=#2"			"same"
"INT::is_geq(INT):BOOL"	"#1>=#2"			"same"
"INT::flt:FLT"		"(FLT)#1"			"same"
"INT::fltd:FLTD"	"(FLTD)#1"			"same"
"INT::flte:FLTE"	"(FLTE)#1"			"same"
"INT::fltde:FLTDE"	"(FLTDE)#1"			"same"
"INT::int:INT"		"(INT)#1"			"same"
"INT::char:CHAR"	"(CHAR)#1"			"same"
"INT::bnot:INT"		"~#1"				"same"
"INT::band(INT):INT"	"#1&#2"				"same"
"INT::bor(INT):INT"	"#1|#2"				"same"
"INT::bxor(INT):INT"	"#1^#2"				"same"
"INT::lshift(INT):INT"	"#1<<#2"			"same"
"INT::rshift(INT):INT"	"c_INT_rshift_INT_INT(#1,#2)"	"same"
"INT::urshift(INT):INT"	"((unsigned)#1)>>((unsigned)#2)" "same"
"INT::is_eq(INT):BOOL"	"#1==#2"			"same"
"INT::is_neq(INT):BOOL"	"#1!=#2"			"same"
"INT::aset(INT,BOOL):INT" "(#1&(~(1<<#2)))|(#3<<#2)"    "same"
"INT::aget(INT):BOOL"   "(CHAR)((#1&(1<<#2))!=0)"	"same"
"INT::maxint:INT"	"SINT_MAX"			"same"
"INT::minint:INT"	"SINT_MIN"			"same"

"BOOL::not:BOOL"	"!(#1)"				"same"
"BOOL::is_eq(BOOL):BOOL" "(#1)==(#2)"			"same"
"BOOL::is_neq(BOOL):BOOL" "(#1)!=(#2)"			"same"

"SYS::destroy($OB)"	"c_SYS_destroy_OB(#1,#2)"	"same"
"SYS::id($OB):INT"	"c_SYS_id_OB_INT(#1,#2)"	"same"
"SYS::tp($OB):INT"	"c_SYS_tp_OB_INT(#1,#2)"	"same"
"SYS::str_for_tp(INT):STR" "c_SYS_str_for_tp_INT_STR(#1,#2)" "same"
"SYS::ob_eq($OB,$OB):BOOL" "@1c_SYS_ob_eq_OB_OB_BOOL(#2,#3)" "same"
"SYS::ext_ob_for($OB):EXT_OB" "#2"			"same"

"FILE::stdin_macro:EXT_OB"	"stdin"			"same"
"FILE::stdout_macro:EXT_OB"	"stdout"		"same"
"FILE::stderr_macro:EXT_OB"	"stderr"		"same"

"CHAR::is_eq(CHAR):BOOL" "#1==#2"			"same"
"CHAR::is_neq(CHAR):BOOL" "#1!=#2"			"same"
"CHAR::int:INT"		"(INT)#1"			"same"
"CHAR::aset(INT,BOOL):CHAR" "(CHAR)((#1&(~(1<<#2)))|(#3<<#2))" "same"
"CHAR::aget(INT):BOOL"   "(CHAR)((#1&(1<<#2))!=0)"	"same"

"FLT::plus(FLT):FLT"	"#1+#2"				"same"
"FLT::minus(FLT):FLT" 	"#1-#2"				"same"
"FLT::times(FLT):FLT" 	"#1*#2"				"same"
"FLT::div(FLT):FLT"	"#1/#2"				"same"
"FLT::negate:FLT"	"-(#1)"				"same"
"FLT::is_eq(FLT):BOOL" 	"#1==#2"			"same"
"FLT::is_neq(FLT):BOOL" "#1!=#2"			"same"
"FLT::is_lt(FLT):BOOL"  "#1<#2"				"same"
"FLT::is_leq(FLT):BOOL" "#1<=#2"			"same"
"FLT::is_gt(FLT):BOOL"  "#1>#2"				"same"
"FLT::is_geq(FLT):BOOL" "#1>=#2"			"same"
"FLT::fltd:FLTD"        "(FLTD)#1"			"same"
"FLT::fltx:FLTX"        "(FLTX)#1"			"same"
"FLT::fltdx:FLTDX"      "(FLTDX)#1"			"same"
"FLT::aset(INT,BOOL):FLT" "c_flt_aset(#1,#2,#3)"	"same"
"FLT::aget(INT):BOOL"	"c_flt_aget(#1,#2)"		"same"

"FLTD::plus(FLTD):FLTD"	 "#1+#2"			"same"
"FLTD::minus(FLTD):FLTD" "#1-#2"			"same"
"FLTD::times(FLTD):FLTD" "#1*#2"			"same"
"FLTD::div(FLTD):FLTD"	 "#1/#2"			"same"
"FLTD::negate:FLTD"	 "-(#1)"			"same"
"FLTD::is_eq(FLTD):BOOL" "#1==#2"			"same"
"FLTD::is_neq(FLTD):BOOL" "#1!=#2"			"same"
"FLTD::is_lt(FLTD):BOOL"  "#1<#2"			"same"
"FLTD::is_leq(FLTD):BOOL" "#1<=#2"			"same"
"FLTD::is_gt(FLTD):BOOL"  "#1>#2"			"same"
"FLTD::is_geq(FLTD):BOOL" "#1>=#2"			"same"
"FLTD::flt:FLT"            "(FLT)#1"			"same"
"FLTD::fltx:FLTX"          "(FLTX)#1"			"same"
"FLTD::fltdx:FLTDX"        "(FLTDX)#1"			"same"
"FLTD::pi:FLTD"		   "M_PI"			"same"
"FLTD::e:FLTD"		   "M_E"			"same"
"FLTD::sqrt_2:FLTD"	   "M_SQRT2"			"same"
"FLTD::log_2:FLTD"	   "M_LN2"			"same"
"FLTD::log2_e:FLTD"	   "M_LOG2E"			"same"
"FLTD::log10_e:FLTD"	   "M_LOG10E"			"same"
"FLTD::log_10:FLTD"	   "M_LN10"			"same"
"FLTD::half_pi:FLTD"	   "M_PI_2"			"same"
"FLTD::quarter_pi:FLTD"	   "M_PI_4"			"same"
"FLTD::inv_sqrt_2:FLTD"	   "M_SQRT1_2"			"same"
"FLTD::inv_pi:FLTD"	   "M_1_PI"			"same"
"FLTD::double_inv_pi:FLTD" "M_2_PI"			"same"
"FLTD::double_sqrt_pi:FLTD" "M_2_SQRTPI"		"same"
"FLTD::aset(INT,BOOL):FLTD" "c_fltd_aset(#1,#2,#3)"	"same"
"FLTD::aget(INT):BOOL"	   "c_fltd_aget(#1,#2)"		"same"

-- System or architecture specific things go here.
--#ifdef ALPHA 
--    "INT::asize:INT" "64" "same"
--#endif



-- Everything from here on after was added by MBK
"FILE::plus(STR)" "fwrite(#2->arr_part,#2->asize,1,#1->fp)" "same"

"STR::acopyn(FSTR,INT)"		"memcpy(#1->arr_part,#2->arr_part,#3)" "same"
"FSTR::acopyn(STR,INT)"		"memcpy(#1->arr_part,#2->arr_part,#3)" "same"
"STR::acopyn(STR,INT)"		"memcpy(#1->arr_part,#2->arr_part,#3)" "same"
"FSTR::acopyn(FSTR,INT)"	"memcpy(#1->arr_part,#2->arr_part,#3)" "same"


"STR::acopy(STR)"		"memcpy(#1->arr_part,#2->arr_part,(#1->asize) > (#2->asize) ? #2->asize:#1->asize)" "same"
"STR::acopy(INT,STR)"		"memcpy(#1->arr_part+#2,#3->arr_part,(#1->asize)-#2 > #3->asize ? #3->asize:(#1->asize)-#2)" "same"

"FSTR::acopy(FSTR)"		"memcpy(#1->arr_part,#2->arr_part,(#1->asize) > (#2->asize) ? #2->asize:#1->asize)" "same"
"FSTR::acopy(STR)"		"memcpy(#1->arr_part,#2->arr_part,(#1->asize) > (#2->asize) ? #2->asize:#1->asize)" "same"
"FSTR::acopy(INT,STR)"		"memcpy(#1->arr_part+#2,#3->arr_part,(#1->asize)-#2 > #3->asize ? #3->asize:(#1->asize)-#2)" "same"

"STR::is_eq_helper(STR,INT):BOOL"	"(memcmp(#1->arr_part,#2->arr_part,#3)==0 ? TRUE : FALSE)" "same"
"FSTR::is_eq_helper(FSTR,INT):BOOL"	"(memcmp(#1->arr_part,#2->arr_part,#3)==0 ? TRUE : FALSE)" "same"
"FSTR::is_eq_helper(STR,INT):BOOL"	"(memcmp(#1->arr_part,#2->arr_part,#3)==0 ? TRUE : FALSE)" "same"

"STR::aset(INT,CHAR)"	 	"#1->arr_part[#2]=#3"	"nomacro"
"FSTR::aset(INT,CHAR)"	 	"#1->arr_part[#2]=#3"	"nomacro"
"STR::aget(INT):CHAR"		"#1->arr_part[#2]"	"nomacro"
"FSTR::aget(INT):CHAR"		"#1->arr_part[#2]"	"nomacro"

-- 1-d aget of 1d structures
"ARRAY{INT}::aget(INT):INT"	"#1->arr_part[#2]"	"nomacro"
"ARRAY{FLT}::aget(INT):FLT"	"#1->arr_part[#2]"	"nomacro"
"ARRAY{FLTD}::aget(INT):FLTD"	"#1->arr_part[#2]"	"nomacro"
"VEC::aget(INT):FLT"		"#1->arr_part[#2]"	"nomacro"

"AREF{INT}::aget(INT):INT"	"#1->arr_part[#2]"	"nomacro"
"AREF{FLT}::aget(INT):FLT"	"#1->arr_part[#2]"	"nomacro"
"AREF{FLTD}::aget(INT):FLTD"	"#1->arr_part[#2]"	"nomacro"

-- 1d getting of 2-d structures
"ARRAY2{INT}::aget(INT):INT"	"#1->arr_part[#2]"	"nomacro"
"ARRAY2{FLT}::aget(INT):FLT"	"#1->arr_part[#2]"	"nomacro"
"ARRAY2{FLTD}::aget(INT):FLTD"	"#1->arr_part[#2]"	"nomacro"
"MAT::aget(INT):FLT"		"#1->arr_part[#2]"	"nomacro"
"FORTMAT::aget(INT):FLT"	"#1->arr_part[#2]"	"nomacro"

-- 2d getting of 2d structures
"MAT::aget(INT,INT):FLT"		"#1->arr_part[#2 *#1->asize2 + #3]" 	"nomacro"
"ARRAY2{INT}::aget(INT,INT):INT"	"#1->arr_part[#2*#1->asize2 + #3]" 	"nomacro"
"ARRAY2{FLT}::aget(INT,INT):FLT"	"#1->arr_part[#2*#1->asize2 + #3]" 	"nomacro"
"ARRAY2{FLTD}::aget(INT,INT):FLTD"	"#1->arr_part[#2*#1->asize2 + #3]" 	"nomacro"

-- notice this one works the other way around, because of Fortran
-- storage order
"FORTMAT::aget(INT,INT):FLT"	"#1->arr_part[#3 *#1->asize1 + #2]"	"nomacro"

-- 1-d setting of 1-d structures
"ARRAY{INT}::aset(INT,INT)"		"#1->arr_part[#2]=#3"	"nomacro"
"ARRAY{FLT}::aset(INT,FLT)"		"#1->arr_part[#2]=#3"	"nomacro"
"ARRAY{FLTD}::aset(INT,FLTD)"		"#1->arr_part[#2]=#3"	"nomacro"

"AREF{INT}::aset(INT,INT)" 		"#1->arr_part[#2]=#3"	"nomacro"
"AREF{FLT}::aset(INT,FLT)" 		"#1->arr_part[#2]=#3"	"nomacro"
"AREF{FLTD}::aset(INT,FLTD)" 		"#1->arr_part[#2]=#3"	"nomacro"


-- 1d setting of 2-d structures

"ARRAY2{INT}::aset(INT,INT)" 		"#1->arr_part[#2]=#3"	"nomacro"
"ARRAY2{FLT}::aset(INT,FLT)" 		"#1->arr_part[#2]=#3"	"nomacro"
"ARRAY2{FLTD}::aset(INT,FLTD)" 		"#1->arr_part[#2]=#3"	"nomacro"

"MAT::aset(INT,FLT)" 			"#1->arr_part[#2]=#3"	"nomacro"
"FORTMAT::aset(INT,FLT)" 		"#1->arr_part[#2]=#3"	"nomacro"
"VEC::aset(INT,FLT)" 			"#1->arr_part[#2]=#3"	"nomacro"

-- 2d setting of 2-d structures
-- notice that the compiler had to be patched to allow macro arguments
-- #4 and #5
"MAT::aset(INT,INT,FLT)"		"#1->arr_part[#2*#1->asize2+#3]=#4"	"nomacro"
"ARRAY2{INT}::aset(INT,INT,INT)"	"#1->arr_part[#2*#1->asize2+#3]=#4"	"nomacro"
"ARRAY2{FLT}::aset(INT,INT,FLT)"	"#1->arr_part[#2*#1->asize2+#3]=#4"  	"nomacro"
"ARRAY2{FLTD}::aset(INT,INT,FLTD)"	"#1->arr_part[#2*#1->asize2+#3]=#4"  	"nomacro"

-- again, backwards from MAT
"FORTMAT::aset(INT,INT,FLT)"		"#1->arr_part[#3*#1->asize1+#2]=#4"	"nomacro"
