mirror of
https://github.com/openharmony/js_util_module.git
synced 2026-07-21 06:05:21 -04:00
0913075b24
Signed-off-by: lifansheng <lifansheng1@huawei.com>
338 lines
12 KiB
C++
Executable File
338 lines
12 KiB
C++
Executable File
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "js_rational.h"
|
|
#include <climits>
|
|
#include <string>
|
|
#include <cctype>
|
|
#include "utils/log.h"
|
|
#include "securec.h"
|
|
namespace OHOS::Util {
|
|
RationalNumber::RationalNumber(napi_env env, int num, int den)
|
|
{
|
|
env_ = env;
|
|
napi_value result = nullptr;
|
|
den < 0 ? num *= -1, den *= -1 : 0;
|
|
if (den == 0) {
|
|
if (num > 0) {
|
|
mnum = 1;
|
|
mden = 0;
|
|
} else if (num < 0) {
|
|
mnum = -1;
|
|
mden = 0;
|
|
} else {
|
|
mnum = 0;
|
|
mden = 0;
|
|
}
|
|
} else if (num == 0) {
|
|
mnum = 0;
|
|
mden = 1;
|
|
} else {
|
|
napi_value num1 = nullptr;
|
|
napi_value num2 = nullptr;
|
|
napi_create_int32(env_, num, &num1);
|
|
napi_create_int32(env_, den, &num2);
|
|
result = GetCommonDivisor(num1, num2);
|
|
int gnum = 0;
|
|
napi_get_value_int32(env_, result, &gnum);
|
|
if (gnum != 0) {
|
|
mnum = num / gnum;
|
|
mden = den / gnum;
|
|
}
|
|
}
|
|
}
|
|
|
|
napi_value RationalNumber::CreatRationalFromString(napi_value str, napi_value RationalNumberClass) const
|
|
{
|
|
size_t len = 0;
|
|
int flag = 0;
|
|
napi_get_value_string_utf8(env_, str, nullptr, 0, &len);
|
|
char* buffer = nullptr;
|
|
if (len > 0) {
|
|
buffer = new char[len + 1];
|
|
if (memset_s(buffer, len + 1, '\0', len + 1) != 0) {
|
|
napi_throw_error(env_, "-1", "memset_s failed");
|
|
}
|
|
} else {
|
|
napi_throw_error(env_, "NullPointerException", "string must not be null!");
|
|
}
|
|
napi_get_value_string_utf8(env_, str, buffer, len + 1, &len);
|
|
std::string buf = buffer;
|
|
delete []buffer;
|
|
if (buf.compare("NaN") == 0) {
|
|
return GreateObj(0, 0, RationalNumberClass);
|
|
} else if (buf.compare("Infinity") == 0) {
|
|
return GreateObj(1, 0, RationalNumberClass);
|
|
} else if (buf.compare("-Infinity") == 0) {
|
|
return GreateObj(-1, 0, RationalNumberClass);
|
|
}
|
|
size_t colon = buf.find(':');
|
|
size_t semicolon = buf.find('/');
|
|
if ((colon == std::string::npos && semicolon == std::string::npos)
|
|
|| (colon != std::string::npos && semicolon != std::string::npos)) {
|
|
napi_throw_error(env_, "invalidRational", "string invalid!");
|
|
}
|
|
size_t index = (colon != std::string::npos) ? colon : semicolon;
|
|
std::string s1 = buf.substr(0, index);
|
|
std::string s2 = buf.substr(index + 1, buf.size());
|
|
size_t len1 = s1.size();
|
|
size_t len2 = s2.size();
|
|
for (int i = 1; i < len1; i++) {
|
|
if (((s1[0] == '+') || (s1[0] == '-') || (isdigit(s1[0]))) && (isdigit(s1[i]))) {
|
|
flag = 1;
|
|
} else {
|
|
napi_throw_error(env_, "invalidRational", "string invalid!");
|
|
}
|
|
}
|
|
int num1 = stoi(s1) * flag;
|
|
for (int i = 1; i < len2; i++) {
|
|
if (((s2[0] == '+') || (s2[0] == '-') || (isdigit(s2[0]))) && (isdigit(s2[i]))) {
|
|
flag = 1;
|
|
} else {
|
|
napi_throw_error(env_, "invalidRational", "string invalid!");
|
|
}
|
|
}
|
|
int num2 = stoi(s2) * flag;
|
|
return GreateObj(num1, num2, RationalNumberClass);
|
|
}
|
|
|
|
napi_value RationalNumber::GreateObj(int num1, int num2, napi_value RationalNumberClass) const
|
|
{
|
|
napi_value argvs[2] = { nullptr };
|
|
NAPI_CALL(env_, napi_create_int32(env_, num1, &argvs[0]));
|
|
NAPI_CALL(env_, napi_create_int32(env_, num2, &argvs[1]));
|
|
size_t argc = 2;
|
|
napi_value res = nullptr;
|
|
NAPI_CALL(env_, napi_new_instance(env_, RationalNumberClass, argc, argvs, &res));
|
|
return res;
|
|
}
|
|
|
|
napi_value RationalNumber::CompareTo(napi_value rational) const
|
|
{
|
|
RationalNumber* other = nullptr;
|
|
NAPI_CALL(env_, napi_unwrap(env_, rational, reinterpret_cast<void**>(&other)));
|
|
if (mnum == other->mnum && mden == other->mden) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, 0, &result));
|
|
return result;
|
|
} else if (mnum == 0 && mden == 0) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, 1, &result));
|
|
return result;
|
|
} else if ((other->mnum == 0) && (other->mden == 0)) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, -1, &result));
|
|
return result;
|
|
} else if ((mden == 0 && mnum > 0) || (other->mden == 0 && other->mnum < 0)) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, 1, &result));
|
|
return result;
|
|
} else if ((mden == 0 && mnum < 0) || (other->mden == 0 && other->mnum > 0)) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, -1, &result));
|
|
return result;
|
|
}
|
|
long thisnum = static_cast<long>(mnum) * other->mden;
|
|
long othernum = static_cast<long>(other->mnum) * mden;
|
|
if (thisnum < othernum) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, -1, &result));
|
|
return result;
|
|
} else if (thisnum > othernum) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int64(env_, 1, &result));
|
|
return result;
|
|
} else {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, 0, &result));
|
|
return result;
|
|
}
|
|
}
|
|
|
|
napi_value RationalNumber::Equals(napi_value obj) const
|
|
{
|
|
RationalNumber* object = nullptr;
|
|
napi_status status = napi_unwrap(env_, obj, reinterpret_cast<void**>(&object));
|
|
bool flag = false;
|
|
long thisnum = static_cast<long>(mnum) * object->mden;
|
|
long objnum = static_cast<long>(object->mnum) * mden;
|
|
if (status != napi_ok) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
if (mnum == object->mnum && mden == object->mden) {
|
|
flag = true;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
} else if ((thisnum == objnum) && (mnum != 0 && mden != 0) && (object->mnum != 0 && object->mden != 0)) {
|
|
flag = true;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
} else if ((mnum == 0 && mden != 0) && (object->mnum == 0 && object->mden != 0)) {
|
|
flag = true;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
} else if ((mnum > 0 && mden == 0) && (object->mnum > 0 && object->mden == 0)) {
|
|
flag = true;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
} else if ((mnum < 0 && mden == 0) && (object->mnum < 0 && object->mden == 0)) {
|
|
flag = true;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
} else {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
}
|
|
|
|
napi_value RationalNumber::Value() const
|
|
{
|
|
if (mnum > 0 && mden == 0) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, INT_MAX, &result));
|
|
return result;
|
|
} else if (mnum < 0 && mden == 0) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, INT_MIN, &result));
|
|
return result;
|
|
} else if ((mnum == 0) && (mden == 0)) {
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, 0, &result));
|
|
return result;
|
|
} else {
|
|
if (mnum % mden == 0) {
|
|
int val = mnum / mden;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, val, &result));
|
|
return result;
|
|
} else {
|
|
double num = mnum;
|
|
double den = mden;
|
|
double res = num / den;
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_double(env_, res, &result));
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
napi_value RationalNumber::GetCommonDivisor(napi_value num1, napi_value num2) const
|
|
{
|
|
int temp = 0;
|
|
int number1 = 0;
|
|
int number2 = 0;
|
|
napi_get_value_int32(env_, num1, &number1);
|
|
napi_get_value_int32(env_, num2, &number2);
|
|
if (number1 == 0 || number2 == 0) {
|
|
napi_throw_error(env_, "invalidnumber", "Parameter cannot be zero!");
|
|
}
|
|
if (number1 < number2) {
|
|
temp = number1;
|
|
number1 = number2;
|
|
number2 = temp;
|
|
}
|
|
while (number1 % number2 != 0) {
|
|
temp = number1 % number2;
|
|
number1 = number2;
|
|
number2 = temp;
|
|
}
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, number2, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::GetDenominator() const
|
|
{
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, mden, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::GetNumerator() const
|
|
{
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_create_int32(env_, mnum, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::IsFinite() const
|
|
{
|
|
bool flag = false;
|
|
if (mden != 0) {
|
|
flag = true;
|
|
}
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::IsInfinite() const
|
|
{
|
|
bool flag = false;
|
|
if ((mnum != 0) && (mden == 0)) {
|
|
flag = true;
|
|
}
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::IsNaN() const
|
|
{
|
|
bool flag = false;
|
|
if ((mnum == 0) && (mden == 0)) {
|
|
flag = true;
|
|
}
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::IsZero() const
|
|
{
|
|
bool flag = false;
|
|
if ((mnum == 0) && (mden != 0)) {
|
|
flag = true;
|
|
}
|
|
napi_value result = nullptr;
|
|
NAPI_CALL(env_, napi_get_boolean(env_, flag, &result));
|
|
return result;
|
|
}
|
|
|
|
napi_value RationalNumber::ToString() const
|
|
{
|
|
std::string buf;
|
|
if (mnum == 0 && mden == 0) {
|
|
buf = "NaN";
|
|
} else if (mnum > 0 && mden == 0) {
|
|
buf = "Infinity";
|
|
} else if (mnum < 0 && mden == 0) {
|
|
buf = "-Infinity";
|
|
} else {
|
|
buf = std::to_string(mnum) + "/" + std::to_string(mden);
|
|
}
|
|
napi_value res = nullptr;
|
|
napi_create_string_utf8(env_, buf.c_str(), buf.size(), &res);
|
|
return res;
|
|
}
|
|
} |