#include "010.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gtypes.h"
#define DM_COM_MOD_NONE ((GInt64)0x7FFFFFFFFFFFFFFF)
enum {
_M_, // メートル法
_Y_, // ヤードポンド法
};
typedef struct CalcValue {
GInt64 uwValue; // 値
GInt64 uwValueMult; // 値に対する縮率
} CalcValue;
/// @brief 表示値計算用テーブル
/// @param RawValue 入力値
/// @param stResolution 分解脳
/// @param dOffset オフセット
/// @param stCoefficient 単位変換係数
/// @param dCoefficientOffset 単位変換係数オフセット
/// @param dMod MOD
/// @param ubDigitMetricInt メートル法 整数桁
/// @param ubDigitMetricDec メートル法 小数桁
/// @param stMinMetric メートル法 最小値
/// @param stMaxMetric メートル法 最大値
/// @param ubDigitYardInt ヤードポンド法 整数桁0
/// @param ubDigitYardDec ヤードポンド法 小数桁
/// @param stMinYard ヤードポンド法 最小値
/// @param stMaxYard ヤードポンド法 最大値
typedef struct test {
GInt64 RawValue; // 入力値
CalcValue stResolution; // 分解脳
GInt64 dOffset; // オフセット
CalcValue stCoefficient; // 単位変換係数
GInt64 dCoefficientOffset; // 単位変換係数オフセット
GInt64 dMod; // MOD
GInt32 ubDigitMetricInt; // メートル法 整数桁
GInt32 ubDigitMetricDec; // メートル法 小数桁
CalcValue stMinMetric; // メートル法 最小値
CalcValue stMaxMetric; // メートル法 最大値
GInt32 ubDigitYardInt; // ヤードポンド法 整数桁
GInt32 ubDigitYardDec; // ヤードポンド法 小数桁
CalcValue stMinYard; // ヤードポンド法 最小値
CalcValue stMaxYard; // ヤードポンド法 最大値
} test;
char* getMode(int type);
static const test pTableList[] = {
{0x127B4, {5, 10}, 0, {2642, 10000}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 4, 2, {0, 100}, {999999, 100}},
{0x126FE, {50, 100}, -3050, {2642, 10000}, 3200, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 4, 2, {0, 100}, {999999, 100}},
{0x00, {1, 1}, -40, {18, 10}, 32, DM_COM_MOD_NONE, 3, 0, {-40, 1}, {210, 1}, 3, 0, {-40, 1}, {410, 1}},
{0xFA, {1, 1}, -40, {18, 10}, 32, DM_COM_MOD_NONE, 3, 0, {-40, 1}, {210, 1}, 3, 0, {-40, 1}, {410, 1}},
{0x01, {5, 10}, -305, {18, 10}, 320, DM_COM_MOD_NONE, 2, 1, {-300, 10}, {500, 10}, 2, 1, {-220, 10}, {1220, 10}},
{0xA1, {5, 10}, -305, {18, 10}, 320, DM_COM_MOD_NONE, 2, 1, {-300, 10}, {500, 10}, 2, 1, {-220, 10}, {1220, 10}},
{35, {50, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
{-35, {5, 10}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {-999999, 10}, {999999, 10}, 5, 1, {-999999, 10}, {999999, 10}},
// {0x00000000, {1, 1000}, 500, {1, 1}, 0, DM_COM_MOD_NONE, 2, 3, {500, 1000}, {99999, 1000}, 2, 3, {500, 1000}, {99999, 1000}},
// {0x000184AB, {1, 1000}, 500, {1, 1}, 0, DM_COM_MOD_NONE, 2, 3, {500, 1000}, {99999, 1000}, 2, 3, {500, 1000}, {99999, 1000}},
{0x3780, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
{0x9080, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
{0x9059, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
{0x9059, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
// {0xFF, {5, 10}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
// {0xFF, {50, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
// {0xFF, {5, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
};
static const GInt64 pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
GInt32 type = _Y_;
GInt64 g_ValueScaled[sizeof(pTableList) / sizeof(pTableList[0])];
int main(void) {
// type = _M_;
// 生値→表示値変換
printf("-------------- %s --------------\n", getMode(type));
GUInt32 i;
for (i = 0; i < sizeof(pTableList) / sizeof(pTableList[0]); i++) {
const test* pTbl = &pTableList[i];
GInt32 uwDispInt; /* 表示用の整数部 */
GInt32 uwDispDec; /* 表示用の小数部 */
GInt8 ubdispInt; /* 表示整数桁数 */
GInt8 ubdispDec; /* 表示小数桁数 */
GInt64 dMinValue; /* 表示可能最小値(内部スケール変換後) */
GInt64 dMaxValue; /* 表示可能最大値(内部スケール変換後) */
GInt64 calcValue; /* 計算結果(内部スケール値) */
GInt64 decScale; /* 内部スケール倍率 */
GInt64 powValue; /* 小数部抽出用の倍率(10,100,1000...) */
if (type == _Y_) {
/* 表示桁数設定 */
ubdispInt = pTbl->ubDigitYardInt;
ubdispDec = pTbl->ubDigitYardDec;
} else {
/* 表示桁数設定 */
ubdispInt = pTbl->ubDigitMetricInt;
ubdispDec = pTbl->ubDigitMetricDec;
}
/* 出力: No.番号 */
printf("No.%03u => ", i + 1);
/* 表示小数桁数に対応する10の累乗値を取得 */
powValue = pow10[ubdispDec];
if (type == _Y_) {
/* ヤードポンド法の内部スケール値を設定 */
decScale = pTbl->stResolution.uwValueMult * pTbl->stCoefficient.uwValueMult / powValue;
/* ((RawValue × 分解能) + stOffset) × 単位変換係数 + 単位変換係数オフセット を計算 */
calcValue = ((pTbl->RawValue * pTbl->stResolution.uwValue) + pTbl->dOffset) * pTbl->stCoefficient.uwValue + (pTbl->dCoefficientOffset * pTbl->stCoefficient.uwValueMult);
printf("%10ld = ((%6ld * %ld) + %ld) * %ld + (%ld * %ld) ", calcValue, pTbl->RawValue, pTbl->stResolution.uwValue, pTbl->dOffset, pTbl->stCoefficient.uwValue, pTbl->dCoefficientOffset, pTbl->stCoefficient.uwValueMult);
/* 最大値・最小値を内部スケール値へ変換 */
dMinValue = pTbl->stMinYard.uwValue * decScale;
dMaxValue = pTbl->stMaxYard.uwValue * decScale;
// dMinValue = pTbl->stMinYard.uwValue;
// dMaxValue = pTbl->stMaxYard.uwValue;
} else {
/* メートル法の内部スケール値を設定 */
decScale = pTbl->stResolution.uwValueMult / powValue;
/* (RawValue × 分解能) + stOffset を内部スケールで計算 */
calcValue = (pTbl->RawValue * pTbl->stResolution.uwValue) + pTbl->dOffset;
printf("%10ld = (%6ld * %ld) + (%ld)) ", calcValue, pTbl->RawValue, pTbl->stResolution.uwValue, pTbl->dOffset);
/* 最大値・最小値を内部スケール値へ変換 */
dMinValue = pTbl->stMinMetric.uwValue * decScale;
dMaxValue = pTbl->stMaxMetric.uwValue * decScale;
// dMinValue = pTbl->stMinMetric.uwValue;
// dMaxValue = pTbl->stMaxMetric.uwValue;
}
if (decScale <= 0) {
return 0;
}
/* 不要な桁切り捨て */
// calcValue = (calcValue / decScale) * decScale;
calcValue = calcValue / decScale;
/* 表示値に対するMOD値を内部スケールへ変換 */
if (pTbl->dMod != DM_COM_MOD_NONE) {
// calcValue = calcValue % (pTbl->dMod * (decScale * powValue));
calcValue = calcValue % pTbl->dMod;
}
/* 下限丸め込み */
if (calcValue < dMinValue) {
calcValue = dMinValue;
}
/* 上限丸め込み */
if (calcValue > dMaxValue) {
calcValue = dMaxValue;
}
/* 整数部を取得 */
// uwDispInt = (GInt32)(calcValue / (decScale * powValue));
uwDispInt = (GInt32)(calcValue / powValue);
/* 小数部を取り出して表示桁数へ変換 */
// uwDispDec = llabs((GInt32)(calcValue % (decScale * powValue) / decScale));
uwDispDec = llabs((GInt32)(calcValue % powValue));
/* 出力: 表示用値 */
printf("Ret = %ld, ", calcValue);
printf(" << 表示値 = %d.%0*d >> ", uwDispInt, ubdispDec, uwDispDec);
printf("Scale = %ld, ", decScale);
printf("powValue = %ld, ", powValue);
printf("MIN = %ld, ", dMinValue);
printf("MAX = %ld, ", dMaxValue);
// printf("\n ");
printf("Int = %d, ", ubdispInt);
printf("Dec = %d, ", ubdispDec);
printf("\n");
/* 表示値→生値変換で使用するため保存 */
g_ValueScaled[i] = calcValue;
}
// 表示値→生値変換
printf("-----------------------------\n");
for (i = 0; i < sizeof(pTableList) / sizeof(pTableList[0]); i++) {
const test* pTbl = &pTableList[i]; /* 対象テーブル */
GInt64 displayValueScaled; /* 表示値(内部スケール値) */
GInt64 rawValue; /* 算出した生値 */
GInt64 decScale; /* 内部スケール倍率 */
GInt64 powValue; /* 小数部抽出用の倍率(10,100,1000...) */
GInt8 ubdispDec; /* 表示小数桁数 */
/* 生値→表示値変換で算出した表示値を取得 */
displayValueScaled = g_ValueScaled[i];
printf("No.%03u => ", i + 1);
printf("表示値(整数スケール)= %6lld, ", (long long)displayValueScaled);
if (type == _Y_) {
/* 表示桁数設定 */
ubdispDec = pTbl->ubDigitYardDec;
} else {
/* 表示桁数設定 */
ubdispDec = pTbl->ubDigitMetricDec;
}
/* 表示小数桁数に対応する10の累乗値を取得 */
powValue = pow10[ubdispDec];
if (type == _Y_) {
/* ヤードポンド法の内部スケール値を設定 */
decScale = pTbl->stResolution.uwValueMult * pTbl->stCoefficient.uwValueMult / powValue;
displayValueScaled *= decScale;
/* 保存した表示値(内部スケール値)を使用 */
rawValue = (((displayValueScaled - (pTbl->dCoefficientOffset * pTbl->stCoefficient.uwValueMult)) / pTbl->stCoefficient.uwValue) - pTbl->dOffset) / pTbl->stResolution.uwValue;
} else {
/* メートル法の内部スケール値を設定 */
decScale = pTbl->stResolution.uwValueMult / powValue;
displayValueScaled *= decScale;
/* 保存した表示値(内部スケール値)を使用 */
rawValue = (displayValueScaled - pTbl->dOffset) / pTbl->stResolution.uwValue;
}
printf("変換後 = %6lld /=/ %6lld = 元データ, ", (long long)rawValue, (long long)pTbl->RawValue);
printf("powValue = %2ld, ", powValue);
printf("decScale = %ld, \n", decScale);
}
return 0;
}
char* getMode(int type) {
switch (type) {
case _M_:
return "メートル法";
break;
case _Y_:
return "ヤード・ポンド法";
break;
default:
break;
}
return "UNKNOWN";
}