Commit c906a2a7 authored by mmitchel's avatar mmitchel
Browse files

* cplus-dem.c (optable): Add sizeof.

	(demangle_template_value_parm): New function containing code
	previously found in demangle_template.
	(demangle_integral_value): New function which handles complicated
	integral expressions.
	(demangle_template): Use them.
	* error.c (dump_expr): Remove unused variable `l'.
	* pt.c (for_each_template_parm): New function, created by
	converting uses_template_parms.
	(tree_fn_t): New typedef.
	(uses_template_parms): Use it.
	(mark_template_parm): New function.
	(push_template_decl): Check that the argument list of a partial
	specialization uses all the template parameters.
	* Make-lang.in (c++filt): Don't delete cxxmain.c after we're done
	with it; we might want it for debugging.
	* cp-tree.h (type_unification): Change interface.
	* class.c (finish_struct_1): Skip nested template types, just like
	ordinary nested types.
	(instantiate_type): Use new interface to type_unification.
	* lex.c (init_lex): Add __sz as opname for sizeof.
	* method.c (build_overload_scope_ref): New function.
	(build_overload_int): Handle complex expressions.  Set
	numeric_output_need_bar if necessary.
	(build_overload_value): Handle non-PARM_DECL nodes; this
	routine is now used by build_overload_int.  Remove some
	assignments to numeric_output_need_bar.  Use
	build_overload_scope_ref.
	(build_qualified_name): Note that some template mangled names end
	with digits, and set numeric_output_need_bar appropriately.  Use
	build_underscore_int.
	* pt.c (unify): Change interface.
	(type_unification_real): Likewise.
	(determine_specialization): Use new interfaces.
	(tsubst): Deal gracefully with situations in which the argument
	vector is not fully filled.
	(fn_type_unification): Use new interfaces.
	(type_unification): Likewise.  Remove NOP_EXPR hack.
	(type_unification_real): Likewise.
	(unify): Likewise.  Deal with unification of complex expresions.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18795 138bc75d-0d04-0410-961f-82ee72b054a4
parent 5ce88198
1998-03-24 Mark Mitchell <mmitchell@usa.net>
* cplus-dem.c (optable): Add sizeof.
(demangle_template_value_parm): New function containing code
previously found in demangle_template.
(demangle_integral_value): New function which handles complicated
integral expressions.
(demangle_template): Use them.
Tue Mar 24 12:13:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (genconfig.o, genflags.o, gencodes.o, genemit.o,
......
Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
* error.c (dump_expr): Remove unused variable `l'.
* pt.c (for_each_template_parm): New function, created by
converting uses_template_parms.
(tree_fn_t): New typedef.
(uses_template_parms): Use it.
(mark_template_parm): New function.
(push_template_decl): Check that the argument list of a partial
specialization uses all the template parameters.
* Make-lang.in (c++filt): Don't delete cxxmain.c after we're done
with it; we might want it for debugging.
* cp-tree.h (type_unification): Change interface.
* class.c (finish_struct_1): Skip nested template types, just like
ordinary nested types.
(instantiate_type): Use new interface to type_unification.
* lex.c (init_lex): Add __sz as opname for sizeof.
* method.c (build_overload_scope_ref): New function.
(build_overload_int): Handle complex expressions. Set
numeric_output_need_bar if necessary.
(build_overload_value): Handle non-PARM_DECL nodes; this
routine is now used by build_overload_int. Remove some
assignments to numeric_output_need_bar. Use
build_overload_scope_ref.
(build_qualified_name): Note that some template mangled names end
with digits, and set numeric_output_need_bar appropriately. Use
build_underscore_int.
* pt.c (unify): Change interface.
(type_unification_real): Likewise.
(determine_specialization): Use new interfaces.
(tsubst): Deal gracefully with situations in which the argument
vector is not fully filled.
(fn_type_unification): Use new interfaces.
(type_unification): Likewise. Remove NOP_EXPR hack.
(type_unification_real): Likewise.
(unify): Likewise. Deal with unification of complex expresions.
Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (complete_template_args): Initialize skip properly.
......
......@@ -107,7 +107,6 @@ cxxmain.o: cplus-dem.c demangle.h
$(LN_S) $(srcdir)/cplus-dem.c cxxmain.c
$(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DVERSION=\"$(version)\" cxxmain.c
rm -f cxxmain.c
$(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \
......
......@@ -3322,7 +3322,8 @@ finish_struct_1 (t, warn_anon)
last_x = x;
if (TREE_CODE (x) == TYPE_DECL)
if (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == TEMPLATE_DECL)
continue;
/* If we've gotten this far, it's a data member, possibly static,
......@@ -5174,8 +5175,8 @@ instantiate_type (lhstype, rhs, complain)
tree t = make_scratch_vec (n);
int i;
i = type_unification
(DECL_INNERMOST_TEMPLATE_PARMS (elem),
&TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
(DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1);
if (i == 0)
{
......
......@@ -2463,7 +2463,7 @@ extern tree instantiate_class_template PROTO((tree));
extern tree instantiate_template PROTO((tree, tree));
extern void overload_template_name PROTO((tree));
extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, int, tree));
extern int type_unification PROTO((tree, tree *, tree, tree, tree, int, int));
extern int type_unification PROTO((tree, tree, tree, tree, tree, int, int));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree));
......
......@@ -1533,12 +1533,7 @@ dump_expr (t, nop)
}
case TEMPLATE_PARM_INDEX:
{
int l = current_template_parms ?
list_length (current_template_parms) : 0;
dump_decl (TEMPLATE_PARM_DECL (t), -1);
}
dump_decl (TEMPLATE_PARM_DECL (t), -1);
break;
case IDENTIFIER_NODE:
......
......@@ -471,6 +471,16 @@ build_underscore_int (i)
OB_PUTC ('_');
}
static void
build_overload_scope_ref (value)
tree value;
{
OB_PUTC2 ('Q', '2');
numeric_output_need_bar = 0;
build_mangled_name (TREE_OPERAND (value, 0), 0, 0);
build_overload_identifier (TREE_OPERAND (value, 1));
}
/* Encoding for an INTEGER_CST value. */
static void
......@@ -479,13 +489,70 @@ build_overload_int (value, in_template)
int in_template;
{
if (in_template && TREE_CODE (value) != INTEGER_CST)
/* We don't ever want this output, but it's inconvenient not to
be able to build the string. This should cause assembler
errors we'll notice. */
{
static int n;
sprintf (digit_buffer, " *%d", n++);
OB_PUTCP (digit_buffer);
if (TREE_CODE (value) == SCOPE_REF)
{
build_overload_scope_ref (value);
return;
}
OB_PUTC ('E');
numeric_output_need_bar = 0;
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value))))
{
int i;
int operands = tree_code_length[(int) TREE_CODE (value)];
tree id;
char* name;
id = ansi_opname [(int) TREE_CODE (value)];
my_friendly_assert (id != NULL_TREE, 0);
name = IDENTIFIER_POINTER (id);
my_friendly_assert (name[0] == '_' && name[1] == '_', 0);
for (i = 0; i < operands; ++i)
{
tree operand;
enum tree_code tc;
/* We just outputted either the `E' or the name of the
operator. */
numeric_output_need_bar = 0;
if (i != 0)
/* Skip the leading underscores. */
OB_PUTCP (name + 2);
operand = TREE_OPERAND (value, i);
tc = TREE_CODE (operand);
if (TREE_CODE_CLASS (tc) == 't')
/* We can get here with sizeof, e.g.:
template <class T> void f(A<sizeof(T)>); */
process_overload_item (operand, 0);
else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
build_overload_int (operand, in_template);
else
build_overload_value (TREE_TYPE (operand),
operand,
in_template);
}
}
else
{
/* We don't ever want this output, but it's
inconvenient not to be able to build the string.
This should cause assembler errors we'll notice. */
static int n;
sprintf (digit_buffer, " *%d", n++);
OB_PUTCP (digit_buffer);
}
OB_PUTC ('W');
numeric_output_need_bar = 0;
return;
}
......@@ -497,12 +564,14 @@ build_overload_int (value, in_template)
{
/* need to print a DImode value in decimal */
dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value));
numeric_output_need_bar = 1;
return;
}
/* else fall through to print in smaller mode */
}
/* Wordsize or smaller */
icat (TREE_INT_CST_LOW (value));
numeric_output_need_bar = 1;
}
......@@ -531,8 +600,11 @@ build_overload_value (type, value, in_template)
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242);
type = TREE_TYPE (type);
if (TREE_CODE (type) == PARM_DECL)
type = TREE_TYPE (type);
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
if (numeric_output_need_bar)
{
......@@ -569,7 +641,6 @@ build_overload_value (type, value, in_template)
case BOOLEAN_TYPE:
{
build_overload_int (value, in_template);
numeric_output_need_bar = 1;
return;
}
case REAL_TYPE:
......@@ -672,7 +743,6 @@ build_overload_value (type, value, in_template)
{
OB_PUTC ('i');
build_overload_int (a3, in_template);
numeric_output_need_bar = 1;
return;
}
}
......@@ -683,7 +753,6 @@ build_overload_value (type, value, in_template)
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value, in_template);
numeric_output_need_bar = 1;
return;
}
else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
......@@ -707,13 +776,7 @@ build_overload_value (type, value, in_template)
return;
}
else if (TREE_CODE (value) == SCOPE_REF)
{
OB_PUTC2 ('Q', '1');
numeric_output_need_bar = 0;
build_mangled_name (TREE_OPERAND (value, 0), 0, 0);
build_overload_identifier (TREE_OPERAND (value, 1));
return;
}
build_overload_scope_ref (value);
else
my_friendly_abort (71);
break; /* not really needed */
......@@ -865,7 +928,10 @@ build_qualified_name (decl)
if (TREE_CODE (decl) == TYPE_DECL
&& DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
{
OB_PUTID (DECL_ASSEMBLER_NAME (decl));
tree id = DECL_ASSEMBLER_NAME (decl);
OB_PUTID (id);
if (isdigit (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1]))
numeric_output_need_bar = 1;
return;
}
......@@ -907,11 +973,7 @@ build_qualified_name (decl)
if (i > 1)
{
OB_PUTC ('Q');
if (i > 9)
OB_PUTC ('_');
icat (i);
if (i > 9)
OB_PUTC ('_');
build_underscore_int (i);
numeric_output_need_bar = 0;
}
build_overload_nested_name (decl);
......
This diff is collapsed.
......@@ -197,7 +197,8 @@ static const struct optable
{"min", "<?", 0}, /* old */
{"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
{"nop", "", 0}, /* old (for operator=) */
{"rm", "->*", DMGL_ANSI} /* ansi */
{"rm", "->*", DMGL_ANSI}, /* ansi */
{"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
};
......@@ -330,6 +331,10 @@ forget_types PARAMS ((struct work_stuff *));
static void
string_prepends PARAMS ((string *, string *));
static int
demangle_template_value_parm PARAMS ((struct work_stuff*,
const char**, string*));
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
Trying to consume something that isn't a count results in
......@@ -995,6 +1000,270 @@ demangle_template_template_parm (work, mangled, tname)
return (success);
}
static int
demangle_integral_value (work, mangled, s)
struct work_stuff *work;
const char** mangled;
string* s;
{
int success;
if (**mangled == 'E')
{
int need_operator = 0;
success = 1;
string_appendn (s, "(", 1);
(*mangled)++;
while (success && **mangled != 'W' && **mangled != '\0')
{
if (need_operator)
{
size_t i;
size_t len;
success = 0;
len = strlen (*mangled);
for (i = 0;
i < sizeof (optable) / sizeof (optable [0]);
++i)
{
size_t l = strlen (optable[i].in);
if (l <= len
&& memcmp (optable[i].in, *mangled, l) == 0)
{
string_appendn (s, " ", 1);
string_append (s, optable[i].out);
string_appendn (s, " ", 1);
success = 1;
(*mangled) += l;
break;
}
}
if (!success)
break;
}
else
need_operator = 1;
success = demangle_template_value_parm (work, mangled, s);
}
if (**mangled != 'W')
success = 0;
else
{
string_appendn (s, ")", 1);
(*mangled)++;
}
}
else if (**mangled == 'Q')
success = demangle_qualified (work, mangled, s, 0, 1);
else
{
success = 0;
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
success = 1;
}
}
return success;
}
static int
demangle_template_value_parm (work, mangled, s)
struct work_stuff *work;
const char **mangled;
string* s;
{
const char *old_p = *mangled;
int is_pointer = 0;
int is_real = 0;
int is_integral = 0;
int is_char = 0;
int is_bool = 0;
int done = 0;
int success = 1;
while (*old_p && !done)
{
switch (*old_p)
{
case 'P':
case 'p':
case 'R':
done = is_pointer = 1;
break;
case 'C': /* const */
case 'S': /* explicitly signed [char] */
case 'U': /* unsigned */
case 'V': /* volatile */
case 'F': /* function */
case 'M': /* member function */
case 'O': /* ??? */
case 'J': /* complex */
old_p++;
continue;
case 'E': /* expression */
case 'Q': /* qualified name */
done = is_integral = 1;
break;
case 'T': /* remembered type */
abort ();
break;
case 'v': /* void */
abort ();
break;
case 'x': /* long long */
case 'l': /* long */
case 'i': /* int */
case 's': /* short */
case 'w': /* wchar_t */
done = is_integral = 1;
break;
case 'b': /* bool */
done = is_bool = 1;
break;
case 'c': /* char */
done = is_char = 1;
break;
case 'r': /* long double */
case 'd': /* double */
case 'f': /* float */
done = is_real = 1;
break;
default:
/* it's probably user defined type, let's assume
it's integral, it seems hard to figure out
what it really is */
done = is_integral = 1;
}
}
if (**mangled == 'Y')
{
/* The next argument is a template parameter. */
int idx;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1
|| (work->tmpl_argvec && idx >= work->ntmpl_args)
|| consume_count_with_underscores (mangled) == -1)
return -1;
if (work->tmpl_argvec)
string_append (s, work->tmpl_argvec[idx]);
else
{
char buf[10];
sprintf(buf, "T%d", idx);
string_append (s, buf);
}
}
else if (is_integral)
success = demangle_integral_value (work, mangled, s);
else if (is_char)
{
char tmp[2];
int val;
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
string_appendn (s, "'", 1);
val = consume_count(mangled);
if (val == 0)
return -1;
tmp[0] = (char)val;
tmp[1] = '\0';
string_appendn (s, &tmp[0], 1);
string_appendn (s, "'", 1);
}
else if (is_bool)
{
int val = consume_count (mangled);
if (val == 0)
string_appendn (s, "false", 5);
else if (val == 1)
string_appendn (s, "true", 4);
else
success = 0;
}
else if (is_real)
{
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
if (**mangled == '.') /* fraction */
{
string_appendn (s, ".", 1);
(*mangled)++;
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
if (**mangled == 'e') /* exponent */
{
string_appendn (s, "e", 1);
(*mangled)++;
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
}
else if (is_pointer)
{
int symbol_len = consume_count (mangled);
if (symbol_len == 0)
return -1;
if (symbol_len == 0)
string_appendn (s, "0", 1);
else
{
char *p = xmalloc (symbol_len + 1), *q;
strncpy (p, *mangled, symbol_len);
p [symbol_len] = '\0';
q = cplus_demangle (p, work->options);
string_appendn (s, "&", 1);
if (q)
{
string_append (s, q);
free (q);
}
else
string_append (s, p);
free (p);
}
*mangled += symbol_len;
}
return success;
}
static int
demangle_template (work, mangled, tname, trawname, is_type)
struct work_stuff *work;
......@@ -1004,18 +1273,10 @@ demangle_template (work, mangled, tname, trawname, is_type)
int is_type;
{
int i;
int is_pointer;
int is_real;
int is_integral;
int is_char;
int is_bool;
int r;
int need_comma = 0;
int success = 0;
int done;
const char *old_p;
const char *start;
int symbol_len;
int is_java_array = 0;
string temp;
......@@ -1148,13 +1409,7 @@ demangle_template (work, mangled, tname, trawname, is_type)
string* s;
/* otherwise, value parameter */
old_p = *mangled;
is_pointer = 0;
is_real = 0;
is_integral = 0;
is_char = 0;
is_bool = 0;
done = 0;
/* temp is initialized in do_type */
success = do_type (work, mangled, &temp);
/*
......@@ -1180,193 +1435,16 @@ demangle_template (work, mangled, tname, trawname, is_type)
else
s = tname;
while (*old_p && !done)
{
switch (*old_p)
{
case 'P':
case 'p':
case 'R':
done = is_pointer = 1;
break;
case 'C': /* const */
case 'S': /* explicitly signed [char] */
case 'U': /* unsigned */
case 'V': /* volatile */
case 'F': /* function */
case 'M': /* member function */
case 'O': /* ??? */
case 'J': /* complex */
old_p++;
continue;
case 'Q': /* qualified name */
done = is_integral = 1;
break;
case 'T': /* remembered type */
abort ();
break;
case 'v': /* void */
abort ();
break;
case 'x': /* long long */
case 'l': /* long */
case 'i': /* int */
case 's': /* short */
case 'w': /* wchar_t */
done = is_integral = 1;
break;
case 'b': /* bool */
done = is_bool = 1;
break;
case 'c': /* char */
done = is_char = 1;
break;
case 'r': /* long double */
case 'd': /* double */
case 'f': /* float */
done = is_real = 1;
break;
default:
/* it's probably user defined type, let's assume
it's integral, it seems hard to figure out
what it really is */
done = is_integral = 1;
}
}
if (**mangled == 'Y')
{
/* The next argument is a template parameter. */
int idx;
success = demangle_template_value_parm (work, mangled, s);
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1
|| (work->tmpl_argvec && idx >= work->ntmpl_args)
|| consume_count_with_underscores (mangled) == -1)
{
success = 0;
if (!is_type)
string_delete (s);
break;
}
if (work->tmpl_argvec)
string_append (s, work->tmpl_argvec[idx]);
else
{
char buf[10];
sprintf(buf, "T%d", idx);
string_append (s, buf);
}
}
else if (is_integral)
{
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
else if (is_char)
{
char tmp[2];
int val;
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
string_appendn (s, "'", 1);
val = consume_count(mangled);
if (val == 0)
{
success = 0;
if (!is_type)
string_delete (s);
break;
}
tmp[0] = (char)val;
tmp[1] = '\0';
string_appendn (s, &tmp[0], 1);
string_appendn (s, "'", 1);
}
else if (is_bool)
{
int val = consume_count (mangled);
if (val == 0)
string_appendn (s, "false", 5);
else if (val == 1)
string_appendn (s, "true", 4);
else
success = 0;
}
else if (is_real)
{
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
if (**mangled == '.') /* fraction */
{
string_appendn (s, ".", 1);
(*mangled)++;
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
if (**mangled == 'e') /* exponent */
{
string_appendn (s, "e", 1);
(*mangled)++;
while (isdigit (**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
}
else if (is_pointer)
if (!success)
{
symbol_len = consume_count (mangled);
if (symbol_len == 0)
{
success = 0;
if (!is_type)
string_delete (s);
break;
}
if (symbol_len == 0)
string_appendn (s, "0", 1);
else
{
char *p = xmalloc (symbol_len + 1), *q;
strncpy (p, *mangled, symbol_len);
p [symbol_len] = '\0';
q = cplus_demangle (p, work->options);
string_appendn (s, "&", 1);
if (q)
{
string_append (s, q);
free (q);
}
else
string_append (s, p);
free (p);
}
*mangled += symbol_len;
if (!is_type)
string_delete (s);
success = 0;
break;
}
if (!is_type)
{
int len = s->p - s->b;
......
// Build don't link:
template <unsigned rank>
class Tensor
{
};
template <unsigned rank>
class Tensor<2> : Tensor<rank> { // ERROR - template parameters not used
};
template <int n> class vec {
double x[n];
public:
vec() {
for (int i=0; i<n-1; ++i) x[i]=0;
}
vec(const vec<n>& v) {
for (int i=0; i<n; ++i) x[i]=v(i);
}
vec(const vec<n-1>& v, const double& y) {
for (int i=0; i<n-1; ++i) x[i]=v(i);
x[n-1]=y;
}
inline double operator()(const int i) const {
return x[i];
}
};
template <int n> vec<n + 1>& operator,(const vec<n>& v, const double& y) {
return *(new vec<n + 1>(v, y));
}
int main() {
vec<4> v;
vec<5> w;
w=(v,3.);
}
// Build don't link:
template <int I>
struct S {};
template <int J>
void foo(S<J + 2>);
void bar()
{
foo(S<3>()); // ERROR - no way to deduce J from this.
}
// Build don't link:
template <int I>
struct S {};
template <int J>
void foo(S<J - 1>);
template <class T>
void baz(S<sizeof(T)>);
template <int J>
void fun(S<J>, S<J * 2>);
void bar()
{
foo<5>(S<4>()); // OK - 4 is 5 - 1.
baz<int>(S<sizeof(int)>()); // OK
fun(S<4>(), S<8>()); // OK - deduce J from first argument.
}
template<class View, class W>
class TinyContainer {
public:
typedef W T_Wrapped;
TinyContainer() { }
TinyContainer(View data) : m_data(data) { }
T_Wrapped &unwrap()
{
return *static_cast<T_Wrapped *>(this);
}
const T_Wrapped &unwrap() const
{
return *static_cast<const T_Wrapped *>(this);
}
protected:
mutable View m_data;
};
template<class Op, class Left, class Right>
class TinyBinaryExpr :
public TinyContainer< Op, TinyBinaryExpr<Op, Left, Right> > {
public:
typedef typename Left::T_Return T_Return;
typedef TinyBinaryExpr<Op, Left, Right> T_Expr;
T_Expr makeExpr() const { return *this; }
TinyBinaryExpr(const Op &op, const Left &left, const Right &right)
: TinyContainer< Op, TinyBinaryExpr<Op, Left, Right> >(op),
m_left(left), m_right(right)
{ }
TinyBinaryExpr(const Left &left, const Right &right)
: m_left(left), m_right(right)
{ }
Op op() const { return m_data; }
Left left() const { return m_left; }
Right right() const { return m_right; }
private:
Left m_left;
Right m_right;
};
struct OpAdd {
template<class T1, class T2>
static T1 apply(const T1 &l, const T2 &r)
{
return l + r;
}
};
template<class V1, class T1, class V2, class T2>
inline TinyBinaryExpr<OpAdd, typename T1::T_Expr, typename T2::T_Expr>
operator+(const TinyContainer<V1,T1>& l, const TinyContainer<V2,T2>& r)
{
typedef TinyBinaryExpr<OpAdd, typename T1::T_Expr, typename T2::T_Expr> ret;
return ret(l.unwrap().makeExpr(), r.unwrap().makeExpr());
}
template<class Op, class T1, class T2, class Functor>
inline
typename T1::T_Return
for_each(const TinyBinaryExpr<Op,T1,T2>& node, Functor f)
{
return Op::apply(for_each(node.left(),f), for_each(node.right(),f));
}
template<class T, unsigned Nrows, unsigned Ncols, unsigned S1, unsigned S2>
class DenseDataView
: public TinyContainer< T*, DenseDataView<T, Nrows, Ncols, S1, S2> > {
public:
typedef T T_Return;
typedef DenseDataView<T, Nrows, Ncols, S1, S2> T_Expr;
T_Expr makeExpr() const { return *this; }
T *beginLoc(unsigned i, unsigned j) const
{ return m_data + S1 * i + S2 * j; }
DenseDataView(T *pData)
: TinyContainer< T*, DenseDataView<T, Nrows, Ncols, S1, S2> >(pData) { }
T &offset(unsigned i, unsigned j)
{
return m_data[S1 * i + S2 * j];
}
T offset(unsigned i, unsigned j) const
{
return m_data[S1 * i + S2 * j];
}
template<unsigned I, unsigned J>
struct Offset {
static T &apply(DenseDataView<T, Nrows, Ncols, S1, S2> &d)
{
return d.m_data[S1 * I + S2 * J];
}
static T constApply(const DenseDataView<T, Nrows, Ncols, S1, S2> &d)
{
return d.m_data[S1 * I + S2 * J];
}
};
};
template<unsigned I, unsigned J>
struct Eval2 { };
template<class T, unsigned Nrows, unsigned Ncols, unsigned S1, unsigned S2,
unsigned I, unsigned J>
inline T
for_each(const DenseDataView<T, Nrows, Ncols, S1, S2> &d,
const Eval2<I,J> &e)
{
return d.offset(I, J);
}
template<class T, unsigned Nrows, unsigned Ncols>
class DenseData
: public TinyContainer< T[Nrows * Ncols], DenseData<T, Nrows, Ncols> > {
public:
typedef T T_Return;
typedef DenseDataView<T, Nrows, Ncols, 1, Nrows> T_Expr;
T_Expr makeExpr() const { return T_Expr(m_data); }
T *beginLoc(unsigned i, unsigned j) const
{ return &m_data[i + Nrows * j]; }
T &operator[](unsigned i)
{
return m_data[i];
}
T operator[](unsigned i) const
{
return m_data[i];
}
T &offset(unsigned i, unsigned j)
{
return m_data[i + Nrows * j];
}
T offset(unsigned i, unsigned j) const
{
return m_data[i + Nrows * j];
}
template<unsigned I, unsigned J>
struct Offset {
static T &apply(DenseData<T, Nrows, Ncols> &d)
{
return d.m_data[I + Nrows * J];
}
static T constApply(const DenseData<T, Nrows, Ncols> &d)
{
return d.m_data[I + Nrows * J];
}
};
};
template<class T, unsigned Nrc>
class DiagonalData {
public:
T &offset(unsigned i, unsigned j)
{
assert(i == j);
return m_data[i];
}
T offset(unsigned i, unsigned j) const
{
return (i == j) ? m_data[i] : T(0);
}
template<unsigned I, unsigned J>
struct Offset {
static T &apply(DiagonalData<T,Nrc> &d)
{
assert(I == J);
return d.m_data[I];
}
static T constApply(const DiagonalData<T,Nrc> &d)
{
return (I == J) ? d.m_data[I] : T(0);
}
};
private:
T m_data[Nrc];
};
template<unsigned I, unsigned J, unsigned C1>
struct InnerLoop {
template<class LHS, class RHS>
static inline void eval(LHS &l, const RHS &r)
{
l.offset(I,J) = for_each(r, Eval2<I,J>());
InnerLoop<I + 1, J, C1 - 1>::eval(l, r);
}
};
template<unsigned I, unsigned J>
struct InnerLoop<I, J, 0> {
template<class LHS, class RHS>
static inline void eval(LHS &, const RHS &) { }
};
template<unsigned I, unsigned J, unsigned C1, unsigned C2>
struct Loop2 {
template<class LHS, class RHS>
static inline void eval(LHS &l, const RHS &r)
{
InnerLoop<I, J, C1>::eval(l, r);
Loop2<I, J + 1, C1, C2 - 1>::eval(l, r);
}
};
template<unsigned I, unsigned J, unsigned C1>
struct Loop2<I, J, C1, 0> {
template<class LHS, class RHS>
static inline void eval(LHS &l, const RHS &r) { }
};
template<unsigned Begin, unsigned End, unsigned Stride = 1>
class TinyRange {
public:
static const unsigned b = Begin;
static const unsigned e = End;
static const unsigned s = Stride;
static const unsigned n = (End - Begin) / Stride + 1;
static unsigned index(unsigned i)
{
return b + s * i;
}
};
template<class Range1, class Range2, class Data>
struct Merge { };
template<class Range1, class Range2, class T, unsigned Nrows, unsigned Ncols>
struct Merge<Range1, Range2, DenseData<T, Nrows, Ncols> >
{
static const unsigned s2 = Nrows * Range2::s;
typedef
DenseDataView<T, Range1::n, Range2::n, Range1::s, s2> type;
};
template<class Range1, class Range2, class T, unsigned Nrows, unsigned Ncols,
unsigned S1, unsigned S2>
struct Merge<Range1, Range2, DenseDataView<T, Nrows, Ncols, S1, S2> >
{
static const unsigned s1 = S1 * Range1::s;
static const unsigned s2 = S2 * Range2::s;
typedef
DenseDataView<T, Range1::n, Range2::n, s1, s2> type;
};
template<class T, unsigned Nrows, unsigned Ncols,
class Data = DenseData<T, Nrows, Ncols> >
class TinyMatrix :
public TinyContainer< Data, TinyMatrix<T, Nrows, Ncols, Data> > {
public:
typedef T T_Return;
typedef typename Data::T_Expr T_Expr;
typedef TinyContainer< Data, TinyMatrix<T, Nrows, Ncols, Data> > T_Base;
T_Expr makeExpr() const { return m_data.makeExpr(); }
TinyMatrix() { }
TinyMatrix(const T &a0, const T &a1, const T &a2,
const T &a3, const T &a4, const T &a5)
{
m_data[0] = a0; m_data[1] = a1; m_data[2] = a2;
m_data[3] = a3; m_data[4] = a4; m_data[5] = a5;
}
TinyMatrix(const T &a0, const T &a1)
{
m_data[0] = a0; m_data[1] = a1;
}
TinyMatrix(const Data &d) : T_Base(d) { }
T operator()(unsigned i, unsigned j) const
{
return m_data.offset(i, j);
}
template<unsigned B1, unsigned E1, unsigned S1,
unsigned B2, unsigned E2, unsigned S2>
TinyMatrix<T, TinyRange<B1, E1, S1>::n,
TinyRange<B2, E2, S2>::n,
typename
Merge< TinyRange<B1, E1, S1>, TinyRange<B2, E2, S2>, Data>::type>
operator()(const TinyRange<B1, E1, S1> &r1, const TinyRange<B2, E2, S2> &r2)
{
typedef typename
Merge< TinyRange<B1, E1, S1>, TinyRange<B2, E2, S2>, Data>::type
T_DataType;
typedef TinyMatrix<T, TinyRange<B1, E1, S1>::n,
TinyRange<B2, E2, S2>::n, T_DataType> T_RetType;
return T_RetType(T_DataType(m_data.beginLoc(B1, B2)));
}
template<class V1, class T1>
void operator=(const TinyContainer<V1, T1> &rhs)
{
Loop2<0, 0, Nrows, Ncols>::eval(m_data, rhs.unwrap().makeExpr());
}
};
int main()
{
TinyMatrix<double, 2, 3> a, b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6), d(0.01, 0.02, 0.03, 0.04, 0.05, 0.06);
TinyMatrix<double, 1, 2> e, f(17.0, 48.3);
a = b + c + d;
a(TinyRange<0,1>(), TinyRange<0,2,2>());
a(TinyRange<0,1>(), TinyRange<0,2,2>())
(TinyRange<0,0>(), TinyRange<0,1>());
e = f + a(TinyRange<0,1>(), TinyRange<0,2,2>())
(TinyRange<0,0>(), TinyRange<0,1>());
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment