blob: 545b38dcede61445f6f44b4be1015c56385bb33f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 - 2019 Profactor GmbH, ACIN, nxtControl GmbH, fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Thomas Strasser, Ingomar Müller, Alois Zoitl,
* Ingo Hegny, Martin Melik Merkumians, Monika Wenger, Stanislav Meduna,
* Matthias Plasch
* - initial implementation and rework communication infrastructure
* Jose Cabral
* - Move arch dependant code (strtod) to the arch folder
*******************************************************************************/
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "forte_real.h"
#include "forte_lreal.h"
#include <forte_printer.h>
#include "../../arch/forte_realFunctions.h"
DEFINE_FIRMWARE_DATATYPE(REAL, g_nStringIdREAL)
int CIEC_REAL::fromString(const char *paValue){
char *pcEnd;
const char *pacRunner = paValue;
TForteFloat realval = 0.0;
const TForteFloat TFLOAT_min = 3.4e-38F; // lower precision boundary
const TForteFloat TFLOAT_max = 3.4e38F; // upper precision boundary
if(0 == strncmp(pacRunner, "REAL#", 5)){
pacRunner += 5;
}
realval = forte_stringToFloat(pacRunner, &pcEnd);
if(((fabs(realval) < TFLOAT_min) && (realval != 0)) || ((fabs(realval) > TFLOAT_max) && (realval != 0)) ||
(pacRunner == pcEnd)) {
return -1;
}
setTFLOAT((TForteFloat) realval);
return static_cast<int>(pcEnd - paValue);
}
int CIEC_REAL::toString(char* paValue, size_t paBufferSize) const {
int nRetVal;
nRetVal = forte_snprintf(paValue, paBufferSize, "%g", getTFLOAT());
if((nRetVal < -1) || (nRetVal >= static_cast<int>(paBufferSize))) {
nRetVal = -1;
}
return nRetVal;
}
void CIEC_REAL::setValue(const CIEC_ANY& paValue){
EDataTypeID eID = paValue.getDataTypeID();
switch (eID) {
case e_REAL:
setValueSimple(paValue);
break;
#ifdef FORTE_USE_LREAL_DATATYPE
case e_LREAL:
(*this)=static_cast<TForteFloat>((CIEC_LREAL&)(paValue));
break;
#endif
case e_STRING:
(*this).fromString(((CIEC_STRING&)paValue).getValue());
break;
case e_WSTRING:
(*this).fromString(((CIEC_WSTRING&)paValue).getValue());
break;
case e_SINT:
case e_INT:
case e_DINT:
case e_LINT:
(*this) = static_cast<TForteFloat>(*((CIEC_ANY::TLargestIntValueType *) paValue.getConstDataPtr()));
break;
default:
(*this) = static_cast<TForteFloat>(*((CIEC_ANY::TLargestUIntValueType *) paValue.getConstDataPtr()));
break;
}
}
void CIEC_REAL::castRealData(const CIEC_REAL &paSrcValue, CIEC_ANY &paDestValue){
switch(paDestValue.getDataTypeID()){
case CIEC_ANY::e_REAL:
static_cast<CIEC_REAL &>(paDestValue) = paSrcValue;
break;
case CIEC_ANY::e_LREAL:
#ifdef FORTE_USE_LREAL_DATATYPE
static_cast<CIEC_LREAL &>(paDestValue) = paSrcValue;
#endif
break;
case CIEC_ANY::e_BYTE:
case CIEC_ANY::e_WORD:
case CIEC_ANY::e_DWORD:
case CIEC_ANY::e_LWORD:
// bit string will cast to the binary representation of the real value
paDestValue.setValue(paSrcValue);
break;
case CIEC_ANY::e_BOOL: //bool works better when treated as signed so that negative numbers will be treated as true to
case CIEC_ANY::e_SINT:
case CIEC_ANY::e_INT:
case CIEC_ANY::e_DINT:
case CIEC_ANY::e_LINT: {
CIEC_REAL::TValueType floatValue = static_cast<CIEC_REAL::TValueType>(paSrcValue);
if(0 < floatValue){
floatValue += 0.5F;
}
if(0 > floatValue){
floatValue -= 0.5F;
}
*((CIEC_ANY::TLargestIntValueType *) paDestValue.getDataPtr()) = static_cast<CIEC_ANY::TLargestIntValueType>(floatValue);
}
break;
default: {
//TODO maybe we should check for destination id to be in valid range (i.e., any_bit, any_unsigned_int, and time)
//should not be necessary because of connect function, but who knows.
CIEC_REAL::TValueType floatValue = static_cast<CIEC_REAL::TValueType>(paSrcValue);
if(0 < floatValue){
floatValue += 0.5F;
}
if(0 > floatValue){
floatValue -= 0.5F;
}
*(reinterpret_cast<CIEC_ANY::TLargestUIntValueType*>(paDestValue.getDataPtr())) = static_cast<CIEC_ANY::TLargestUIntValueType>(floatValue);
}
break;
}
}