mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- $defined(#hash) will not check the internal expression, just that #hash exists.
- Added optional macro arguments using `macro foo(int x = ...)` which can be checked using `$defined(x)`. - Supplemental `roundeven` has a normal implementation.
This commit is contained in:
@@ -746,39 +746,39 @@ fn void* tmalloc(usz size, usz alignment = 0) @builtin @inline @nodiscard
|
||||
|
||||
<*
|
||||
@param $Type : "The type to allocate"
|
||||
@param #init : "The optional initializer"
|
||||
|
||||
@require $vacount < 2 : "Too many arguments."
|
||||
@require $vacount == 0 ||| $defined($Type a = $vaexpr[0]) : "The second argument must be an initializer for the type"
|
||||
@require !$defined(#init) ||| $defined($Type a = #init) : "#init must be an initializer for the type"
|
||||
@require $Type.alignof <= DEFAULT_MEM_ALIGNMENT : "Types with alignment exceeding the default must use 'alloc_aligned' instead"
|
||||
@return "A pointer to data of type $Type."
|
||||
*>
|
||||
macro new($Type, ...) @nodiscard
|
||||
macro new($Type, #init = ...) @nodiscard @safemacro
|
||||
{
|
||||
$if $vacount == 0:
|
||||
return ($Type*)calloc($Type.sizeof);
|
||||
$else
|
||||
$if $defined(#init):
|
||||
$Type* val = malloc($Type.sizeof);
|
||||
*val = $vaexpr[0];
|
||||
*val = #init;
|
||||
return val;
|
||||
$else
|
||||
return ($Type*)calloc($Type.sizeof);
|
||||
$endif
|
||||
}
|
||||
|
||||
<*
|
||||
@param $Type : "The type to allocate"
|
||||
@param padding : "The padding to add after the allocation"
|
||||
@param #init : "The optional initializer"
|
||||
|
||||
@require $vacount < 2 : "Too many arguments."
|
||||
@require $vacount == 0 ||| $defined($Type a = $vaexpr[0]) : "The second argument must be an initializer for the type"
|
||||
@require !$defined(#init) ||| $defined($Type a = #init) : "#init must be an initializer for the type"
|
||||
@return "A pointer to data of type $Type."
|
||||
*>
|
||||
macro new_with_padding($Type, usz padding, ...) @nodiscard
|
||||
macro new_with_padding($Type, usz padding, #init = ...) @nodiscard @safemacro
|
||||
{
|
||||
$if $vacount == 0:
|
||||
return ($Type*)calloc($Type.sizeof + padding);
|
||||
$else
|
||||
$if $defined(#init):
|
||||
$Type* val = malloc($Type.sizeof + padding);
|
||||
*val = $vaexpr[0];
|
||||
*val = #init;
|
||||
return val;
|
||||
$else
|
||||
return ($Type*)calloc($Type.sizeof + padding);
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -787,19 +787,19 @@ macro new_with_padding($Type, usz padding, ...) @nodiscard
|
||||
exceeding DEFAULT_MEM_ALIGNMENT. IMPORTANT! It must be freed using free_aligned.
|
||||
|
||||
@param $Type : "The type to allocate"
|
||||
@param #init : "The optional initializer"
|
||||
|
||||
@require $vacount < 2 : "Too many arguments."
|
||||
@require $vacount == 0 ||| $defined($Type a = $vaexpr[0]) : "The second argument must be an initializer for the type"
|
||||
@require !$defined(#init) ||| $defined($Type a = #init) : "#init must be an initializer for the type"
|
||||
@return "A pointer to data of type $Type with the proper alignment"
|
||||
*>
|
||||
macro new_aligned($Type, ...) @nodiscard
|
||||
macro new_aligned($Type, #init = ...) @nodiscard @safemacro
|
||||
{
|
||||
$if $vacount == 0:
|
||||
return ($Type*)calloc_aligned($Type.sizeof, $Type.alignof);
|
||||
$else
|
||||
$if $defined(#init):
|
||||
$Type* val = malloc_aligned($Type.sizeof, $Type.alignof);
|
||||
*val = $vaexpr[0];
|
||||
*val = #init;
|
||||
return val;
|
||||
$else
|
||||
return ($Type*)calloc_aligned($Type.sizeof, $Type.alignof);
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -841,38 +841,38 @@ macro alloc_aligned($Type) @nodiscard
|
||||
|
||||
<*
|
||||
@param $Type : "The type to allocate"
|
||||
@param #init : "The optional initializer"
|
||||
|
||||
@require $vacount < 2 : "Too many arguments."
|
||||
@require $vacount == 0 ||| $defined($Type a = $vaexpr[0]) : "The second argument must be an initializer for the type"
|
||||
@require !$defined(#init) ||| $defined($Type a = #init) : "#init must be an initializer for the type"
|
||||
@return "A pointer to temporary data of type $Type."
|
||||
*>
|
||||
macro tnew($Type, ...) @nodiscard
|
||||
macro tnew($Type, #init = ...) @nodiscard @safemacro
|
||||
{
|
||||
$if $vacount == 0:
|
||||
return ($Type*)tcalloc($Type.sizeof, $Type.alignof) @inline;
|
||||
$else
|
||||
$if $defined(#init):
|
||||
$Type* val = tmalloc($Type.sizeof, $Type.alignof) @inline;
|
||||
*val = $vaexpr[0];
|
||||
*val = #init;
|
||||
return val;
|
||||
$else
|
||||
return ($Type*)tcalloc($Type.sizeof, $Type.alignof) @inline;
|
||||
$endif
|
||||
}
|
||||
|
||||
<*
|
||||
@param $Type : "The type to allocate"
|
||||
@param padding : "The padding to add after the allocation"
|
||||
@param #init : "The optional initializer"
|
||||
|
||||
@require $vacount < 2 : "Too many arguments."
|
||||
@require $vacount == 0 ||| $defined($Type a = $vaexpr[0]) : "The second argument must be an initializer for the type"
|
||||
@require !$defined(#init) ||| $defined($Type a = #init) : "#init must be an initializer for the type"
|
||||
@return "A pointer to temporary data of type $Type with added padding at the end."
|
||||
*>
|
||||
macro temp_with_padding($Type, usz padding, ...) @nodiscard
|
||||
macro temp_with_padding($Type, usz padding, #init = ...) @nodiscard @safemacro
|
||||
{
|
||||
$if $vacount == 0:
|
||||
return ($Type*)tcalloc($Type.sizeof + padding, $Type.alignof) @inline;
|
||||
$else
|
||||
$if $defined(#init):
|
||||
$Type* val = tmalloc($Type.sizeof + padding, $Type.alignof) @inline;
|
||||
*val = $vaexpr[0];
|
||||
*val = #init;
|
||||
return val;
|
||||
$else
|
||||
return ($Type*)tcalloc($Type.sizeof + padding, $Type.alignof) @inline;
|
||||
$endif
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ fn float _roundf(float x) @extern("roundf") @weak @nostrip
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (u >> 23) & 0xff;
|
||||
if (e >= 0x7f + 23) return x;
|
||||
if (u >> 31) x = -x;
|
||||
bool signed = u >> 31 != 0;
|
||||
if (signed) x = -x;
|
||||
if (e < 0x7f - 1)
|
||||
{
|
||||
force_eval_add(x, TOINTF);
|
||||
@@ -47,7 +48,7 @@ fn float _roundf(float x) @extern("roundf") @weak @nostrip
|
||||
default:
|
||||
y = y + x;
|
||||
}
|
||||
if (u >> 31) y = -y;
|
||||
if (signed) y = -y;
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,78 @@
|
||||
module std::math::math_rt;
|
||||
|
||||
fn float __roundevenf(float f) @extern("roundevenf") @weak @nostrip
|
||||
const double TOINT = 1 / math::DOUBLE_EPSILON;
|
||||
const float TOINTF = (float)(1 / math::FLOAT_EPSILON);
|
||||
macro force_eval_add(x, v)
|
||||
{
|
||||
// Slow implementation
|
||||
return math::round(f / 2) * 2;
|
||||
$typeof(x) temp @noinit;
|
||||
@volatile_store(temp, x + v);
|
||||
}
|
||||
|
||||
fn double __roundeven(double d) @extern("roundeven") @weak @nostrip
|
||||
fn double __roundeven(double x) @extern("roundeven") @weak @nostrip
|
||||
{
|
||||
// Slow implementation
|
||||
return math::round(d / 2) * 2;
|
||||
ulong u = bitcast(x, ulong);
|
||||
int e = (int)((u >> 52) & 0x7ff);
|
||||
if (e >= 0x3ff + 52) return x;
|
||||
bool signed = u >> 63 != 0;
|
||||
if (signed) x = -x;
|
||||
if (e < 0x3ff - 1)
|
||||
{
|
||||
/* raise inexact if x!=0 */
|
||||
force_eval_add(x, TOINT);
|
||||
return 0 * x;
|
||||
}
|
||||
double y = (x + TOINT) - TOINT - x;
|
||||
switch
|
||||
{
|
||||
case y > 0.5:
|
||||
y = y + x - 1;
|
||||
case y < -0.5:
|
||||
y = y + x + 1;
|
||||
case y == 0.5 || y == -0.5:
|
||||
if (u & 1)
|
||||
{
|
||||
y = x + (y > 0 ? y + 1 : y - 1);
|
||||
break;
|
||||
}
|
||||
nextcase;
|
||||
default:
|
||||
y = y + x;
|
||||
}
|
||||
if (signed) y = -y;
|
||||
return y;
|
||||
}
|
||||
|
||||
fn float __roundevenf(float x) @extern("roundevenf") @weak @nostrip
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (u >> 23) & 0xff;
|
||||
if (e >= 0x7f + 23) return x;
|
||||
bool signed = u >> 31 != 0;
|
||||
if (signed) x = -x;
|
||||
if (e < 0x7f - 1)
|
||||
{
|
||||
force_eval_add(x, TOINTF);
|
||||
return 0 * x;
|
||||
}
|
||||
float y = (x + TOINTF) - TOINTF - x;
|
||||
switch
|
||||
{
|
||||
case y > 0.5f:
|
||||
y = y + x - 1;
|
||||
case y < -0.5f:
|
||||
y = y + x + 1;
|
||||
case y == 0.5f || y == -0.5f:
|
||||
if (u & 1)
|
||||
{
|
||||
y = x + (y > 0.0f ? y + 1.0f : y - 1.0f);
|
||||
break;
|
||||
}
|
||||
nextcase;
|
||||
default:
|
||||
y = y + x;
|
||||
}
|
||||
if (signed) y = -y;
|
||||
return y;
|
||||
}
|
||||
|
||||
fn double __powidf2(double a, int b) @extern("__powidf2") @weak @nostrip
|
||||
|
||||
Reference in New Issue
Block a user