pcbnew: Allow tuning length to be longer than INT_MAX

The INT_MAX limit for most elements makes sense only for single-segment,
straight line elements.  For elements that accumulate lengths, we should
utilize the long long int (64 bits) to allow for greater lengths.

Fixes: lp:1842367
* https://bugs.launchpad.net/kicad/+bug/1842367
This commit is contained in:
Seth Hillbrand 2019-09-03 16:38:58 -07:00
parent 8bbbc66e46
commit c8a6878eb8
17 changed files with 74 additions and 90 deletions

View File

@ -124,7 +124,14 @@ double To_User_Unit( EDA_UNITS_T aUnit, double aValue, bool aUseMils )
// A lower-precision (for readability) version of StringFromValue()
wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils )
{
return MessageTextFromValue( aUnits, (double) aValue, aUseMils );
return MessageTextFromValue( aUnits, double( aValue ), aUseMils );
}
// A lower-precision (for readability) version of StringFromValue()
wxString MessageTextFromValue( EDA_UNITS_T aUnits, long long int aValue, bool aUseMils )
{
return MessageTextFromValue( aUnits, double( aValue ), aUseMils );
}
@ -207,7 +214,7 @@ void StripTrailingZeros( wxString& aStringValue, unsigned aTrailingZeroAllowed )
* otherwise the actual value is rounded when read from dialog and converted
* in internal units, and therefore modified.
*/
wxString StringFromValue( EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils )
wxString StringFromValue( EDA_UNITS_T aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils )
{
double value_to_print = To_User_Unit( aUnits, aValue, aUseMils );
@ -411,10 +418,10 @@ void FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS_T& aUnits, bool
}
int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils )
long long int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils )
{
double value = DoubleValueFromString( aUnits, aTextValue, aUseMils );
return KiROUND( value );
return KiROUND<double, long long int>( value );
}

View File

@ -100,9 +100,9 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
}
int SHAPE_LINE_CHAIN::Length() const
long long int SHAPE_LINE_CHAIN::Length() const
{
int l = 0;
long long int l = 0;
for( int i = 0; i < SegmentCount(); i++ )
l += CSegment( i ).Length();

View File

@ -123,7 +123,7 @@ void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
}
bool UNIT_BINDER::Validate( int aMin, int aMax, bool setFocusOnError )
bool UNIT_BINDER::Validate( long long int aMin, long long int aMax, bool setFocusOnError )
{
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
@ -212,7 +212,7 @@ void UNIT_BINDER::ChangeValue( wxString aValue )
}
int UNIT_BINDER::GetValue()
long long int UNIT_BINDER::GetValue()
{
auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
auto staticText = dynamic_cast<wxStaticText*>( m_value );

View File

@ -112,6 +112,8 @@ wxString MessageTextFromValue( EDA_UNITS_T aUnits, double aValue, bool aUseMils
wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils = false );
wxString MessageTextFromValue( EDA_UNITS_T aUnits, long long int aValue, bool aUseMils = false );
/**
* Function StringFromValue
* returns the string from \a aValue according to units (inch, mm ...) for display,
@ -132,8 +134,8 @@ wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils = f
* @param aUseMils Indicates mils should be used for imperial units (inches).
* @return A wxString object containing value and optionally the symbol unit (like 2.000 mm)
*/
wxString StringFromValue( EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol = false,
bool aUseMils = false );
wxString StringFromValue(
EDA_UNITS_T aUnit, double aValue, bool aAddUnitSymbol = false, bool aUseMils = false );
/**
* Return in internal units the value "val" given in a real unit
@ -162,7 +164,8 @@ double DoubleValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue,
* @param aUseMils Indicates mils should be used for imperial units (inches).
* @return The string from Value, according to units (inch, mm ...) for display,
*/
int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils = false );
long long int ValueFromString(
EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils = false );
/**
* Function FetchUnitsFromString

View File

@ -43,7 +43,9 @@
#include <gal/color4d.h>
#include <atomic>
#include <limits>
#include <memory>
#include <type_traits>
class wxAboutDialogInfo;
class SEARCH_STACK;
@ -105,49 +107,20 @@ enum pseudokeys {
/**
* Round a floating point number to an integer using "round halfway cases away from zero".
*
* In Debug build an assert fires if will not fit into an int.
* In Debug build an assert fires if will not fit into the return type.
*/
#if !defined( DEBUG )
/// KiROUND: a function so v is not evaluated twice. Unfortunately, compiler
/// is unable to pre-compute constants using this.
static inline int KiROUND( double v )
template <typename fp_type, typename ret_type = int>
constexpr ret_type KiROUND( fp_type v )
{
return int( v < 0 ? v - 0.5 : v + 0.5 );
using max_ret = long long int;
fp_type ret = v < 0 ? v - 0.5 : v + 0.5;
wxASSERT( ret <= std::numeric_limits<ret_type>::max()
&& ret >= std::numeric_limits<ret_type>::lowest() );
return ret_type( max_ret( ret ) );
}
/// KIROUND: a macro so compiler can pre-compute constants. Use this with compile
/// time constants rather than the inline function above.
#define KIROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#else
// DEBUG: KiROUND() is a macro to capture line and file, then calls this inline
static inline int kiRound_( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n",
__FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n",
__FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) kiRound_( v, __LINE__, __FILE__ )
// in Debug build, use the overflow catcher since code size is immaterial
#define KIROUND( v ) KiROUND( v )
#endif
//-----</KiROUND KIT>-----------------------------------------------------------

View File

@ -364,7 +364,7 @@ public:
* Returns length of the line chain in Euclidean metric.
* @return length of the line chain
*/
int Length() const;
long long int Length() const;
/**
* Function Append()

View File

@ -85,7 +85,7 @@ public:
* Function GetValue
* Returns the current value in Internal Units.
*/
virtual int GetValue();
virtual long long int GetValue();
/**
* Function IsIndeterminate
@ -102,7 +102,7 @@ public:
* @param aMax a maximum value (in internal units) for validation
* @return false on error.
*/
virtual bool Validate( int aMin, int aMax, bool setFocusOnError = true );
virtual bool Validate( long long int aMin, long long int aMax, bool setFocusOnError = true );
void SetLabel( const wxString& aLabel );

View File

@ -107,13 +107,13 @@ bool DIALOG_PNS_LENGTH_TUNING_SETTINGS::TransferDataToWindow()
bool DIALOG_PNS_LENGTH_TUNING_SETTINGS::AcceptOptions( )
{
if( !m_minAmpl.Validate( 0, INT_MAX ) )
if( !m_minAmpl.Validate( 0, std::numeric_limits<int>::max() ) )
return false;
if( !m_maxAmpl.Validate( m_minAmpl.GetValue(), INT_MAX ) )
if( !m_maxAmpl.Validate( m_minAmpl.GetValue(), std::numeric_limits<int>::max() ) )
return false;
if( !m_spacing.Validate( 0, INT_MAX ) )
if( !m_spacing.Validate( 0, std::numeric_limits<int>::max() ) )
return false;
if( !m_targetLength.Validate( 0, INT_MAX ) )
if( !m_targetLength.Validate( 0, std::numeric_limits<long long int>::max() ) )
return false;
if( !m_radius.Validate( 0, 100 ) )
return false;

View File

@ -119,10 +119,10 @@ void DP_MEANDER_PLACER::release()
}
int DP_MEANDER_PLACER::origPathLength() const
long long int DP_MEANDER_PLACER::origPathLength() const
{
int totalP = 0;
int totalN = 0;
long long int totalP = 0;
long long int totalN = 0;
for( const ITEM* item : m_tunedPathP.CItems() )
{
@ -243,7 +243,7 @@ bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
while( curIndexN < tunedN.PointCount() )
m_result.AddCorner( tunedP.CPoint( -1 ), tunedN.CPoint( curIndexN++ ) );
int dpLen = origPathLength();
long long int dpLen = origPathLength();
m_lastStatus = TUNED;

View File

@ -98,7 +98,7 @@ public:
int CurrentLayer() const override;
int totalLength();
long long int totalLength();
const wxString TuningInfo( EDA_UNITS_T aUnits ) const override;
TUNING_STATUS TuningStatus() const override;
@ -120,7 +120,7 @@ private:
void setWorld( NODE* aWorld );
void release();
int origPathLength() const;
long long int origPathLength() const;
///> pointer to world to search colliding items
NODE* m_world;
@ -141,7 +141,7 @@ private:
MEANDERED_LINE m_result;
SEGMENT* m_initialSegment;
int m_lastLength;
long long int m_lastLength;
TUNING_STATUS m_lastStatus;
};

View File

@ -80,8 +80,8 @@ public:
int m_spacing;
///> amplitude/spacing adjustment step
int m_step;
///> desired length of the tuned line/diff pair
int m_targetLength;
///> desired length of the tuned line/diff pair (this is in nm, so allow more than board width)
long long int m_targetLength;
///> type of corners for the meandered line
MEANDER_STYLE m_cornerStyle;
///> rounding percentage (0 - 100)

View File

@ -89,9 +89,9 @@ bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
}
int MEANDER_PLACER::origPathLength() const
long long int MEANDER_PLACER::origPathLength() const
{
int total = 0;
long long int total = 0;
for( const ITEM* item : m_tunedPath.CItems() )
{
if( const LINE* l = dyn_cast<const LINE*>( item ) )
@ -110,7 +110,7 @@ bool MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
}
bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLength )
bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int aTargetLength )
{
SHAPE_LINE_CHAIN pre, tuned, post;
@ -133,7 +133,7 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLeng
m_result.AddCorner( s.B );
}
int lineLen = origPathLength();
long long int lineLen = origPathLength();
m_lastLength = lineLen;
m_lastStatus = TUNED;

View File

@ -89,12 +89,11 @@ public:
bool CheckFit ( MEANDER_SHAPE* aShape ) override;
protected:
bool doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLength );
bool doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int aTargetLength );
void setWorld( NODE* aWorld );
virtual int origPathLength() const;
virtual long long int origPathLength() const;
///> pointer to world to search colliding items
NODE* m_world;
@ -113,7 +112,7 @@ protected:
MEANDERED_LINE m_result;
SEGMENT* m_initialSegment;
int m_lastLength;
long long int m_lastLength;
TUNING_STATUS m_lastStatus;
};

View File

@ -106,9 +106,9 @@ void MEANDER_PLACER_BASE::cutTunedLine( const SHAPE_LINE_CHAIN& aOrigin,
}
void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongation )
void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation )
{
int remaining = aElongation;
long long int remaining = aElongation;
bool finished = false;
for( MEANDER_SHAPE* m : aTuned.Meanders() )
@ -155,7 +155,7 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongatio
}
}
int balance = 0;
long long int balance = 0;
if( meanderCount )
balance = -remaining / meanderCount;
@ -166,7 +166,8 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongatio
{
if( m->Type() != MT_CORNER && m->Type() != MT_EMPTY )
{
m->Resize( std::max( m->Amplitude() - balance / 2, m_settings.m_minAmplitude ) );
m->Resize( std::max( m->Amplitude() - balance / 2,
(long long int) ( m_settings.m_minAmplitude ) ) );
}
}
}
@ -179,7 +180,8 @@ const MEANDER_SETTINGS& MEANDER_PLACER_BASE::MeanderSettings() const
}
int MEANDER_PLACER_BASE::compareWithTolerance( int aValue, int aExpected, int aTolerance ) const
int MEANDER_PLACER_BASE::compareWithTolerance(
long long int aValue, long long int aExpected, long long int aTolerance ) const
{
if( aValue < aExpected - aTolerance )
return -1;

View File

@ -147,14 +147,15 @@ protected:
* Takes a set of meanders in aTuned and tunes their length to
* extend the original line length by aElongation.
*/
void tuneLineLength( MEANDERED_LINE& aTuned, int aElongation );
void tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation );
/**
* Function compareWithTolerance()
*
* Compares aValue against aExpected with given tolerance.
*/
int compareWithTolerance ( int aValue, int aExpected, int aTolerance = 0 ) const;
int compareWithTolerance(
long long int aValue, long long int aExpected, long long int aTolerance = 0 ) const;
///> width of the meandered trace(s)
int m_currentWidth;

View File

@ -99,15 +99,15 @@ bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
}
int MEANDER_SKEW_PLACER::origPathLength( ) const
long long int MEANDER_SKEW_PLACER::origPathLength() const
{
return itemsetLength ( m_tunedPath );
}
int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const
long long int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const
{
int total = 0;
long long int total = 0;
for( const ITEM* item : aSet.CItems() )
{
if( const LINE* l = dyn_cast<const LINE*>( item ) )
@ -120,7 +120,7 @@ int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const
}
int MEANDER_SKEW_PLACER::currentSkew() const
long long int MEANDER_SKEW_PLACER::currentSkew() const
{
return m_lastLength - m_coupledLength;
}

View File

@ -52,16 +52,15 @@ public:
const wxString TuningInfo( EDA_UNITS_T aUnits ) const override;
private:
long long int currentSkew() const;
long long int itemsetLength( const ITEM_SET& aSet ) const;
int currentSkew( ) const;
int itemsetLength( const ITEM_SET& aSet ) const;
int origPathLength () const override;
long long int origPathLength() const override;
DIFF_PAIR m_originPair;
ITEM_SET m_tunedPath, m_tunedPathP, m_tunedPathN;
int m_coupledLength;
long long int m_coupledLength;
};
}