blob: 2726fa194824334e0c152ebfc1638ba315b8e69e [file] [log] [blame]
/*
* Copyright (c) 2014, STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "testframework.h"
#define DIV(s, t, out) \
do { \
TEE_BigIntConvertFromString(n, (s)); \
TEE_BigIntConvertFromString(d, (t)); \
TEE_BigIntDiv(q, r, n, d); \
TB_ASSERT_HEX_PRINT_VALUE(q, (out), 0); \
if (TEE_BigIntCmpS32(d, 0) > 0) \
TB_ASSERT_BIGINT_LESS(r, d); \
} while (0)
#define SELF_VERIFY_DIV(s, t) \
do { \
TEE_BigIntConvertFromString(n, (s)); \
TEE_BigIntConvertFromString(d, (t)); \
TEE_BigIntDiv(q, r, n, d); \
if (TEE_BigIntCmpS32(d, 0) > 0) \
TB_ASSERT_BIGINT_LESS(r, d); \
TEE_BigIntMul(v, q, d); \
TEE_BigIntAdd(v, v, r); \
TB_ASSERT_BIGINT_EQ(n, v); \
} while (0)
static void test_div_basic(void)
{
TB_INFO(" Testing basic cases");
DEF_BIGINT(n, 2048);
DEF_BIGINT(d, 2048);
DEF_BIGINT(q, 2048);
DEF_BIGINT(r, 2048);
DEF_BIGINT(v, 2048);
SELF_VERIFY_DIV("8111_1110_0000_0001_12345678", "8000000012345678");
DIV("0", "1", "0");
DIV("1", "1", "1");
DIV("b7fb", "5", "24CB");
DIV("124378912734891273894712890347102358129034789120374",
"1984086C15FA011154C86FA68", "B73D14EC7205D3311F6E78411D");
SELF_VERIFY_DIV("124378912734891273894712890347102358129034789120374",
"1984086C15FA011154C86FA68");
SELF_VERIFY_DIV("-124378912734891273894712890347102358129034789120374",
"1984086C15FA011154C86FA68");
SELF_VERIFY_DIV("124378912734891273894712890347102358129034789120374",
"-1984086C15FA011154C86FA68");
SELF_VERIFY_DIV("-124378912734891273894712890347102358129034789120374",
"-1984086C15FA011154C86FA68");
SELF_VERIFY_DIV("12345678", "10");
SELF_VERIFY_DIV("-12345678", "10");
SELF_VERIFY_DIV("12345678", "-10");
SELF_VERIFY_DIV("-12345678", "-10");
SELF_VERIFY_DIV("12345678901234567890123456789012345678901", "10");
SELF_VERIFY_DIV("1234567890123456789012345678901234567890", "10");
SELF_VERIFY_DIV("123456789012345678901234567890123456789", "10");
DEL_BIGINT(n);
DEL_BIGINT(d);
DEL_BIGINT(q);
DEL_BIGINT(r);
DEL_BIGINT(v);
}
static void test_div_random(void)
{
int i;
char str[MAX_RAND_STRING_SIZE];
TB_INFO(" Testing random divisions");
DEF_BIGINT(n, 2048);
DEF_BIGINT(d, 2048);
DEF_BIGINT(q, 2048);
DEF_BIGINT(r, 2048);
DEF_BIGINT(v, 2048);
for (i = 0; i < 10000; i++) {
tb_set_random_value(n, str, 1);
/* don't divide by zero */
do {
tb_set_random_value(d, str, 1);
} while (TEE_BigIntCmpS32(d, 0) == 0);
TEE_BigIntDiv(q, r, n, d);
TEE_BigIntMul(v, q, d);
TEE_BigIntAdd(v, v, r);
TB_ASSERT_BIGINT_EQ(n, v);
if (TEE_BigIntCmpS32(d, 0) > 0)
TB_ASSERT_BIGINT_LESS(r, d);
}
DEL_BIGINT(n);
DEL_BIGINT(d);
DEL_BIGINT(q);
DEL_BIGINT(r);
DEL_BIGINT(v);
}
#define CMP_EQUAL ==
#define CMP_LARGER >
#define CMP_SMALLER <
#define DIV_CHECK_SIGN(sn, sd, cmpq, cmpr) \
do {\
SELF_VERIFY_DIV(sn, sd); \
TEE_BigIntConvertFromString(n, (sn)); \
TEE_BigIntConvertFromString(d, (sd)); \
TEE_BigIntDiv(q, r, n, d); \
TB_ASSERT_MSG(TEE_BigIntCmpS32(q, 0) cmpq 0, "q has wrong sign."); \
TB_ASSERT_MSG(TEE_BigIntCmpS32(r, 0) cmpr 0, "r has wrong sign."); \
} while (0)
static void test_div_signs(void)
{
TB_INFO(" Testing signs of q and r");
DEF_BIGINT(n, 2048);
DEF_BIGINT(d, 2048);
DEF_BIGINT(q, 2048);
DEF_BIGINT(r, 2048);
DEF_BIGINT(v, 2048);
DIV_CHECK_SIGN("53", "7", CMP_LARGER, CMP_LARGER);
DIV_CHECK_SIGN("-53", "7", CMP_SMALLER, CMP_SMALLER);
DIV_CHECK_SIGN("53", "-7", CMP_SMALLER, CMP_LARGER);
DIV_CHECK_SIGN("-53", "-7", CMP_LARGER, CMP_SMALLER);
DIV_CHECK_SIGN("123456789abcdef123456789abcdef", "fedcba98765432100",
CMP_LARGER, CMP_LARGER);
DIV_CHECK_SIGN("-123456789abcdef123456789abcdef", "fedcba98765432100",
CMP_SMALLER, CMP_SMALLER);
DIV_CHECK_SIGN("123456789abcdef123456789abcdef", "-fedcba98765432100",
CMP_SMALLER, CMP_LARGER);
DIV_CHECK_SIGN("-123456789abcdef123456789abcdef", "-fedcba98765432100",
CMP_LARGER, CMP_SMALLER);
DEL_BIGINT(n);
DEL_BIGINT(d);
DEL_BIGINT(q);
DEL_BIGINT(r);
DEL_BIGINT(v);
}
void tb_div(void)
{
const char *TEST_NAME = "Division";
TB_HEADER(TEST_NAME);
test_div_basic();
test_div_random();
test_div_signs();
TB_FOOTER(TEST_NAME);
}