mirror of
https://github.com/Z3Prover/z3
synced 2026-03-20 20:05:51 +00:00
234 lines
No EOL
7.3 KiB
C++
234 lines
No EOL
7.3 KiB
C++
/*++
|
|
Copyright (c) 2025 Daily Test Coverage Improver
|
|
|
|
Module Name:
|
|
|
|
api_algebraic.cpp
|
|
|
|
Abstract:
|
|
|
|
Test API algebraic number functions
|
|
|
|
Author:
|
|
|
|
Daily Test Coverage Improver 2025-09-16
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
#include "api/z3.h"
|
|
#include "util/trace.h"
|
|
#include "util/rational.h"
|
|
|
|
void tst_api_algebraic() {
|
|
Z3_config cfg = Z3_mk_config();
|
|
Z3_set_param_value(cfg, "model", "true");
|
|
Z3_context ctx = Z3_mk_context(cfg);
|
|
Z3_del_config(cfg);
|
|
|
|
// Test Z3_algebraic_is_value with rational numbers
|
|
{
|
|
Z3_ast zero = Z3_mk_real(ctx, 0, 1);
|
|
Z3_ast one = Z3_mk_real(ctx, 1, 1);
|
|
Z3_ast negative_one = Z3_mk_real(ctx, -1, 1);
|
|
Z3_ast half = Z3_mk_real(ctx, 1, 2);
|
|
|
|
ENSURE(Z3_algebraic_is_value(ctx, zero));
|
|
ENSURE(Z3_algebraic_is_value(ctx, one));
|
|
ENSURE(Z3_algebraic_is_value(ctx, negative_one));
|
|
ENSURE(Z3_algebraic_is_value(ctx, half));
|
|
}
|
|
|
|
// Test Z3_algebraic_is_value with non-algebraic values
|
|
{
|
|
Z3_symbol x_sym = Z3_mk_string_symbol(ctx, "x");
|
|
Z3_sort real_sort = Z3_mk_real_sort(ctx);
|
|
Z3_ast x = Z3_mk_const(ctx, x_sym, real_sort);
|
|
|
|
// Variable should not be an algebraic value
|
|
ENSURE(!Z3_algebraic_is_value(ctx, x));
|
|
}
|
|
|
|
// Test Z3_algebraic_is_zero, Z3_algebraic_is_pos, Z3_algebraic_is_neg
|
|
{
|
|
Z3_ast zero = Z3_mk_real(ctx, 0, 1);
|
|
Z3_ast positive = Z3_mk_real(ctx, 5, 1);
|
|
Z3_ast negative = Z3_mk_real(ctx, -3, 1);
|
|
|
|
ENSURE(Z3_algebraic_is_zero(ctx, zero));
|
|
ENSURE(!Z3_algebraic_is_pos(ctx, zero));
|
|
ENSURE(!Z3_algebraic_is_neg(ctx, zero));
|
|
|
|
ENSURE(!Z3_algebraic_is_zero(ctx, positive));
|
|
ENSURE(Z3_algebraic_is_pos(ctx, positive));
|
|
ENSURE(!Z3_algebraic_is_neg(ctx, positive));
|
|
|
|
ENSURE(!Z3_algebraic_is_zero(ctx, negative));
|
|
ENSURE(!Z3_algebraic_is_pos(ctx, negative));
|
|
ENSURE(Z3_algebraic_is_neg(ctx, negative));
|
|
}
|
|
|
|
// Test Z3_algebraic_sign
|
|
{
|
|
Z3_ast zero = Z3_mk_real(ctx, 0, 1);
|
|
Z3_ast positive = Z3_mk_real(ctx, 7, 1);
|
|
Z3_ast negative = Z3_mk_real(ctx, -4, 1);
|
|
|
|
ENSURE(Z3_algebraic_sign(ctx, zero) == 0);
|
|
ENSURE(Z3_algebraic_sign(ctx, positive) > 0);
|
|
ENSURE(Z3_algebraic_sign(ctx, negative) < 0);
|
|
}
|
|
|
|
// Test Z3_algebraic_add
|
|
{
|
|
Z3_ast two = Z3_mk_real(ctx, 2, 1);
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast five = Z3_mk_real(ctx, 5, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_add(ctx, two, three);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, five));
|
|
}
|
|
|
|
// Test Z3_algebraic_sub
|
|
{
|
|
Z3_ast seven = Z3_mk_real(ctx, 7, 1);
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast four = Z3_mk_real(ctx, 4, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_sub(ctx, seven, three);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, four));
|
|
}
|
|
|
|
// Test Z3_algebraic_mul
|
|
{
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast four = Z3_mk_real(ctx, 4, 1);
|
|
Z3_ast twelve = Z3_mk_real(ctx, 12, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_mul(ctx, three, four);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, twelve));
|
|
}
|
|
|
|
// Test Z3_algebraic_div
|
|
{
|
|
Z3_ast twelve = Z3_mk_real(ctx, 12, 1);
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast four = Z3_mk_real(ctx, 4, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_div(ctx, twelve, three);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, four));
|
|
}
|
|
|
|
// Test Z3_algebraic_power
|
|
{
|
|
Z3_ast two = Z3_mk_real(ctx, 2, 1);
|
|
Z3_ast eight = Z3_mk_real(ctx, 8, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_power(ctx, two, 3);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, eight));
|
|
}
|
|
|
|
// Test comparison functions: Z3_algebraic_lt, Z3_algebraic_le, Z3_algebraic_gt, Z3_algebraic_ge
|
|
{
|
|
Z3_ast two = Z3_mk_real(ctx, 2, 1);
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast also_three = Z3_mk_real(ctx, 3, 1);
|
|
|
|
// Less than
|
|
ENSURE(Z3_algebraic_lt(ctx, two, three));
|
|
ENSURE(!Z3_algebraic_lt(ctx, three, two));
|
|
ENSURE(!Z3_algebraic_lt(ctx, three, also_three));
|
|
|
|
// Less than or equal
|
|
ENSURE(Z3_algebraic_le(ctx, two, three));
|
|
ENSURE(!Z3_algebraic_le(ctx, three, two));
|
|
ENSURE(Z3_algebraic_le(ctx, three, also_three));
|
|
|
|
// Greater than
|
|
ENSURE(!Z3_algebraic_gt(ctx, two, three));
|
|
ENSURE(Z3_algebraic_gt(ctx, three, two));
|
|
ENSURE(!Z3_algebraic_gt(ctx, three, also_three));
|
|
|
|
// Greater than or equal
|
|
ENSURE(!Z3_algebraic_ge(ctx, two, three));
|
|
ENSURE(Z3_algebraic_ge(ctx, three, two));
|
|
ENSURE(Z3_algebraic_ge(ctx, three, also_three));
|
|
}
|
|
|
|
// Test equality and inequality: Z3_algebraic_eq, Z3_algebraic_neq
|
|
{
|
|
Z3_ast two = Z3_mk_real(ctx, 2, 1);
|
|
Z3_ast three = Z3_mk_real(ctx, 3, 1);
|
|
Z3_ast also_two = Z3_mk_real(ctx, 2, 1);
|
|
|
|
// Equality
|
|
ENSURE(Z3_algebraic_eq(ctx, two, also_two));
|
|
ENSURE(!Z3_algebraic_eq(ctx, two, three));
|
|
|
|
// Inequality
|
|
ENSURE(!Z3_algebraic_neq(ctx, two, also_two));
|
|
ENSURE(Z3_algebraic_neq(ctx, two, three));
|
|
}
|
|
|
|
// Test Z3_algebraic_root
|
|
{
|
|
Z3_ast four = Z3_mk_real(ctx, 4, 1);
|
|
Z3_ast two = Z3_mk_real(ctx, 2, 1);
|
|
|
|
Z3_ast result = Z3_algebraic_root(ctx, four, 2); // Square root of 4
|
|
ENSURE(Z3_algebraic_eq(ctx, result, two));
|
|
}
|
|
|
|
// Test with negative numbers and fractions
|
|
{
|
|
Z3_ast neg_half = Z3_mk_real(ctx, -1, 2);
|
|
Z3_ast quarter = Z3_mk_real(ctx, 1, 4);
|
|
Z3_ast neg_quarter = Z3_mk_real(ctx, -1, 4);
|
|
|
|
ENSURE(Z3_algebraic_is_value(ctx, neg_half));
|
|
ENSURE(Z3_algebraic_is_neg(ctx, neg_half));
|
|
ENSURE(Z3_algebraic_is_pos(ctx, quarter));
|
|
|
|
Z3_ast result = Z3_algebraic_add(ctx, neg_half, quarter);
|
|
ENSURE(Z3_algebraic_eq(ctx, result, neg_quarter));
|
|
}
|
|
|
|
// Test Z3_algebraic_eval: evaluate the sign of a polynomial at algebraic values.
|
|
// The mutation swapped "r > 0" with "r < 0", so tests must distinguish positive
|
|
// from negative results.
|
|
//
|
|
// Polynomial p(x0) = x0 - 2. Built using a free variable (de Bruijn index 0).
|
|
// p(3) = 1 > 0 → should return 1
|
|
// p(1) = -1 < 0 → should return -1
|
|
// p(2) = 0 = 0 → should return 0
|
|
{
|
|
Z3_sort real_sort = Z3_mk_real_sort(ctx);
|
|
|
|
// x0 is the free variable at de Bruijn index 0.
|
|
Z3_ast x0 = Z3_mk_bound(ctx, 0, real_sort);
|
|
Z3_ast c2 = Z3_mk_real(ctx, 2, 1);
|
|
Z3_ast poly_args[2] = { x0, c2 };
|
|
// p = x0 - 2
|
|
Z3_ast poly = Z3_mk_sub(ctx, 2, poly_args);
|
|
|
|
// Evaluate at 3: p(3) = 1 > 0 → +1
|
|
Z3_ast val3 = Z3_mk_real(ctx, 3, 1);
|
|
ENSURE(Z3_algebraic_is_value(ctx, val3));
|
|
int sign3 = Z3_algebraic_eval(ctx, poly, 1, &val3);
|
|
ENSURE(sign3 == 1);
|
|
|
|
// Evaluate at 1: p(1) = -1 < 0 → -1
|
|
Z3_ast val1 = Z3_mk_real(ctx, 1, 1);
|
|
ENSURE(Z3_algebraic_is_value(ctx, val1));
|
|
int sign1 = Z3_algebraic_eval(ctx, poly, 1, &val1);
|
|
ENSURE(sign1 == -1);
|
|
|
|
// Evaluate at 2: p(2) = 0 → 0
|
|
Z3_ast val2 = Z3_mk_real(ctx, 2, 1);
|
|
ENSURE(Z3_algebraic_is_value(ctx, val2));
|
|
int sign2 = Z3_algebraic_eval(ctx, poly, 1, &val2);
|
|
ENSURE(sign2 == 0);
|
|
}
|
|
|
|
Z3_del_context(ctx);
|
|
} |