AERA
code_utils.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2023 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2023 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2023 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #include "../submodules/CoreLibrary/CoreLibrary/utils.h"
86 #include "object.h"
87 
88 #include <math.h>
89 
90 using namespace std;
91 using namespace std::chrono;
92 
93 namespace r_code {
94 
95 Timestamp Utils::TimeReference = Timestamp(microseconds(0));
96 microseconds Utils::BasePeriod = microseconds(0);
97 float32 Utils::FloatTolerance = 0;
98 microseconds Utils::TimeTolerance = microseconds(0);
99 
100 Timestamp Utils::GetTimeReference() { return TimeReference; }
101 microseconds Utils::GetBasePeriod() { return BasePeriod; }
102 uint32 Utils::GetFloatTolerance() { return FloatTolerance; }
103 microseconds Utils::GetTimeTolerance() { return TimeTolerance; }
104 
105 void Utils::SetReferenceValues(microseconds base_period, float32 float_tolerance, microseconds time_tolerance) {
106 
107  BasePeriod = base_period;
108  FloatTolerance = float_tolerance;
109  TimeTolerance = time_tolerance;
110 }
111 
112 void Utils::SetTimeReference(Timestamp time_reference) {
113 
114  TimeReference = time_reference;
115 }
116 
117 bool Utils::Equal(float32 l, float32 r) {
118 
119  if (l == r)
120  return true;
121  return fabs(l - r) < FloatTolerance;
122 }
123 
124 bool Utils::Synchronous(Timestamp l, Timestamp r) {
125 
126  return abs(l - r) < TimeTolerance;
127 }
128 
129 Timestamp Utils::GetTimestamp(const Atom *iptr) {
130 
131  return Timestamp(microseconds(GetInt64(iptr, 1)));
132 }
133 
134 void Utils::SetTimestamp(Atom *iptr, Timestamp timestamp) {
135 
136  iptr[0] = Atom::Timestamp();
137  SetInt64(iptr, 1, duration_cast<microseconds>(timestamp.time_since_epoch()).count());
138 }
139 
140 void Utils::SetTimestampStruct(Code *object, uint16 index, Timestamp timestamp) {
141 
142  object->code(index) = Atom::Timestamp();
143  // This will resize the code array if needed.
144  object->code(index + 2) = 0;
145  SetInt64(&object->code(0), index + 1, duration_cast<microseconds>(timestamp.time_since_epoch()).count());
146 }
147 
148 string Utils::ToString_s_ms_us(Timestamp timestamp, Timestamp time_reference) {
149  auto duration = timestamp - time_reference;
150  uint64 t = abs(duration_cast<microseconds>(duration).count());
151 
152  uint64 us = t % 1000;
153  uint64 ms = t / 1000;
154  uint64 s = ms / 1000;
155  ms = ms % 1000;
156 
157  std::string result = (duration < microseconds(0) ? "-" : "");
158  result += std::to_string(s);
159  result += "s:";
160  result += std::to_string(ms);
161  result += "ms:";
162  result += std::to_string(us);
163  result += "us";
164 
165  return result;
166 }
167 
168 void Utils::SetDurationStruct(Code *object, uint16 index, microseconds duration) {
169  object->resize_code(index + 3);
170  object->code(index) = Atom::Duration();
171  SetInt64(&object->code(0), index + 1, duration.count());
172 }
173 
174 string Utils::ToString_us(microseconds duration) {
175  uint64 us = abs(duration_cast<microseconds>(duration).count());
176 
177  std::string sign = (duration < microseconds(0) ? "-" : "");
178  if (us % 1000 != 0)
179  return sign + std::to_string(us) + "us";
180  else {
181  uint64 ms = us / 1000;
182  if (ms % 1000 != 0)
183  return sign + std::to_string(ms) + "ms";
184  else {
185  uint64 s = ms / 1000;
186  return sign + std::to_string(s) + "s";
187  }
188  }
189 }
190 
191 std::string Utils::GetString(const Atom *iptr) {
192 
193  std::string s;
194  char buffer[255];
195  uint8 char_count = (iptr[0].atom_ & 0x000000FF);
196  memcpy(buffer, iptr + 1, char_count);
197  buffer[char_count] = 0;
198  s += buffer;
199  return s;
200 }
201 
202 void Utils::SetString(Atom *iptr, const std::string &s) {
203 
204  uint8 l = (uint8)s.length();
205  uint8 index = 0;
206  iptr[index] = Atom::String(l);
207  uint32 st = 0;
208  int8 shift = 0;
209  for (uint8 i = 0; i < l; ++i) {
210 
211  st |= s[i] << shift;
212  shift += 8;
213  if (shift == 32) {
214 
215  iptr[++index] = st;
216  st = 0;
217  shift = 0;
218  }
219  }
220  if (l % 4)
221  iptr[++index] = st;
222 }
223 
224 int32 Utils::GetResilience(Timestamp now, microseconds time_to_live, uint64 upr) {
225 
226  if (time_to_live.count() == 0 || upr == 0)
227  return 1;
228  auto deadline = now + time_to_live;
229  uint64 last_upr = duration_cast<microseconds>(now - TimeReference).count() / upr;
230  uint64 next_upr = duration_cast<microseconds>(deadline - TimeReference).count() / upr;
231  if (duration_cast<microseconds>(deadline - TimeReference).count() % upr > 0)
232  ++next_upr;
233  return next_upr - last_upr;
234 }
235 
236 int32 Utils::GetResilience(float32 resilience, float32 origin_upr, float32 destination_upr) {
237 
238  if (origin_upr == 0)
239  return 1;
240  if (destination_upr <= origin_upr)
241  return 1;
242  float32 r = origin_upr / destination_upr;
243  float32 res = resilience * r;
244  if (res < 1)
245  return 1;
246  return res;
247 }
248 
249 std::string Utils::RelativeTime(Timestamp t) {
250 
251  return ToString_s_ms_us(t, TimeReference);
252 }
253 
254 bool Utils::has_reference(const Atom* code, uint16 index) {
255  Atom atom = code[index];
256 
257  switch (atom.getDescriptor()) {
258  case Atom::R_PTR:
259  return true;
260  case Atom::I_PTR:
261  return has_reference(code, atom.asIndex());
262  case Atom::C_PTR:
263  case Atom::SET:
264  case Atom::OBJECT:
265  case Atom::S_SET:
266  case Atom::MARKER:
267  case Atom::OPERATOR:
268  case Atom::TIMESTAMP:
269  case Atom::DURATION:
270  case Atom::GROUP: {
271  uint16 count = atom.getAtomCount();
272  for (uint16 i = 1; i <= count; ++i) {
273  if (has_reference(code, index + i))
274  return true;
275  }
276  return false;
277  }
278  default:
279  return false;
280  }
281 }
282 
283 }
r_code::Atom
Definition: atom.h:104
r_code::Code
Definition: r_code/object.h:224