Skip to content
Snippets Groups Projects
Commit fb5099ec authored by Anton Gerasimov's avatar Anton Gerasimov
Browse files

sum functions for 128 and 256

parent a51077b4
No related branches found
No related tags found
1 merge request!419Feature 5220
Pipeline #7616 passed with stage
in 5 seconds
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "dap_common.h" #include "dap_common.h"#include <boost/multiprecision/cpp_int.hpp>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <iostream>
#include <fstream>
typedef struct unsign128_t {
uint64_t hi;
uint64_t lo;
} unsign128_t;
typedef struct unsign256_t {
unsign128_t hi;
unsign128_t lo;
} unsign256_t;
const unsign128_t two_power_64={ .hi = 1, .lo = 0};
const uint64_t lo_32=0xffffffff;
const uint64_t hi_32=0xffffffff00000000;
const uint64_t ones_64=0xffffffffffffffff;
#if defined(__GNUC__) || defined (__clang__)
#if __SIZEOF_INT128__ == 16 static inline int SUM_64_64(uint64_t a_64_bit,uint64_t b_64_bit,uint64_t* c_64_bit ) {
#define DAP_GLOBAL_IS_INT128 int overflow_flag;
typedef __int128 _dap_int128_t; *c_64_bit=a_64_bit+b_64_bit;
overflow_flag=(*c_64_bit<a_64_bit);
return overflow_flag;}
#if !defined (int128_t) //!!!!This function returns void because THERE CANNOT BE OVERFLOW IN A (64,64)->128 SUM!!!!
typedef __int128 int128_t; static inline void SUM_64_128(uint64_t a_64_bit,uint64_t b_64_bit,unsign128_t* c_128_bit ) {
#endif int overflow_flag;
c_128_bit->lo=a_64_bit+b_64_bit;
c_128_bit->hi=(c_128_bit->lo<a_64_bit);}
#if !defined (uint128_t) //Mixed precision: add a uint64_t into a unsign128_t
typedef unsigned __int128 uint128_t; static inline int ADD_64_INTO_128(uint64_t a_64_bit,unsign128_t* c_128_bit ) {
#endif int overflow_flag;
uint64_t overflow_64;
uint64_t temp;
temp=c_128_bit->lo;
overflow_flag=SUM_64_64(a_64_bit,temp,&c_128_bit->lo);
overflow_64=overflow_flag;
temp=c_128_bit->hi;
overflow_flag=SUM_64_64(overflow_64,temp,&c_128_bit->hi);
return overflow_flag;}
static inline int SUM_128_128(unsign128_t a_128_bit,unsign128_t b_128_bit,unsign128_t* c_128_bit){
int overflow_flag;
overflow_flag=SUM_64_64(a_128_bit.lo,b_128_bit.lo,&c_128_bit->lo);
uint64_t carry_in_64=overflow_flag;
uint64_t intermediate_value=0;
overflow_flag=0;
overflow_flag=SUM_64_64(a_128_bit.hi,b_128_bit.hi,&intermediate_value);
carry_in_64=overflow_flag;
overflow_flag=0;
overflow_flag=SUM_64_64(carry_in_64,intermediate_value,&c_128_bit->hi);
return overflow_flag;}
#else // __SIZEOF_INT128__ == 16
typedef union uint128 {
uint64_t u64[2];
uint32_t u32[4];
} uint128_t;
typedef union int128 { static inline int SUM_256_256(unsign256_t a_256_bit,unsign256_t b_256_bit,unsign256_t* c_256_bit){
int64_t i64[2]; int overflow_flag;
int32_t i32[4]; overflow_flag=SUM_128_128(a_256_bit.lo,b_256_bit.lo,&c_256_bit->lo);
} int128_t; unsign128_t carry_in_128;
carry_in_128.hi=0;
carry_in_128.lo=overflow_flag;
unsign128_t intermediate_value;
intermediate_value.hi=0;
intermediate_value.lo=0;
overflow_flag=0;
overflow_flag=SUM_128_128(carry_in_128,a_256_bit.hi,&intermediate_value);
//we store overflow_flag in case there is already overflow
int overflow_flag_bis=0;
overflow_flag_bis=SUM_128_128(intermediate_value,b_256_bit.hi,&c_256_bit->hi);
overflow_flag=overflow_flag||overflow_flag_bis;
return overflow_flag;}
typedef int128_t _dap_int128_t;
#endif // __SIZEOF_INT128__ == 16
#endif //defined(__GNUC__) || defined (__clang__)
uint128_t dap_uint128_substract(uint128_t a, uint128_t b);
uint128_t dap_uint128_add(uint128_t a, uint128_t b);
bool dap_uint128_check_equal(uint128_t a, uint128_t b);
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Ltd. https://demlabs.net
* Copyright (c) 2021
* All rights reserved.
This file is part of DAP SDK the open source project
DAP SDK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP SDK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dap_math_ops.h"
#define LOG_TAG "dap_math_ops"
/**
* @brief dap_chain_balance_substract
* @param a
* @param b
* @return
*/
uint128_t dap_uint128_substract(uint128_t a, uint128_t b)
{
#ifdef DAP_GLOBAL_IS_INT128
if (a < b) {
log_it(L_WARNING, "Substract result overflow");
return 0;
}
return a - b;
#else
uint128_t l_ret = {};
if (a.u64[0] < b.u64[0] || (a.u64[0] == b.u64[0] && a.u64[1] < b.u64[1])) {
log_it(L_WARNING, "Substract result overflow");
return l_ret;
}
l_ret.u64[0] = a.u64[0] - b.u64[0];
l_ret.u64[1] = a.u64[1] - b.u64[1];
if (a.u64[1] < b.u64[1])
l_ret.u64[0]--;
return l_ret;
#endif
}
/**
* @brief dap_chain_balance_add
* @param a
* @param b
* @return
*/
uint128_t dap_uint128_add(uint128_t a, uint128_t b)
{
#ifdef DAP_GLOBAL_IS_INT128
uint128_t l_ret = a + b;
if (l_ret < a || l_ret < b) {
log_it(L_WARNING, "Sum result overflow");
return 0;
}
#else
uint128_t l_ret = {};
l_ret.u64[0] = a.u64[0] + b.u64[0];
l_ret.u64[1] = a.u64[1] + b.u64[1];
if (l_ret.u64[1] < a.u64[1] || l_ret.u64[1] < b.u64[1])
l_ret.u64[0]++;
if (l_ret.u64[0] < a.u64[0] || l_ret.u64[0] < b.u64[0]) {
log_it(L_WARNING, "Sum result overflow");
uint128_t l_nul = {};
return l_nul;
}
#endif
return l_ret;
}
/**
* @brief dap_uint128_check_equal
* @param a
* @param b
* @return
*/
bool dap_uint128_check_equal(uint128_t a, uint128_t b)
{
#ifdef DAP_GLOBAL_IS_INT128
return a == b;
#else
return a.u64[0]==b.u64[0] && a.u64[1]==b.u64[1];
#endif
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment