1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  array.cpp --
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2002-02-15
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36 *****************************************************************************/
37
38// array.cxx --
39// Copyright Synopsys 1998
40// Author          : Ric Hilderink
41// Created On      : Wed Dec 30 11:55:50 1998
42// Status          : none
43//
44
45#include <limits.h>
46#define SC_INCLUDE_FX
47#include "systemc.h"
48#include "fx_precision_double.h"
49
50// Without this, conversions use the implicit
51// operator double, which is both lossy and
52// can cause UB in certain cases.
53template <typename From>
54class converter {
55  From val;
56public:
57  converter(From val): val(val) {}
58  operator int() const            { return val.to_int();    }
59  operator unsigned int() const   { return val.to_uint();   }
60  operator short() const          { return val.to_short();  }
61  operator unsigned short() const { return val.to_ushort(); }
62  operator long() const           { return val.to_long();   }
63  operator unsigned long() const  { return val.to_ulong();  }
64  operator float() const          { return val.to_float();  }
65  operator double() const         { return val.to_double(); }
66};
67
68template <typename To, typename From>
69To convert(From val) {
70  return converter<From>(val);
71}
72
73
74template <typename T>
75void show(char const *const name, int i, T val) {
76  cerr << name << "[" << i << "] : " << val.to_double() << " : " << val.to_string(SC_HEX) << "\n";
77}
78
79template <typename T, typename U>
80void test_fx(U a_mul, U b_init, U b_mul, char const *t_name, char const *u_name)
81{
82  cerr << "--array-Inf-Inf-Inf-Inf-Inf- test_fx_" << t_name << "_" << u_name << "\n";
83
84  T a(static_cast<U>(0));
85  T b(b_init);
86  show("a", 0, a);
87  show("b", 0, b);
88
89  for (U i = 1; i < 4; ++i) {
90    // Be careful here. We don't want a T to ever be implicitly converted,
91    // else we have a double which cannot be safely cast, but converting early
92    // means we can be subject to implicit upcasts. That's minimized by having all
93    // of the values of type U, but if U is smaller than int it can still be
94    // implicitly upcast, ergo the outer cast.
95    a = static_cast<U>(i * i * a_mul);
96    b = static_cast<U>(convert<U>(b) * i * b_mul);
97    show("a", i, a);
98    show("b", i, b);
99  }
100}
101
102template <typename T>
103void batch_test_fx(char const *t_name, int uinit) {
104  cerr << "************** array test_fx_" << t_name << "_\n";
105  test_fx<T, int           >(1,     -1, -1, t_name, "int");
106  test_fx<T, unsigned int  >(1,  uinit, -1, t_name, "uint");
107  test_fx<T, short         >(1,     -1, -1, t_name, "short");
108  test_fx<T, unsigned short>(1,  uinit, -1, t_name, "ushort");
109  test_fx<T, long          >(1,     -1, -1, t_name, "long");
110  test_fx<T, unsigned long >(1,  uinit, -1, t_name, "ulong");
111  test_fx<T, float >(1.123456789f, -1.987654321f, -1.789654123f, t_name, "float");
112  test_fx<T, double>(1.123456789,  -1.987654321,  -1.789654123,  t_name, "double");
113}
114
115void array() {
116  batch_test_fx<sc_fxval>("float", -1);
117  batch_test_fx<sc_ufix>("ufix", -1);
118  batch_test_fx<sc_fix>("fix", -1);
119  batch_test_fx<sc_fixed<8, 5> >("fixed", 1);
120  batch_test_fx<sc_ufixed<8, 5> >("ufixed", 1);
121}
122